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 if (!CalleeFnDecl)
7364 return Call;
7365
7366 if (getLangOpts().OpenMP >= 50 && getLangOpts().OpenMP <= 60 &&
7367 CalleeFnDecl->getIdentifier() &&
7368 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7369 // checking for any calls inside an Order region
7371 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7372 }
7373
7374 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7375 return Call;
7376
7377 ASTContext &Context = getASTContext();
7378 std::function<void(StringRef)> DiagUnknownTrait = [this,
7379 CE](StringRef ISATrait) {
7380 // TODO Track the selector locations in a way that is accessible here to
7381 // improve the diagnostic location.
7382 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7383 << ISATrait;
7384 };
7385 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7386 SemaRef.getCurFunctionDecl(),
7387 DSAStack->getConstructTraits(), getOpenMPDeviceNum());
7388
7389 QualType CalleeFnType = CalleeFnDecl->getType();
7390
7393 while (CalleeFnDecl) {
7394 for (OMPDeclareVariantAttr *A :
7395 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7396 Expr *VariantRef = A->getVariantFuncRef();
7397
7398 VariantMatchInfo VMI;
7399 OMPTraitInfo &TI = A->getTraitInfo();
7400 TI.getAsVariantMatchInfo(Context, VMI);
7401 if (!isVariantApplicableInContext(VMI, OMPCtx,
7402 /*DeviceSetOnly=*/false))
7403 continue;
7404
7405 VMIs.push_back(VMI);
7406 Exprs.push_back(VariantRef);
7407 }
7408
7409 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7410 }
7411
7412 ExprResult NewCall;
7413 do {
7414 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7415 if (BestIdx < 0)
7416 return Call;
7417 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7418 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7419
7420 {
7421 // Try to build a (member) call expression for the current best applicable
7422 // variant expression. We allow this to fail in which case we continue
7423 // with the next best variant expression. The fail case is part of the
7424 // implementation defined behavior in the OpenMP standard when it talks
7425 // about what differences in the function prototypes: "Any differences
7426 // that the specific OpenMP context requires in the prototype of the
7427 // variant from the base function prototype are implementation defined."
7428 // This wording is there to allow the specialized variant to have a
7429 // different type than the base function. This is intended and OK but if
7430 // we cannot create a call the difference is not in the "implementation
7431 // defined range" we allow.
7433
7434 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7435 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7436 BestExpr = MemberExpr::CreateImplicit(
7437 Context, MemberCall->getImplicitObjectArgument(),
7438 /*IsArrow=*/false, SpecializedMethod, Context.BoundMemberTy,
7439 MemberCall->getValueKind(), MemberCall->getObjectKind());
7440 }
7441 NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs,
7442 RParenLoc, ExecConfig);
7443 if (NewCall.isUsable()) {
7444 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7445 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7447 CalleeFnType, NewCalleeFnDecl->getType(),
7448 /*OfBlockPointer=*/false,
7449 /*Unqualified=*/false, /*AllowCXX=*/true);
7450 if (!NewType.isNull())
7451 break;
7452 // Don't use the call if the function type was not compatible.
7453 NewCall = nullptr;
7454 }
7455 }
7456 }
7457
7458 VMIs.erase(VMIs.begin() + BestIdx);
7459 Exprs.erase(Exprs.begin() + BestIdx);
7460 } while (!VMIs.empty());
7461
7462 if (!NewCall.isUsable())
7463 return Call;
7464 return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
7465}
7466
7467std::optional<std::pair<FunctionDecl *, Expr *>>
7469 Expr *VariantRef,
7470 OMPTraitInfo &TI,
7471 unsigned NumAppendArgs,
7472 SourceRange SR) {
7473 ASTContext &Context = getASTContext();
7474 if (!DG || DG.get().isNull())
7475 return std::nullopt;
7476
7477 const int VariantId = 1;
7478 // Must be applied only to single decl.
7479 if (!DG.get().isSingleDecl()) {
7480 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7481 << VariantId << SR;
7482 return std::nullopt;
7483 }
7484 Decl *ADecl = DG.get().getSingleDecl();
7485 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7486 ADecl = FTD->getTemplatedDecl();
7487
7488 // Decl must be a function.
7489 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7490 if (!FD) {
7491 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7492 << VariantId << SR;
7493 return std::nullopt;
7494 }
7495
7496 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7497 // The 'target' attribute needs to be separately checked because it does
7498 // not always signify a multiversion function declaration.
7499 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7500 };
7501 // OpenMP is not compatible with multiversion function attributes.
7502 if (HasMultiVersionAttributes(FD)) {
7503 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7504 << SR;
7505 return std::nullopt;
7506 }
7507
7508 // Allow #pragma omp declare variant only if the function is not used.
7509 if (FD->isUsed(false))
7510 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7511 << FD->getLocation();
7512
7513 // Check if the function was emitted already.
7514 const FunctionDecl *Definition;
7515 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7516 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7517 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7518 << FD->getLocation();
7519
7520 // The VariantRef must point to function.
7521 if (!VariantRef) {
7522 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7523 return std::nullopt;
7524 }
7525
7526 auto ShouldDelayChecks = [](Expr *&E, bool) {
7527 return E && (E->isTypeDependent() || E->isValueDependent() ||
7530 };
7531 // Do not check templates, wait until instantiation.
7532 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7533 TI.anyScoreOrCondition(ShouldDelayChecks))
7534 return std::make_pair(FD, VariantRef);
7535
7536 // Deal with non-constant score and user condition expressions.
7537 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7538 bool IsScore) -> bool {
7539 if (!E || E->isIntegerConstantExpr(getASTContext()))
7540 return false;
7541
7542 if (IsScore) {
7543 // We warn on non-constant scores and pretend they were not present.
7544 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7545 << E;
7546 E = nullptr;
7547 } else {
7548 // We could replace a non-constant user condition with "false" but we
7549 // will soon need to handle these anyway for the dynamic version of
7550 // OpenMP context selectors.
7551 Diag(E->getExprLoc(),
7552 diag::err_omp_declare_variant_user_condition_not_constant)
7553 << E;
7554 }
7555 return true;
7556 };
7557 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7558 return std::nullopt;
7559
7560 QualType AdjustedFnType = FD->getType();
7561 if (NumAppendArgs) {
7562 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7563 if (!PTy) {
7564 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7565 << SR;
7566 return std::nullopt;
7567 }
7568 // Adjust the function type to account for an extra omp_interop_t for each
7569 // specified in the append_args clause.
7570 const TypeDecl *TD = nullptr;
7571 LookupResult Result(SemaRef, &Context.Idents.get("omp_interop_t"),
7573 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
7574 NamedDecl *ND = Result.getFoundDecl();
7575 TD = dyn_cast_or_null<TypeDecl>(ND);
7576 }
7577 if (!TD) {
7578 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7579 return std::nullopt;
7580 }
7581 QualType InteropType =
7582 Context.getTypeDeclType(ElaboratedTypeKeyword::None,
7583 /*Qualifier=*/std::nullopt, TD);
7584 if (PTy->isVariadic()) {
7585 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7586 return std::nullopt;
7587 }
7589 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7590 Params.insert(Params.end(), NumAppendArgs, InteropType);
7591 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7592 PTy->getExtProtoInfo());
7593 }
7594
7595 // Convert VariantRef expression to the type of the original function to
7596 // resolve possible conflicts.
7597 ExprResult VariantRefCast = VariantRef;
7598 if (getLangOpts().CPlusPlus) {
7599 QualType FnPtrType;
7600 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7601 if (Method && !Method->isStatic()) {
7602 FnPtrType = Context.getMemberPointerType(
7603 AdjustedFnType, /*Qualifier=*/std::nullopt, Method->getParent());
7604 ExprResult ER;
7605 {
7606 // Build addr_of unary op to correctly handle type checks for member
7607 // functions.
7609 ER = SemaRef.CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7610 VariantRef);
7611 }
7612 if (!ER.isUsable()) {
7613 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7614 << VariantId << VariantRef->getSourceRange();
7615 return std::nullopt;
7616 }
7617 VariantRef = ER.get();
7618 } else {
7619 FnPtrType = Context.getPointerType(AdjustedFnType);
7620 }
7621 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7622 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7623 ImplicitConversionSequence ICS = SemaRef.TryImplicitConversion(
7624 VariantRef, FnPtrType.getUnqualifiedType(),
7625 /*SuppressUserConversions=*/false, Sema::AllowedExplicit::None,
7626 /*InOverloadResolution=*/false,
7627 /*CStyle=*/false,
7628 /*AllowObjCWritebackConversion=*/false);
7629 if (ICS.isFailure()) {
7630 Diag(VariantRef->getExprLoc(),
7631 diag::err_omp_declare_variant_incompat_types)
7632 << VariantRef->getType()
7633 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7634 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7635 return std::nullopt;
7636 }
7637 VariantRefCast = SemaRef.PerformImplicitConversion(
7638 VariantRef, FnPtrType.getUnqualifiedType(),
7640 if (!VariantRefCast.isUsable())
7641 return std::nullopt;
7642 }
7643 // Drop previously built artificial addr_of unary op for member functions.
7644 if (Method && !Method->isStatic()) {
7645 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7646 if (auto *UO = dyn_cast<UnaryOperator>(
7647 PossibleAddrOfVariantRef->IgnoreImplicit()))
7648 VariantRefCast = UO->getSubExpr();
7649 }
7650 }
7651
7652 ExprResult ER = SemaRef.CheckPlaceholderExpr(VariantRefCast.get());
7653 if (!ER.isUsable() ||
7655 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7656 << VariantId << VariantRef->getSourceRange();
7657 return std::nullopt;
7658 }
7659
7660 // The VariantRef must point to function.
7661 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7662 if (!DRE) {
7663 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7664 << VariantId << VariantRef->getSourceRange();
7665 return std::nullopt;
7666 }
7667 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7668 if (!NewFD) {
7669 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7670 << VariantId << VariantRef->getSourceRange();
7671 return std::nullopt;
7672 }
7673
7674 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7675 Diag(VariantRef->getExprLoc(),
7676 diag::err_omp_declare_variant_same_base_function)
7677 << VariantRef->getSourceRange();
7678 return std::nullopt;
7679 }
7680
7681 // Check if function types are compatible in C.
7682 if (!getLangOpts().CPlusPlus) {
7683 QualType NewType =
7684 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7685 if (NewType.isNull()) {
7686 Diag(VariantRef->getExprLoc(),
7687 diag::err_omp_declare_variant_incompat_types)
7688 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7689 << VariantRef->getSourceRange();
7690 return std::nullopt;
7691 }
7692 if (NewType->isFunctionProtoType()) {
7693 if (FD->getType()->isFunctionNoProtoType())
7694 setPrototype(SemaRef, FD, NewFD, NewType);
7695 else if (NewFD->getType()->isFunctionNoProtoType())
7696 setPrototype(SemaRef, NewFD, FD, NewType);
7697 }
7698 }
7699
7700 // Check if variant function is not marked with declare variant directive.
7701 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7702 Diag(VariantRef->getExprLoc(),
7703 diag::warn_omp_declare_variant_marked_as_declare_variant)
7704 << VariantRef->getSourceRange();
7705 SourceRange SR =
7706 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7707 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7708 return std::nullopt;
7709 }
7710
7711 enum DoesntSupport {
7712 VirtFuncs = 1,
7713 Constructors = 3,
7714 Destructors = 4,
7715 DeletedFuncs = 5,
7716 DefaultedFuncs = 6,
7717 ConstexprFuncs = 7,
7718 ConstevalFuncs = 8,
7719 };
7720 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7721 if (CXXFD->isVirtual()) {
7722 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7723 << VirtFuncs;
7724 return std::nullopt;
7725 }
7726
7727 if (isa<CXXConstructorDecl>(FD)) {
7728 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7729 << Constructors;
7730 return std::nullopt;
7731 }
7732
7733 if (isa<CXXDestructorDecl>(FD)) {
7734 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7735 << Destructors;
7736 return std::nullopt;
7737 }
7738 }
7739
7740 if (FD->isDeleted()) {
7741 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7742 << DeletedFuncs;
7743 return std::nullopt;
7744 }
7745
7746 if (FD->isDefaulted()) {
7747 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7748 << DefaultedFuncs;
7749 return std::nullopt;
7750 }
7751
7752 if (FD->isConstexpr()) {
7753 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7754 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7755 return std::nullopt;
7756 }
7757
7758 // Check general compatibility.
7759 if (SemaRef.areMultiversionVariantFunctionsCompatible(
7764 VariantRef->getExprLoc(),
7765 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7766 PartialDiagnosticAt(VariantRef->getExprLoc(),
7767 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7768 << FD->getLocation()),
7769 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7770 /*CLinkageMayDiffer=*/true))
7771 return std::nullopt;
7772 return std::make_pair(FD, cast<Expr>(DRE));
7773}
7774
7776 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7777 ArrayRef<Expr *> AdjustArgsNothing,
7778 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7779 ArrayRef<Expr *> AdjustArgsNeedDeviceAddr,
7780 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7781 SourceLocation AppendArgsLoc, SourceRange SR) {
7782
7783 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7784 // An adjust_args clause or append_args clause can only be specified if the
7785 // dispatch selector of the construct selector set appears in the match
7786 // clause.
7787
7788 SmallVector<Expr *, 8> AllAdjustArgs;
7789 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7790 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7791 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDeviceAddr);
7792
7793 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7794 VariantMatchInfo VMI;
7796 if (!llvm::is_contained(
7797 VMI.ConstructTraits,
7798 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7799 if (!AllAdjustArgs.empty())
7800 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7801 << getOpenMPClauseNameForDiag(OMPC_adjust_args);
7802 if (!AppendArgs.empty())
7803 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7804 << getOpenMPClauseNameForDiag(OMPC_append_args);
7805 return;
7806 }
7807 }
7808
7809 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7810 // Each argument can only appear in a single adjust_args clause for each
7811 // declare variant directive.
7813
7814 for (Expr *E : AllAdjustArgs) {
7815 E = E->IgnoreParenImpCasts();
7816 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7817 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7818 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7819 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7820 FD->getParamDecl(PVD->getFunctionScopeIndex())
7821 ->getCanonicalDecl() == CanonPVD) {
7822 // It's a parameter of the function, check duplicates.
7823 if (!AdjustVars.insert(CanonPVD).second) {
7824 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7825 << PVD;
7826 return;
7827 }
7828 continue;
7829 }
7830 }
7831 }
7832 // Anything that is not a function parameter is an error.
7833 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7834 return;
7835 }
7836
7837 // OpenMP 6.0 [9.6.2 (page 332, line 31-33, adjust_args clause, Restrictions]
7838 // If the `need_device_addr` adjust-op modifier is present, each list item
7839 // that appears in the clause must refer to an argument in the declaration of
7840 // the function variant that has a reference type
7841 if (getLangOpts().OpenMP >= 60) {
7842 for (Expr *E : AdjustArgsNeedDeviceAddr) {
7843 E = E->IgnoreParenImpCasts();
7844 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7845 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
7846 if (!VD->getType()->isReferenceType())
7847 Diag(E->getExprLoc(),
7848 diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
7849 }
7850 }
7851 }
7852 }
7853
7854 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7855 getASTContext(), VariantRef, &TI,
7856 const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7857 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7858 AdjustArgsNeedDevicePtr.size(),
7859 const_cast<Expr **>(AdjustArgsNeedDeviceAddr.data()),
7860 AdjustArgsNeedDeviceAddr.size(),
7861 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7862 FD->addAttr(NewAttr);
7863}
7864
7865static CapturedStmt *
7867 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7868 assert(CS && "Captured statement expected");
7869 // 1.2.2 OpenMP Language Terminology
7870 // Structured block - An executable statement with a single entry at the
7871 // top and a single exit at the bottom.
7872 // The point of exit cannot be a branch out of the structured block.
7873 // longjmp() and throw() must not violate the entry/exit criteria.
7874 CS->getCapturedDecl()->setNothrow();
7875
7876 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
7877 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7879 // 1.2.2 OpenMP Language Terminology
7880 // Structured block - An executable statement with a single entry at the
7881 // top and a single exit at the bottom.
7882 // The point of exit cannot be a branch out of the structured block.
7883 // longjmp() and throw() must not violate the entry/exit criteria.
7884 CS->getCapturedDecl()->setNothrow();
7885 }
7887 return CS;
7888}
7889
7892 Stmt *AStmt, SourceLocation StartLoc,
7893 SourceLocation EndLoc) {
7894 if (!AStmt)
7895 return StmtError();
7896
7897 setBranchProtectedScope(SemaRef, OMPD_parallel, AStmt);
7898
7899 return OMPParallelDirective::Create(
7900 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
7901 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
7902}
7903
7904namespace {
7905/// Iteration space of a single for loop.
7906struct LoopIterationSpace final {
7907 /// True if the condition operator is the strict compare operator (<, > or
7908 /// !=).
7909 bool IsStrictCompare = false;
7910 /// Condition of the loop.
7911 Expr *PreCond = nullptr;
7912 /// This expression calculates the number of iterations in the loop.
7913 /// It is always possible to calculate it before starting the loop.
7914 Expr *NumIterations = nullptr;
7915 /// The loop counter variable.
7916 Expr *CounterVar = nullptr;
7917 /// Private loop counter variable.
7918 Expr *PrivateCounterVar = nullptr;
7919 /// This is initializer for the initial value of #CounterVar.
7920 Expr *CounterInit = nullptr;
7921 /// This is step for the #CounterVar used to generate its update:
7922 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7923 Expr *CounterStep = nullptr;
7924 /// Should step be subtracted?
7925 bool Subtract = false;
7926 /// Source range of the loop init.
7927 SourceRange InitSrcRange;
7928 /// Source range of the loop condition.
7929 SourceRange CondSrcRange;
7930 /// Source range of the loop increment.
7931 SourceRange IncSrcRange;
7932 /// Minimum value that can have the loop control variable. Used to support
7933 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7934 /// since only such variables can be used in non-loop invariant expressions.
7935 Expr *MinValue = nullptr;
7936 /// Maximum value that can have the loop control variable. Used to support
7937 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7938 /// since only such variables can be used in non-loop invariant expressions.
7939 Expr *MaxValue = nullptr;
7940 /// true, if the lower bound depends on the outer loop control var.
7941 bool IsNonRectangularLB = false;
7942 /// true, if the upper bound depends on the outer loop control var.
7943 bool IsNonRectangularUB = false;
7944 /// Index of the loop this loop depends on and forms non-rectangular loop
7945 /// nest.
7946 unsigned LoopDependentIdx = 0;
7947 /// Final condition for the non-rectangular loop nest support. It is used to
7948 /// check that the number of iterations for this particular counter must be
7949 /// finished.
7950 Expr *FinalCondition = nullptr;
7951};
7952
7953/// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls
7954/// set are referenced. Used for verifying loop nest structure before
7955/// performing a loop collapse operation.
7956class ForSubExprChecker : public DynamicRecursiveASTVisitor {
7957 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7958 VarDecl *ForbiddenVar = nullptr;
7959 SourceRange ErrLoc;
7960
7961public:
7962 explicit ForSubExprChecker(
7963 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7964 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
7965 // We want to visit implicit code, i.e. synthetic initialisation statements
7966 // created during range-for lowering.
7967 ShouldVisitImplicitCode = true;
7968 }
7969
7970 bool VisitDeclRefExpr(DeclRefExpr *E) override {
7971 ValueDecl *VD = E->getDecl();
7973 return true;
7974 VarDecl *V = VD->getPotentiallyDecomposedVarDecl();
7975 if (V->getType()->isReferenceType()) {
7976 VarDecl *VD = V->getDefinition();
7977 if (VD->hasInit()) {
7978 Expr *I = VD->getInit();
7979 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
7980 if (!DRE)
7981 return true;
7983 }
7984 }
7985 Decl *Canon = V->getCanonicalDecl();
7986 if (CollapsedLoopVarDecls.contains(Canon)) {
7987 ForbiddenVar = V;
7988 ErrLoc = E->getSourceRange();
7989 return false;
7990 }
7991
7992 return true;
7993 }
7994
7995 VarDecl *getForbiddenVar() const { return ForbiddenVar; }
7996 SourceRange getErrRange() const { return ErrLoc; }
7997};
7998
7999/// Helper class for checking canonical form of the OpenMP loops and
8000/// extracting iteration space of each loop in the loop nest, that will be used
8001/// for IR generation.
8002class OpenMPIterationSpaceChecker {
8003 /// Reference to Sema.
8004 Sema &SemaRef;
8005 /// Does the loop associated directive support non-rectangular loops?
8006 bool SupportsNonRectangular;
8007 /// Data-sharing stack.
8008 DSAStackTy &Stack;
8009 /// A location for diagnostics (when there is no some better location).
8010 SourceLocation DefaultLoc;
8011 /// A location for diagnostics (when increment is not compatible).
8012 SourceLocation ConditionLoc;
8013 /// The set of variables declared within the (to be collapsed) loop nest.
8014 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8015 /// A source location for referring to loop init later.
8016 SourceRange InitSrcRange;
8017 /// A source location for referring to condition later.
8018 SourceRange ConditionSrcRange;
8019 /// A source location for referring to increment later.
8020 SourceRange IncrementSrcRange;
8021 /// Loop variable.
8022 ValueDecl *LCDecl = nullptr;
8023 /// Reference to loop variable.
8024 Expr *LCRef = nullptr;
8025 /// Lower bound (initializer for the var).
8026 Expr *LB = nullptr;
8027 /// Upper bound.
8028 Expr *UB = nullptr;
8029 /// Loop step (increment).
8030 Expr *Step = nullptr;
8031 /// This flag is true when condition is one of:
8032 /// Var < UB
8033 /// Var <= UB
8034 /// UB > Var
8035 /// UB >= Var
8036 /// This will have no value when the condition is !=
8037 std::optional<bool> TestIsLessOp;
8038 /// This flag is true when condition is strict ( < or > ).
8039 bool TestIsStrictOp = false;
8040 /// This flag is true when step is subtracted on each iteration.
8041 bool SubtractStep = false;
8042 /// The outer loop counter this loop depends on (if any).
8043 const ValueDecl *DepDecl = nullptr;
8044 /// Contains number of loop (starts from 1) on which loop counter init
8045 /// expression of this loop depends on.
8046 std::optional<unsigned> InitDependOnLC;
8047 /// Contains number of loop (starts from 1) on which loop counter condition
8048 /// expression of this loop depends on.
8049 std::optional<unsigned> CondDependOnLC;
8050 /// Checks if the provide statement depends on the loop counter.
8051 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
8052 bool IsInitializer);
8053 /// Original condition required for checking of the exit condition for
8054 /// non-rectangular loop.
8055 Expr *Condition = nullptr;
8056
8057public:
8058 OpenMPIterationSpaceChecker(
8059 Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack,
8060 SourceLocation DefaultLoc,
8061 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
8062 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8063 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
8064 CollapsedLoopVarDecls(CollapsedLoopDecls) {}
8065 /// Check init-expr for canonical loop form and save loop counter
8066 /// variable - #Var and its initialization value - #LB.
8067 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
8068 /// Check test-expr for canonical form, save upper-bound (#UB), flags
8069 /// for less/greater and for strict/non-strict comparison.
8070 bool checkAndSetCond(Expr *S);
8071 /// Check incr-expr for canonical loop form and return true if it
8072 /// does not conform, otherwise save loop step (#Step).
8073 bool checkAndSetInc(Expr *S);
8074 /// Return the loop counter variable.
8075 ValueDecl *getLoopDecl() const { return LCDecl; }
8076 /// Return the reference expression to loop counter variable.
8077 Expr *getLoopDeclRefExpr() const { return LCRef; }
8078 /// Source range of the loop init.
8079 SourceRange getInitSrcRange() const { return InitSrcRange; }
8080 /// Source range of the loop condition.
8081 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
8082 /// Source range of the loop increment.
8083 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
8084 /// True if the step should be subtracted.
8085 bool shouldSubtractStep() const { return SubtractStep; }
8086 /// True, if the compare operator is strict (<, > or !=).
8087 bool isStrictTestOp() const { return TestIsStrictOp; }
8088 /// Build the expression to calculate the number of iterations.
8089 Expr *buildNumIterations(
8090 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8091 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8092 /// Build the precondition expression for the loops.
8093 Expr *
8094 buildPreCond(Scope *S, Expr *Cond,
8095 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8096 /// Build reference expression to the counter be used for codegen.
8097 DeclRefExpr *
8098 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8099 DSAStackTy &DSA) const;
8100 /// Build reference expression to the private counter be used for
8101 /// codegen.
8102 Expr *buildPrivateCounterVar() const;
8103 /// Build initialization of the counter be used for codegen.
8104 Expr *buildCounterInit() const;
8105 /// Build step of the counter be used for codegen.
8106 Expr *buildCounterStep() const;
8107 /// Build loop data with counter value for depend clauses in ordered
8108 /// directives.
8109 Expr *
8110 buildOrderedLoopData(Scope *S, Expr *Counter,
8111 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8112 SourceLocation Loc, Expr *Inc = nullptr,
8113 OverloadedOperatorKind OOK = OO_Amp);
8114 /// Builds the minimum value for the loop counter.
8115 std::pair<Expr *, Expr *> buildMinMaxValues(
8116 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8117 /// Builds final condition for the non-rectangular loops.
8118 Expr *buildFinalCondition(Scope *S) const;
8119 /// Return true if any expression is dependent.
8120 bool dependent() const;
8121 /// Returns true if the initializer forms non-rectangular loop.
8122 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
8123 /// Returns true if the condition forms non-rectangular loop.
8124 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
8125 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
8126 unsigned getLoopDependentIdx() const {
8127 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
8128 }
8129
8130private:
8131 /// Check the right-hand side of an assignment in the increment
8132 /// expression.
8133 bool checkAndSetIncRHS(Expr *RHS);
8134 /// Helper to set loop counter variable and its initializer.
8135 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8136 bool EmitDiags);
8137 /// Helper to set upper bound.
8138 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
8139 SourceRange SR, SourceLocation SL);
8140 /// Helper to set loop increment.
8141 bool setStep(Expr *NewStep, bool Subtract);
8142};
8143
8144bool OpenMPIterationSpaceChecker::dependent() const {
8145 if (!LCDecl) {
8146 assert(!LB && !UB && !Step);
8147 return false;
8148 }
8149 return LCDecl->getType()->isDependentType() ||
8150 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
8151 (Step && Step->isValueDependent());
8152}
8153
8154bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
8155 Expr *NewLCRefExpr,
8156 Expr *NewLB, bool EmitDiags) {
8157 // State consistency checking to ensure correct usage.
8158 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
8159 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8160 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
8161 return true;
8162 LCDecl = getCanonicalDecl(NewLCDecl);
8163 LCRef = NewLCRefExpr;
8164 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
8165 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8166 if ((Ctor->isCopyOrMoveConstructor() ||
8167 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8168 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8169 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
8170 LB = NewLB;
8171 if (EmitDiags)
8172 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
8173 return false;
8174}
8175
8176bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
8177 bool StrictOp, SourceRange SR,
8178 SourceLocation SL) {
8179 // State consistency checking to ensure correct usage.
8180 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
8181 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8182 if (!NewUB || NewUB->containsErrors())
8183 return true;
8184 UB = NewUB;
8185 if (LessOp)
8186 TestIsLessOp = LessOp;
8187 TestIsStrictOp = StrictOp;
8188 ConditionSrcRange = SR;
8189 ConditionLoc = SL;
8190 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
8191 return false;
8192}
8193
8194bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
8195 // State consistency checking to ensure correct usage.
8196 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
8197 if (!NewStep || NewStep->containsErrors())
8198 return true;
8199 if (!NewStep->isValueDependent()) {
8200 // Check that the step is integer expression.
8201 SourceLocation StepLoc = NewStep->getBeginLoc();
8203 StepLoc, getExprAsWritten(NewStep));
8204 if (Val.isInvalid())
8205 return true;
8206 NewStep = Val.get();
8207
8208 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8209 // If test-expr is of form var relational-op b and relational-op is < or
8210 // <= then incr-expr must cause var to increase on each iteration of the
8211 // loop. If test-expr is of form var relational-op b and relational-op is
8212 // > or >= then incr-expr must cause var to decrease on each iteration of
8213 // the loop.
8214 // If test-expr is of form b relational-op var and relational-op is < or
8215 // <= then incr-expr must cause var to decrease on each iteration of the
8216 // loop. If test-expr is of form b relational-op var and relational-op is
8217 // > or >= then incr-expr must cause var to increase on each iteration of
8218 // the loop.
8219 std::optional<llvm::APSInt> Result =
8220 NewStep->getIntegerConstantExpr(SemaRef.Context);
8221 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
8222 bool IsConstNeg =
8223 Result && Result->isSigned() && (Subtract != Result->isNegative());
8224 bool IsConstPos =
8225 Result && Result->isSigned() && (Subtract == Result->isNegative());
8226 bool IsConstZero = Result && !Result->getBoolValue();
8227
8228 // != with increment is treated as <; != with decrement is treated as >
8229 if (!TestIsLessOp)
8230 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8231 if (UB && (IsConstZero ||
8232 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8233 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8234 SemaRef.Diag(NewStep->getExprLoc(),
8235 diag::err_omp_loop_incr_not_compatible)
8236 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
8237 SemaRef.Diag(ConditionLoc,
8238 diag::note_omp_loop_cond_requires_compatible_incr)
8239 << *TestIsLessOp << ConditionSrcRange;
8240 return true;
8241 }
8242 if (*TestIsLessOp == Subtract) {
8243 NewStep =
8244 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
8245 .get();
8246 Subtract = !Subtract;
8247 }
8248 }
8249
8250 Step = NewStep;
8251 SubtractStep = Subtract;
8252 return false;
8253}
8254
8255namespace {
8256/// Checker for the non-rectangular loops. Checks if the initializer or
8257/// condition expression references loop counter variable.
8258class LoopCounterRefChecker final
8259 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8260 Sema &SemaRef;
8261 DSAStackTy &Stack;
8262 const ValueDecl *CurLCDecl = nullptr;
8263 const ValueDecl *DepDecl = nullptr;
8264 const ValueDecl *PrevDepDecl = nullptr;
8265 bool IsInitializer = true;
8266 bool SupportsNonRectangular;
8267 unsigned BaseLoopId = 0;
8268 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8269 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
8270 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8271 << (IsInitializer ? 0 : 1);
8272 return false;
8273 }
8274 const auto &&Data = Stack.isLoopControlVariable(VD);
8275 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8276 // The type of the loop iterator on which we depend may not have a random
8277 // access iterator type.
8278 if (Data.first && VD->getType()->isRecordType()) {
8279 SmallString<128> Name;
8280 llvm::raw_svector_ostream OS(Name);
8281 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8282 /*Qualified=*/true);
8283 SemaRef.Diag(E->getExprLoc(),
8284 diag::err_omp_wrong_dependency_iterator_type)
8285 << OS.str();
8286 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8287 return false;
8288 }
8289 if (Data.first && !SupportsNonRectangular) {
8290 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8291 return false;
8292 }
8293 if (Data.first &&
8294 (DepDecl || (PrevDepDecl &&
8295 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8296 if (!DepDecl && PrevDepDecl)
8297 DepDecl = PrevDepDecl;
8298 SmallString<128> Name;
8299 llvm::raw_svector_ostream OS(Name);
8300 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8301 /*Qualified=*/true);
8302 SemaRef.Diag(E->getExprLoc(),
8303 diag::err_omp_invariant_or_linear_dependency)
8304 << OS.str();
8305 return false;
8306 }
8307 if (Data.first) {
8308 DepDecl = VD;
8309 BaseLoopId = Data.first;
8310 }
8311 return Data.first;
8312 }
8313
8314public:
8315 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8316 const ValueDecl *VD = E->getDecl();
8317 if (isa<VarDecl>(VD))
8318 return checkDecl(E, VD);
8319 return false;
8320 }
8321 bool VisitMemberExpr(const MemberExpr *E) {
8322 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8323 const ValueDecl *VD = E->getMemberDecl();
8324 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8325 return checkDecl(E, VD);
8326 }
8327 return false;
8328 }
8329 bool VisitStmt(const Stmt *S) {
8330 bool Res = false;
8331 for (const Stmt *Child : S->children())
8332 Res = (Child && Visit(Child)) || Res;
8333 return Res;
8334 }
8335 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8336 const ValueDecl *CurLCDecl, bool IsInitializer,
8337 const ValueDecl *PrevDepDecl = nullptr,
8338 bool SupportsNonRectangular = true)
8339 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8340 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8341 SupportsNonRectangular(SupportsNonRectangular) {}
8342 unsigned getBaseLoopId() const {
8343 assert(CurLCDecl && "Expected loop dependency.");
8344 return BaseLoopId;
8345 }
8346 const ValueDecl *getDepDecl() const {
8347 assert(CurLCDecl && "Expected loop dependency.");
8348 return DepDecl;
8349 }
8350};
8351} // namespace
8352
8353std::optional<unsigned>
8354OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8355 bool IsInitializer) {
8356 // Check for the non-rectangular loops.
8357 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8358 DepDecl, SupportsNonRectangular);
8359 if (LoopStmtChecker.Visit(S)) {
8360 DepDecl = LoopStmtChecker.getDepDecl();
8361 return LoopStmtChecker.getBaseLoopId();
8362 }
8363 return std::nullopt;
8364}
8365
8366bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8367 // Check init-expr for canonical loop form and save loop counter
8368 // variable - #Var and its initialization value - #LB.
8369 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8370 // var = lb
8371 // integer-type var = lb
8372 // random-access-iterator-type var = lb
8373 // pointer-type var = lb
8374 //
8375 if (!S) {
8376 if (EmitDiags) {
8377 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8378 }
8379 return true;
8380 }
8381 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8382 if (!ExprTemp->cleanupsHaveSideEffects())
8383 S = ExprTemp->getSubExpr();
8384
8385 if (!CollapsedLoopVarDecls.empty()) {
8386 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8387 if (!FSEC.TraverseStmt(S)) {
8388 SourceRange Range = FSEC.getErrRange();
8389 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8390 << Range.getEnd() << 0 << FSEC.getForbiddenVar();
8391 return true;
8392 }
8393 }
8394
8395 InitSrcRange = S->getSourceRange();
8396 if (Expr *E = dyn_cast<Expr>(S))
8397 S = E->IgnoreParens();
8398 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8399 if (BO->getOpcode() == BO_Assign) {
8400 Expr *LHS = BO->getLHS()->IgnoreParens();
8401 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8402 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8403 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8404 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8405 EmitDiags);
8406 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8407 }
8408 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8409 if (ME->isArrow() &&
8410 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8411 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8412 EmitDiags);
8413 }
8414 }
8415 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8416 if (DS->isSingleDecl()) {
8417 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8418 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8419 // Accept non-canonical init form here but emit ext. warning.
8420 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8421 SemaRef.Diag(S->getBeginLoc(),
8422 diag::ext_omp_loop_not_canonical_init)
8423 << S->getSourceRange();
8424 return setLCDeclAndLB(
8425 Var,
8426 buildDeclRefExpr(SemaRef, Var,
8427 Var->getType().getNonReferenceType(),
8428 DS->getBeginLoc()),
8429 Var->getInit(), EmitDiags);
8430 }
8431 }
8432 }
8433 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8434 if (CE->getOperator() == OO_Equal) {
8435 Expr *LHS = CE->getArg(0);
8436 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8437 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8438 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8439 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8440 EmitDiags);
8441 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8442 }
8443 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8444 if (ME->isArrow() &&
8445 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8446 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8447 EmitDiags);
8448 }
8449 }
8450 }
8451
8452 if (dependent() || SemaRef.CurContext->isDependentContext())
8453 return false;
8454 if (EmitDiags) {
8455 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8456 << S->getSourceRange();
8457 }
8458 return true;
8459}
8460
8461/// Ignore parenthesizes, implicit casts, copy constructor and return the
8462/// variable (which may be the loop variable) if possible.
8463static const ValueDecl *getInitLCDecl(const Expr *E) {
8464 if (!E)
8465 return nullptr;
8466 E = getExprAsWritten(E);
8467 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8468 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8469 if ((Ctor->isCopyOrMoveConstructor() ||
8470 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8471 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8472 E = CE->getArg(0)->IgnoreParenImpCasts();
8473 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8474 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8475 return getCanonicalDecl(VD);
8476 }
8477 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8478 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8479 return getCanonicalDecl(ME->getMemberDecl());
8480 return nullptr;
8481}
8482
8483bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8484 // Check test-expr for canonical form, save upper-bound UB, flags for
8485 // less/greater and for strict/non-strict comparison.
8486 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8487 // var relational-op b
8488 // b relational-op var
8489 //
8490 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8491 if (!S) {
8492 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8493 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8494 return true;
8495 }
8496 Condition = S;
8497 S = getExprAsWritten(S);
8498
8499 if (!CollapsedLoopVarDecls.empty()) {
8500 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8501 if (!FSEC.TraverseStmt(S)) {
8502 SourceRange Range = FSEC.getErrRange();
8503 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8504 << Range.getEnd() << 1 << FSEC.getForbiddenVar();
8505 return true;
8506 }
8507 }
8508
8509 SourceLocation CondLoc = S->getBeginLoc();
8510 auto &&CheckAndSetCond =
8511 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8512 const Expr *RHS, SourceRange SR,
8513 SourceLocation OpLoc) -> std::optional<bool> {
8514 if (BinaryOperator::isRelationalOp(Opcode)) {
8515 if (getInitLCDecl(LHS) == LCDecl)
8516 return setUB(const_cast<Expr *>(RHS),
8517 (Opcode == BO_LT || Opcode == BO_LE),
8518 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8519 if (getInitLCDecl(RHS) == LCDecl)
8520 return setUB(const_cast<Expr *>(LHS),
8521 (Opcode == BO_GT || Opcode == BO_GE),
8522 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8523 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8524 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8525 /*LessOp=*/std::nullopt,
8526 /*StrictOp=*/true, SR, OpLoc);
8527 }
8528 return std::nullopt;
8529 };
8530 std::optional<bool> Res;
8531 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8532 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8533 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8534 RBO->getOperatorLoc());
8535 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8536 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8537 BO->getSourceRange(), BO->getOperatorLoc());
8538 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8539 if (CE->getNumArgs() == 2) {
8540 Res = CheckAndSetCond(
8541 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8542 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8543 }
8544 }
8545 if (Res)
8546 return *Res;
8547 if (dependent() || SemaRef.CurContext->isDependentContext())
8548 return false;
8549 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8550 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8551 return true;
8552}
8553
8554bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8555 // RHS of canonical loop form increment can be:
8556 // var + incr
8557 // incr + var
8558 // var - incr
8559 //
8560 RHS = RHS->IgnoreParenImpCasts();
8561 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8562 if (BO->isAdditiveOp()) {
8563 bool IsAdd = BO->getOpcode() == BO_Add;
8564 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8565 return setStep(BO->getRHS(), !IsAdd);
8566 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8567 return setStep(BO->getLHS(), /*Subtract=*/false);
8568 }
8569 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8570 bool IsAdd = CE->getOperator() == OO_Plus;
8571 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8572 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8573 return setStep(CE->getArg(1), !IsAdd);
8574 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8575 return setStep(CE->getArg(0), /*Subtract=*/false);
8576 }
8577 }
8578 if (dependent() || SemaRef.CurContext->isDependentContext())
8579 return false;
8580 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8581 << RHS->getSourceRange() << LCDecl;
8582 return true;
8583}
8584
8585bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8586 // Check incr-expr for canonical loop form and return true if it
8587 // does not conform.
8588 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8589 // ++var
8590 // var++
8591 // --var
8592 // var--
8593 // var += incr
8594 // var -= incr
8595 // var = var + incr
8596 // var = incr + var
8597 // var = var - incr
8598 //
8599 if (!S) {
8600 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8601 return true;
8602 }
8603 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8604 if (!ExprTemp->cleanupsHaveSideEffects())
8605 S = ExprTemp->getSubExpr();
8606
8607 if (!CollapsedLoopVarDecls.empty()) {
8608 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8609 if (!FSEC.TraverseStmt(S)) {
8610 SourceRange Range = FSEC.getErrRange();
8611 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8612 << Range.getEnd() << 2 << FSEC.getForbiddenVar();
8613 return true;
8614 }
8615 }
8616
8617 IncrementSrcRange = S->getSourceRange();
8618 S = S->IgnoreParens();
8619 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8620 if (UO->isIncrementDecrementOp() &&
8621 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8622 return setStep(SemaRef
8623 .ActOnIntegerConstant(UO->getBeginLoc(),
8624 (UO->isDecrementOp() ? -1 : 1))
8625 .get(),
8626 /*Subtract=*/false);
8627 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8628 switch (BO->getOpcode()) {
8629 case BO_AddAssign:
8630 case BO_SubAssign:
8631 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8632 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8633 break;
8634 case BO_Assign:
8635 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8636 return checkAndSetIncRHS(BO->getRHS());
8637 break;
8638 default:
8639 break;
8640 }
8641 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8642 switch (CE->getOperator()) {
8643 case OO_PlusPlus:
8644 case OO_MinusMinus:
8645 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8646 return setStep(SemaRef
8647 .ActOnIntegerConstant(
8648 CE->getBeginLoc(),
8649 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8650 .get(),
8651 /*Subtract=*/false);
8652 break;
8653 case OO_PlusEqual:
8654 case OO_MinusEqual:
8655 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8656 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8657 break;
8658 case OO_Equal:
8659 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8660 return checkAndSetIncRHS(CE->getArg(1));
8661 break;
8662 default:
8663 break;
8664 }
8665 }
8666 if (dependent() || SemaRef.CurContext->isDependentContext())
8667 return false;
8668 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8669 << S->getSourceRange() << LCDecl;
8670 return true;
8671}
8672
8673static ExprResult
8674tryBuildCapture(Sema &SemaRef, Expr *Capture,
8675 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8676 StringRef Name = ".capture_expr.") {
8677 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8678 return Capture;
8679 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8680 return SemaRef.PerformImplicitConversion(Capture->IgnoreImpCasts(),
8681 Capture->getType(),
8683 /*AllowExplicit=*/true);
8684 auto I = Captures.find(Capture);
8685 if (I != Captures.end())
8686 return buildCapture(SemaRef, Capture, I->second, Name);
8687 DeclRefExpr *Ref = nullptr;
8688 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8689 Captures[Capture] = Ref;
8690 return Res;
8691}
8692
8693/// Calculate number of iterations, transforming to unsigned, if number of
8694/// iterations may be larger than the original type.
8695static Expr *
8696calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8697 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8698 bool TestIsStrictOp, bool RoundToStep,
8699 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8700 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8701 if (!NewStep.isUsable())
8702 return nullptr;
8703 llvm::APSInt LRes, SRes;
8704 bool IsLowerConst = false, IsStepConst = false;
8705 if (std::optional<llvm::APSInt> Res =
8706 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8707 LRes = *Res;
8708 IsLowerConst = true;
8709 }
8710 if (std::optional<llvm::APSInt> Res =
8711 Step->getIntegerConstantExpr(SemaRef.Context)) {
8712 SRes = *Res;
8713 IsStepConst = true;
8714 }
8715 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8716 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8717 (TestIsStrictOp && LRes.isStrictlyPositive()));
8718 bool NeedToReorganize = false;
8719 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8720 if (!NoNeedToConvert && IsLowerConst &&
8721 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8722 NoNeedToConvert = true;
8723 if (RoundToStep) {
8724 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8725 ? LRes.getBitWidth()
8726 : SRes.getBitWidth();
8727 LRes = LRes.extend(BW + 1);
8728 LRes.setIsSigned(true);
8729 SRes = SRes.extend(BW + 1);
8730 SRes.setIsSigned(true);
8731 LRes -= SRes;
8732 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8733 LRes = LRes.trunc(BW);
8734 }
8735 if (TestIsStrictOp) {
8736 unsigned BW = LRes.getBitWidth();
8737 LRes = LRes.extend(BW + 1);
8738 LRes.setIsSigned(true);
8739 ++LRes;
8740 NoNeedToConvert =
8741 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8742 // truncate to the original bitwidth.
8743 LRes = LRes.trunc(BW);
8744 }
8745 NeedToReorganize = NoNeedToConvert;
8746 }
8747 llvm::APSInt URes;
8748 bool IsUpperConst = false;
8749 if (std::optional<llvm::APSInt> Res =
8750 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8751 URes = *Res;
8752 IsUpperConst = true;
8753 }
8754 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8755 (!RoundToStep || IsStepConst)) {
8756 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8757 : URes.getBitWidth();
8758 LRes = LRes.extend(BW + 1);
8759 LRes.setIsSigned(true);
8760 URes = URes.extend(BW + 1);
8761 URes.setIsSigned(true);
8762 URes -= LRes;
8763 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8764 NeedToReorganize = NoNeedToConvert;
8765 }
8766 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8767 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8768 // unsigned.
8769 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8770 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8771 QualType LowerTy = Lower->getType();
8772 QualType UpperTy = Upper->getType();
8773 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8774 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8775 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8776 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8778 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8779 Upper =
8780 SemaRef
8782 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8784 .get();
8785 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8786 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8787 }
8788 }
8789 if (!Lower || !Upper || NewStep.isInvalid())
8790 return nullptr;
8791
8792 ExprResult Diff;
8793 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8794 // 1]).
8795 if (NeedToReorganize) {
8796 Diff = Lower;
8797
8798 if (RoundToStep) {
8799 // Lower - Step
8800 Diff =
8801 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8802 if (!Diff.isUsable())
8803 return nullptr;
8804 }
8805
8806 // Lower - Step [+ 1]
8807 if (TestIsStrictOp)
8808 Diff = SemaRef.BuildBinOp(
8809 S, DefaultLoc, BO_Add, Diff.get(),
8810 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8811 if (!Diff.isUsable())
8812 return nullptr;
8813
8814 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8815 if (!Diff.isUsable())
8816 return nullptr;
8817
8818 // Upper - (Lower - Step [+ 1]).
8819 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8820 if (!Diff.isUsable())
8821 return nullptr;
8822 } else {
8823 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8824
8825 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8826 // BuildBinOp already emitted error, this one is to point user to upper
8827 // and lower bound, and to tell what is passed to 'operator-'.
8828 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8829 << Upper->getSourceRange() << Lower->getSourceRange();
8830 return nullptr;
8831 }
8832
8833 if (!Diff.isUsable())
8834 return nullptr;
8835
8836 // Upper - Lower [- 1]
8837 if (TestIsStrictOp)
8838 Diff = SemaRef.BuildBinOp(
8839 S, DefaultLoc, BO_Sub, Diff.get(),
8840 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8841 if (!Diff.isUsable())
8842 return nullptr;
8843
8844 if (RoundToStep) {
8845 // Upper - Lower [- 1] + Step
8846 Diff =
8847 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8848 if (!Diff.isUsable())
8849 return nullptr;
8850 }
8851 }
8852
8853 // Parentheses (for dumping/debugging purposes only).
8854 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8855 if (!Diff.isUsable())
8856 return nullptr;
8857
8858 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8859 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8860 if (!Diff.isUsable())
8861 return nullptr;
8862
8863 return Diff.get();
8864}
8865
8866/// Build the expression to calculate the number of iterations.
8867Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8868 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8869 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8870 QualType VarType = LCDecl->getType().getNonReferenceType();
8871 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8872 !SemaRef.getLangOpts().CPlusPlus)
8873 return nullptr;
8874 Expr *LBVal = LB;
8875 Expr *UBVal = UB;
8876 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8877 // max(LB(MinVal), LB(MaxVal)))
8878 if (InitDependOnLC) {
8879 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8880 if (!IS.MinValue || !IS.MaxValue)
8881 return nullptr;
8882 // OuterVar = Min
8883 ExprResult MinValue =
8884 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8885 if (!MinValue.isUsable())
8886 return nullptr;
8887
8888 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8889 IS.CounterVar, MinValue.get());
8890 if (!LBMinVal.isUsable())
8891 return nullptr;
8892 // OuterVar = Min, LBVal
8893 LBMinVal =
8894 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8895 if (!LBMinVal.isUsable())
8896 return nullptr;
8897 // (OuterVar = Min, LBVal)
8898 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8899 if (!LBMinVal.isUsable())
8900 return nullptr;
8901
8902 // OuterVar = Max
8903 ExprResult MaxValue =
8904 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8905 if (!MaxValue.isUsable())
8906 return nullptr;
8907
8908 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8909 IS.CounterVar, MaxValue.get());
8910 if (!LBMaxVal.isUsable())
8911 return nullptr;
8912 // OuterVar = Max, LBVal
8913 LBMaxVal =
8914 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8915 if (!LBMaxVal.isUsable())
8916 return nullptr;
8917 // (OuterVar = Max, LBVal)
8918 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8919 if (!LBMaxVal.isUsable())
8920 return nullptr;
8921
8922 Expr *LBMin =
8923 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
8924 Expr *LBMax =
8925 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
8926 if (!LBMin || !LBMax)
8927 return nullptr;
8928 // LB(MinVal) < LB(MaxVal)
8929 ExprResult MinLessMaxRes =
8930 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8931 if (!MinLessMaxRes.isUsable())
8932 return nullptr;
8933 Expr *MinLessMax =
8934 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
8935 .get();
8936 if (!MinLessMax)
8937 return nullptr;
8938 if (*TestIsLessOp) {
8939 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8940 // LB(MaxVal))
8941 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8942 MinLessMax, LBMin, LBMax);
8943 if (!MinLB.isUsable())
8944 return nullptr;
8945 LBVal = MinLB.get();
8946 } else {
8947 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8948 // LB(MaxVal))
8949 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8950 MinLessMax, LBMax, LBMin);
8951 if (!MaxLB.isUsable())
8952 return nullptr;
8953 LBVal = MaxLB.get();
8954 }
8955 // OuterVar = LB
8956 LBMinVal =
8957 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8958 if (!LBMinVal.isUsable())
8959 return nullptr;
8960 LBVal = LBMinVal.get();
8961 }
8962 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8963 // min(UB(MinVal), UB(MaxVal))
8964 if (CondDependOnLC) {
8965 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8966 if (!IS.MinValue || !IS.MaxValue)
8967 return nullptr;
8968 // OuterVar = Min
8969 ExprResult MinValue =
8970 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8971 if (!MinValue.isUsable())
8972 return nullptr;
8973
8974 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8975 IS.CounterVar, MinValue.get());
8976 if (!UBMinVal.isUsable())
8977 return nullptr;
8978 // OuterVar = Min, UBVal
8979 UBMinVal =
8980 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
8981 if (!UBMinVal.isUsable())
8982 return nullptr;
8983 // (OuterVar = Min, UBVal)
8984 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
8985 if (!UBMinVal.isUsable())
8986 return nullptr;
8987
8988 // OuterVar = Max
8989 ExprResult MaxValue =
8990 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8991 if (!MaxValue.isUsable())
8992 return nullptr;
8993
8994 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8995 IS.CounterVar, MaxValue.get());
8996 if (!UBMaxVal.isUsable())
8997 return nullptr;
8998 // OuterVar = Max, UBVal
8999 UBMaxVal =
9000 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
9001 if (!UBMaxVal.isUsable())
9002 return nullptr;
9003 // (OuterVar = Max, UBVal)
9004 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
9005 if (!UBMaxVal.isUsable())
9006 return nullptr;
9007
9008 Expr *UBMin =
9009 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
9010 Expr *UBMax =
9011 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
9012 if (!UBMin || !UBMax)
9013 return nullptr;
9014 // UB(MinVal) > UB(MaxVal)
9015 ExprResult MinGreaterMaxRes =
9016 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
9017 if (!MinGreaterMaxRes.isUsable())
9018 return nullptr;
9019 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
9020 Captures, ".min_greater_max")
9021 .get();
9022 if (!MinGreaterMax)
9023 return nullptr;
9024 if (*TestIsLessOp) {
9025 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
9026 // UB(MaxVal))
9027 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
9028 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
9029 if (!MaxUB.isUsable())
9030 return nullptr;
9031 UBVal = MaxUB.get();
9032 } else {
9033 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
9034 // UB(MaxVal))
9035 ExprResult MinUB = SemaRef.ActOnConditionalOp(
9036 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
9037 if (!MinUB.isUsable())
9038 return nullptr;
9039 UBVal = MinUB.get();
9040 }
9041 }
9042 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9043 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9044 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
9045 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
9046 if (!Upper || !Lower)
9047 return nullptr;
9048
9049 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9050 Step, VarType, TestIsStrictOp,
9051 /*RoundToStep=*/true, Captures);
9052 if (!Diff.isUsable())
9053 return nullptr;
9054
9055 // OpenMP runtime requires 32-bit or 64-bit loop variables.
9056 QualType Type = Diff.get()->getType();
9057 ASTContext &C = SemaRef.Context;
9058 bool UseVarType = VarType->hasIntegerRepresentation() &&
9059 C.getTypeSize(Type) > C.getTypeSize(VarType);
9060 if (!Type->isIntegerType() || UseVarType) {
9061 unsigned NewSize =
9062 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
9063 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
9065 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
9066 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
9067 Diff = SemaRef.PerformImplicitConversion(Diff.get(), Type,
9069 /*AllowExplicit=*/true);
9070 if (!Diff.isUsable())
9071 return nullptr;
9072 }
9073 }
9074 if (LimitedType) {
9075 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
9076 if (NewSize != C.getTypeSize(Type)) {
9077 if (NewSize < C.getTypeSize(Type)) {
9078 assert(NewSize == 64 && "incorrect loop var size");
9079 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
9080 << InitSrcRange << ConditionSrcRange;
9081 }
9082 QualType NewType = C.getIntTypeForBitwidth(
9084 C.getTypeSize(Type) < NewSize);
9085 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
9086 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
9088 /*AllowExplicit=*/true);
9089 if (!Diff.isUsable())
9090 return nullptr;
9091 }
9092 }
9093 }
9094
9095 return Diff.get();
9096}
9097
9098std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9099 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9100 // Do not build for iterators, they cannot be used in non-rectangular loop
9101 // nests.
9102 if (LCDecl->getType()->isRecordType())
9103 return std::make_pair(nullptr, nullptr);
9104 // If we subtract, the min is in the condition, otherwise the min is in the
9105 // init value.
9106 Expr *MinExpr = nullptr;
9107 Expr *MaxExpr = nullptr;
9108 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9109 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9110 bool LBNonRect =
9111 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9112 bool UBNonRect =
9113 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9114 Expr *Lower =
9115 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
9116 Expr *Upper =
9117 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
9118 if (!Upper || !Lower)
9119 return std::make_pair(nullptr, nullptr);
9120
9121 if (*TestIsLessOp)
9122 MinExpr = Lower;
9123 else
9124 MaxExpr = Upper;
9125
9126 // Build minimum/maximum value based on number of iterations.
9127 QualType VarType = LCDecl->getType().getNonReferenceType();
9128
9129 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9130 Step, VarType, TestIsStrictOp,
9131 /*RoundToStep=*/false, Captures);
9132 if (!Diff.isUsable())
9133 return std::make_pair(nullptr, nullptr);
9134
9135 // ((Upper - Lower [- 1]) / Step) * Step
9136 // Parentheses (for dumping/debugging purposes only).
9137 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9138 if (!Diff.isUsable())
9139 return std::make_pair(nullptr, nullptr);
9140
9141 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
9142 if (!NewStep.isUsable())
9143 return std::make_pair(nullptr, nullptr);
9144 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
9145 if (!Diff.isUsable())
9146 return std::make_pair(nullptr, nullptr);
9147
9148 // Parentheses (for dumping/debugging purposes only).
9149 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9150 if (!Diff.isUsable())
9151 return std::make_pair(nullptr, nullptr);
9152
9153 // Convert to the ptrdiff_t, if original type is pointer.
9154 if (VarType->isAnyPointerType() &&
9155 !SemaRef.Context.hasSameType(
9156 Diff.get()->getType(),
9158 Diff = SemaRef.PerformImplicitConversion(
9159 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
9160 AssignmentAction::Converting, /*AllowExplicit=*/true);
9161 }
9162 if (!Diff.isUsable())
9163 return std::make_pair(nullptr, nullptr);
9164
9165 if (*TestIsLessOp) {
9166 // MinExpr = Lower;
9167 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
9168 Diff = SemaRef.BuildBinOp(
9169 S, DefaultLoc, BO_Add,
9170 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
9171 Diff.get());
9172 if (!Diff.isUsable())
9173 return std::make_pair(nullptr, nullptr);
9174 } else {
9175 // MaxExpr = Upper;
9176 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
9177 Diff = SemaRef.BuildBinOp(
9178 S, DefaultLoc, BO_Sub,
9179 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
9180 Diff.get());
9181 if (!Diff.isUsable())
9182 return std::make_pair(nullptr, nullptr);
9183 }
9184
9185 // Convert to the original type.
9186 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
9187 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
9189 /*AllowExplicit=*/true);
9190 if (!Diff.isUsable())
9191 return std::make_pair(nullptr, nullptr);
9192
9193 Sema::TentativeAnalysisScope Trap(SemaRef);
9194 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
9195 if (!Diff.isUsable())
9196 return std::make_pair(nullptr, nullptr);
9197
9198 if (*TestIsLessOp)
9199 MaxExpr = Diff.get();
9200 else
9201 MinExpr = Diff.get();
9202
9203 return std::make_pair(MinExpr, MaxExpr);
9204}
9205
9206Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
9207 if (InitDependOnLC || CondDependOnLC)
9208 return Condition;
9209 return nullptr;
9210}
9211
9212Expr *OpenMPIterationSpaceChecker::buildPreCond(
9213 Scope *S, Expr *Cond,
9214 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9215 // Do not build a precondition when the condition/initialization is dependent
9216 // to prevent pessimistic early loop exit.
9217 // TODO: this can be improved by calculating min/max values but not sure that
9218 // it will be very effective.
9219 if (CondDependOnLC || InitDependOnLC)
9220 return SemaRef
9222 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
9223 SemaRef.Context.BoolTy, /*Action=*/AssignmentAction::Casting,
9224 /*AllowExplicit=*/true)
9225 .get();
9226
9227 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
9228 Sema::TentativeAnalysisScope Trap(SemaRef);
9229
9230 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9231 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9232 if (!NewLB.isUsable() || !NewUB.isUsable())
9233 return nullptr;
9234
9235 ExprResult CondExpr =
9236 SemaRef.BuildBinOp(S, DefaultLoc,
9237 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9238 : (TestIsStrictOp ? BO_GT : BO_GE),
9239 NewLB.get(), NewUB.get());
9240 if (CondExpr.isUsable()) {
9241 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
9242 SemaRef.Context.BoolTy))
9243 CondExpr = SemaRef.PerformImplicitConversion(
9244 CondExpr.get(), SemaRef.Context.BoolTy,
9245 /*Action=*/AssignmentAction::Casting,
9246 /*AllowExplicit=*/true);
9247 }
9248
9249 // Otherwise use original loop condition and evaluate it in runtime.
9250 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9251}
9252
9253/// Build reference expression to the counter be used for codegen.
9254DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9255 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9256 DSAStackTy &DSA) const {
9257 auto *VD = dyn_cast<VarDecl>(LCDecl);
9258 if (!VD) {
9259 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(LCDecl);
9261 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
9262 const DSAStackTy::DSAVarData Data =
9263 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
9264 // If the loop control decl is explicitly marked as private, do not mark it
9265 // as captured again.
9266 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
9267 Captures.insert(std::make_pair(LCRef, Ref));
9268 return Ref;
9269 }
9270 return cast<DeclRefExpr>(LCRef);
9271}
9272
9273Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9274 if (LCDecl && !LCDecl->isInvalidDecl()) {
9276 VarDecl *PrivateVar = buildVarDecl(
9277 SemaRef, DefaultLoc, Type, LCDecl->getName(),
9278 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9279 isa<VarDecl>(LCDecl)
9280 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
9281 : nullptr);
9282 if (PrivateVar->isInvalidDecl())
9283 return nullptr;
9284 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
9285 }
9286 return nullptr;
9287}
9288
9289/// Build initialization of the counter to be used for codegen.
9290Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9291
9292/// Build step of the counter be used for codegen.
9293Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9294
9295Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9296 Scope *S, Expr *Counter,
9297 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9298 Expr *Inc, OverloadedOperatorKind OOK) {
9299 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
9300 if (!Cnt)
9301 return nullptr;
9302 if (Inc) {
9303 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9304 "Expected only + or - operations for depend clauses.");
9305 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9306 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
9307 if (!Cnt)
9308 return nullptr;
9309 }
9310 QualType VarType = LCDecl->getType().getNonReferenceType();
9311 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9312 !SemaRef.getLangOpts().CPlusPlus)
9313 return nullptr;
9314 // Upper - Lower
9315 Expr *Upper =
9316 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9317 Expr *Lower =
9318 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9319 if (!Upper || !Lower)
9320 return nullptr;
9321
9322 ExprResult Diff = calculateNumIters(
9323 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9324 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9325 if (!Diff.isUsable())
9326 return nullptr;
9327
9328 return Diff.get();
9329}
9330} // namespace
9331
9333 Stmt *Init) {
9334 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9335 assert(Init && "Expected loop in canonical form.");
9336 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9337 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9338 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
9339 return;
9340
9341 DSAStack->loopStart();
9343 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9344 *DSAStack, ForLoc, EmptyDeclSet);
9345 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9346 if (ValueDecl *D = ISC.getLoopDecl()) {
9347 auto *VD = dyn_cast<VarDecl>(D);
9348 DeclRefExpr *PrivateRef = nullptr;
9349 if (!VD) {
9351 VD = Private;
9352 } else {
9353 PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(),
9354 /*WithInit=*/false);
9355 VD = cast<VarDecl>(PrivateRef->getDecl());
9356 }
9357 }
9358 DSAStack->addLoopControlVariable(D, VD);
9359 const Decl *LD = DSAStack->getPossiblyLoopCounter();
9360 if (LD != D->getCanonicalDecl()) {
9361 DSAStack->resetPossibleLoopCounter();
9362 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9363 SemaRef.MarkDeclarationsReferencedInExpr(buildDeclRefExpr(
9364 SemaRef, const_cast<VarDecl *>(Var),
9365 Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
9366 /*RefersToCapture=*/true));
9367 }
9368 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9369 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9370 // associated for-loop of a simd construct with just one associated
9371 // for-loop may be listed in a linear clause with a constant-linear-step
9372 // that is the increment of the associated for-loop. The loop iteration
9373 // variable(s) in the associated for-loop(s) of a for or parallel for
9374 // construct may be listed in a private or lastprivate clause.
9375 DSAStackTy::DSAVarData DVar =
9376 DSAStack->getTopDSA(D, /*FromParent=*/false);
9377 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9378 // is declared in the loop and it is predetermined as a private.
9379 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9380 OpenMPClauseKind PredeterminedCKind =
9382 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9383 : OMPC_private;
9384 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
9385 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9386 };
9387 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9388 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9389 (getLangOpts().OpenMP <= 45 ||
9390 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9392 IsOpenMPTaskloopDirective(DKind) ||
9394 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9395 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9396 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9397 unsigned OMPVersion = getLangOpts().OpenMP;
9398 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9399 << getOpenMPClauseNameForDiag(DVar.CKind)
9400 << getOpenMPDirectiveName(DKind, OMPVersion)
9401 << getOpenMPClauseNameForDiag(PredeterminedCKind);
9402 if (DVar.RefExpr == nullptr)
9403 DVar.CKind = PredeterminedCKind;
9404 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
9405 } else if (LoopDeclRefExpr) {
9406 // Make the loop iteration variable private (for worksharing
9407 // constructs), linear (for simd directives with the only one
9408 // associated loop) or lastprivate (for simd directives with several
9409 // collapsed or ordered loops).
9410 if (DVar.CKind == OMPC_unknown)
9411 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9412 }
9413 }
9414 }
9415 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9416}
9417
9418namespace {
9419// Utility for OpenMP doacross clause kind
9420class OMPDoacrossKind {
9421public:
9422 bool isSource(const OMPDoacrossClause *C) {
9423 return C->getDependenceType() == OMPC_DOACROSS_source ||
9424 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9425 }
9426 bool isSink(const OMPDoacrossClause *C) {
9427 return C->getDependenceType() == OMPC_DOACROSS_sink;
9428 }
9429 bool isSinkIter(const OMPDoacrossClause *C) {
9430 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9431 }
9432};
9433} // namespace
9434/// Called on a for stmt to check and extract its iteration space
9435/// for further processing (such as collapsing).
9437 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9438 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9439 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9440 Expr *OrderedLoopCountExpr,
9441 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9443 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9444 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9445 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9446 // OpenMP [2.9.1, Canonical Loop Form]
9447 // for (init-expr; test-expr; incr-expr) structured-block
9448 // for (range-decl: range-expr) structured-block
9449 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9450 S = CanonLoop->getLoopStmt();
9451 auto *For = dyn_cast_or_null<ForStmt>(S);
9452 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9453 // Ranged for is supported only in OpenMP 5.0.
9454 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9455 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
9456 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9457 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9458 << getOpenMPDirectiveName(DKind, OMPVersion) << TotalNestedLoopCount
9459 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9460 if (TotalNestedLoopCount > 1) {
9461 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9462 SemaRef.Diag(DSA.getConstructLoc(),
9463 diag::note_omp_collapse_ordered_expr)
9464 << 2 << CollapseLoopCountExpr->getSourceRange()
9465 << OrderedLoopCountExpr->getSourceRange();
9466 else if (CollapseLoopCountExpr)
9467 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9468 diag::note_omp_collapse_ordered_expr)
9469 << 0 << CollapseLoopCountExpr->getSourceRange();
9470 else if (OrderedLoopCountExpr)
9471 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9472 diag::note_omp_collapse_ordered_expr)
9473 << 1 << OrderedLoopCountExpr->getSourceRange();
9474 }
9475 return true;
9476 }
9477 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9478 "No loop body.");
9479 // Postpone analysis in dependent contexts for ranged for loops.
9480 if (CXXFor && SemaRef.CurContext->isDependentContext())
9481 return false;
9482
9483 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9484 For ? For->getForLoc() : CXXFor->getForLoc(),
9485 CollapsedLoopVarDecls);
9486
9487 // Check init.
9488 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9489 if (ISC.checkAndSetInit(Init))
9490 return true;
9491
9492 bool HasErrors = false;
9493
9494 // Check loop variable's type.
9495 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9496 // OpenMP [2.6, Canonical Loop Form]
9497 // Var is one of the following:
9498 // A variable of signed or unsigned integer type.
9499 // For C++, a variable of a random access iterator type.
9500 // For C, a variable of a pointer type.
9501 QualType VarType = LCDecl->getType().getNonReferenceType();
9502 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9503 !VarType->isPointerType() &&
9504 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9505 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9506 << SemaRef.getLangOpts().CPlusPlus;
9507 HasErrors = true;
9508 }
9509
9510 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9511 // a Construct
9512 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9513 // parallel for construct is (are) private.
9514 // The loop iteration variable in the associated for-loop of a simd
9515 // construct with just one associated for-loop is linear with a
9516 // constant-linear-step that is the increment of the associated for-loop.
9517 // Exclude loop var from the list of variables with implicitly defined data
9518 // sharing attributes.
9519 VarsWithImplicitDSA.erase(LCDecl);
9520
9521 assert((isOpenMPLoopDirective(DKind) ||
9523 "DSA for non-loop vars");
9524
9525 // Check test-expr.
9526 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9527
9528 // Check incr-expr.
9529 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9530 }
9531
9532 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9533 return HasErrors;
9534
9535 // Build the loop's iteration space representation.
9536 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9537 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9538 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9539 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9545 Captures);
9546 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9547 ISC.buildCounterVar(Captures, DSA);
9548 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9549 ISC.buildPrivateCounterVar();
9550 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9551 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9552 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9553 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9554 ISC.getConditionSrcRange();
9555 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9556 ISC.getIncrementSrcRange();
9557 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9558 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9559 ISC.isStrictTestOp();
9560 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9561 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9562 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9563 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9564 ISC.buildFinalCondition(DSA.getCurScope());
9565 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9566 ISC.doesInitDependOnLC();
9567 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9568 ISC.doesCondDependOnLC();
9569 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9570 ISC.getLoopDependentIdx();
9571
9572 HasErrors |=
9573 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9574 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9575 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9576 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9577 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9578 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9579 if (!HasErrors && DSA.isOrderedRegion()) {
9580 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9581 if (CurrentNestedLoopCount <
9582 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9583 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9584 CurrentNestedLoopCount,
9585 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9586 DSA.getOrderedRegionParam().second->setLoopCounter(
9587 CurrentNestedLoopCount,
9588 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9589 }
9590 }
9591 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9592 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9593 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9594 unsigned NumLoops =
9595 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9596 if (CurrentNestedLoopCount >= NumLoops) {
9597 // Erroneous case - clause has some problems.
9598 continue;
9599 }
9600 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9601 Pair.second.size() <= CurrentNestedLoopCount) {
9602 // Erroneous case - clause has some problems.
9603 DependC->setLoopData(CurrentNestedLoopCount, nullptr);
9604 continue;
9605 }
9606 OMPDoacrossKind ODK;
9607 if (DoacrossC && ODK.isSink(DoacrossC) &&
9608 Pair.second.size() <= CurrentNestedLoopCount) {
9609 // Erroneous case - clause has some problems.
9610 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
9611 continue;
9612 }
9613 Expr *CntValue;
9614 SourceLocation DepLoc =
9615 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9616 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9617 (DoacrossC && ODK.isSource(DoacrossC)))
9618 CntValue = ISC.buildOrderedLoopData(
9619 DSA.getCurScope(),
9620 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9621 DepLoc);
9622 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9623 Expr *Cnt = SemaRef
9625 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9626 .get();
9627 if (!Cnt)
9628 continue;
9629 // build CounterVar - 1
9630 Expr *Inc =
9631 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
9632 .get();
9633 CntValue = ISC.buildOrderedLoopData(
9634 DSA.getCurScope(),
9635 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9636 DepLoc, Inc, clang::OO_Minus);
9637 } else
9638 CntValue = ISC.buildOrderedLoopData(
9639 DSA.getCurScope(),
9640 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9641 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9642 Pair.second[CurrentNestedLoopCount].second);
9643 if (DependC)
9644 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9645 else
9646 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9647 }
9648 }
9649
9650 return HasErrors;
9651}
9652
9653/// Build 'VarRef = Start.
9654static ExprResult
9656 ExprResult Start, bool IsNonRectangularLB,
9657 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9658 // Build 'VarRef = Start.
9659 ExprResult NewStart = IsNonRectangularLB
9660 ? Start.get()
9661 : tryBuildCapture(SemaRef, Start.get(), Captures);
9662 if (!NewStart.isUsable())
9663 return ExprError();
9664 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9665 VarRef.get()->getType())) {
9666 NewStart = SemaRef.PerformImplicitConversion(
9667 NewStart.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9668 /*AllowExplicit=*/true);
9669 if (!NewStart.isUsable())
9670 return ExprError();
9671 }
9672
9674 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9675 return Init;
9676}
9677
9678/// Build 'VarRef = Start + Iter * Step'.
9680 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9681 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9682 bool IsNonRectangularLB,
9683 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9684 // Add parentheses (for debugging purposes only).
9685 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9686 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9687 !Step.isUsable())
9688 return ExprError();
9689
9690 ExprResult NewStep = Step;
9691 if (Captures)
9692 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9693 if (NewStep.isInvalid())
9694 return ExprError();
9696 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9697 if (!Update.isUsable())
9698 return ExprError();
9699
9700 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9701 // 'VarRef = Start (+|-) Iter * Step'.
9702 if (!Start.isUsable())
9703 return ExprError();
9704 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9705 if (!NewStart.isUsable())
9706 return ExprError();
9707 if (Captures && !IsNonRectangularLB)
9708 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9709 if (NewStart.isInvalid())
9710 return ExprError();
9711
9712 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9713 ExprResult SavedUpdate = Update;
9714 ExprResult UpdateVal;
9715 if (VarRef.get()->getType()->isOverloadableType() ||
9716 NewStart.get()->getType()->isOverloadableType() ||
9717 Update.get()->getType()->isOverloadableType()) {
9718 Sema::TentativeAnalysisScope Trap(SemaRef);
9719
9720 Update =
9721 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9722 if (Update.isUsable()) {
9723 UpdateVal =
9724 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9725 VarRef.get(), SavedUpdate.get());
9726 if (UpdateVal.isUsable()) {
9727 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9728 UpdateVal.get());
9729 }
9730 }
9731 }
9732
9733 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9734 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9735 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9736 NewStart.get(), SavedUpdate.get());
9737 if (!Update.isUsable())
9738 return ExprError();
9739
9740 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9741 VarRef.get()->getType())) {
9743 Update.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9744 /*AllowExplicit=*/true);
9745 if (!Update.isUsable())
9746 return ExprError();
9747 }
9748
9749 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9750 }
9751 return Update;
9752}
9753
9754/// Convert integer expression \a E to make it have at least \a Bits
9755/// bits.
9756static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9757 if (E == nullptr)
9758 return ExprError();
9759 ASTContext &C = SemaRef.Context;
9760 QualType OldType = E->getType();
9761 unsigned HasBits = C.getTypeSize(OldType);
9762 if (HasBits >= Bits)
9763 return ExprResult(E);
9764 // OK to convert to signed, because new type has more bits than old.
9765 QualType NewType = C.getIntTypeForBitwidth(Bits, /*Signed=*/true);
9766 return SemaRef.PerformImplicitConversion(
9767 E, NewType, AssignmentAction::Converting, /*AllowExplicit=*/true);
9768}
9769
9770/// Check if the given expression \a E is a constant integer that fits
9771/// into \a Bits bits.
9772static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9773 if (E == nullptr)
9774 return false;
9775 if (std::optional<llvm::APSInt> Result =
9776 E->getIntegerConstantExpr(SemaRef.Context))
9777 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9778 return false;
9779}
9780
9781/// Build preinits statement for the given declarations.
9783 MutableArrayRef<Decl *> PreInits) {
9784 if (!PreInits.empty()) {
9785 return new (Context) DeclStmt(
9786 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9788 }
9789 return nullptr;
9790}
9791
9792/// Append the \p Item or the content of a CompoundStmt to the list \p
9793/// TargetList.
9794///
9795/// A CompoundStmt is used as container in case multiple statements need to be
9796/// stored in lieu of using an explicit list. Flattening is necessary because
9797/// contained DeclStmts need to be visible after the execution of the list. Used
9798/// for OpenMP pre-init declarations/statements.
9800 Stmt *Item) {
9801 // nullptr represents an empty list.
9802 if (!Item)
9803 return;
9804
9805 if (auto *CS = dyn_cast<CompoundStmt>(Item))
9806 llvm::append_range(TargetList, CS->body());
9807 else
9808 TargetList.push_back(Item);
9809}
9810
9811/// Build preinits statement for the given declarations.
9812static Stmt *
9814 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9815 if (!Captures.empty()) {
9816 SmallVector<Decl *, 16> PreInits;
9817 for (const auto &Pair : Captures)
9818 PreInits.push_back(Pair.second->getDecl());
9819 return buildPreInits(Context, PreInits);
9820 }
9821 return nullptr;
9822}
9823
9824/// Build pre-init statement for the given statements.
9825static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
9826 if (PreInits.empty())
9827 return nullptr;
9828
9829 SmallVector<Stmt *> Stmts;
9830 for (Stmt *S : PreInits)
9831 appendFlattenedStmtList(Stmts, S);
9832 return CompoundStmt::Create(Context, PreInits, FPOptionsOverride(), {}, {});
9833}
9834
9835/// Build postupdate expression for the given list of postupdates expressions.
9836static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9837 Expr *PostUpdate = nullptr;
9838 if (!PostUpdates.empty()) {
9839 for (Expr *E : PostUpdates) {
9840 Expr *ConvE = S.BuildCStyleCastExpr(
9841 E->getExprLoc(),
9843 E->getExprLoc(), E)
9844 .get();
9845 PostUpdate = PostUpdate
9846 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9847 PostUpdate, ConvE)
9848 .get()
9849 : ConvE;
9850 }
9851 }
9852 return PostUpdate;
9853}
9854
9855/// Look for variables declared in the body parts of a for-loop nest. Used
9856/// for verifying loop nest structure before performing a loop collapse
9857/// operation.
9859 int NestingDepth = 0;
9860 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9861
9862public:
9863 explicit ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl *> &VD)
9864 : VarDecls(VD) {}
9865
9866 bool VisitForStmt(ForStmt *F) override {
9867 ++NestingDepth;
9868 TraverseStmt(F->getBody());
9869 --NestingDepth;
9870 return false;
9871 }
9872
9874 ++NestingDepth;
9875 TraverseStmt(RF->getBody());
9876 --NestingDepth;
9877 return false;
9878 }
9879
9880 bool VisitVarDecl(VarDecl *D) override {
9881 Decl *C = D->getCanonicalDecl();
9882 if (NestingDepth > 0)
9883 VarDecls.insert(C);
9884 return true;
9885 }
9886};
9887
9888/// Called on a for stmt to check itself and nested loops (if any).
9889/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9890/// number of collapsed loops otherwise.
9891static unsigned
9892checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9893 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9894 DSAStackTy &DSA,
9895 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9896 OMPLoopBasedDirective::HelperExprs &Built) {
9897 // If either of the loop expressions exist and contain errors, we bail out
9898 // early because diagnostics have already been emitted and we can't reliably
9899 // check more about the loop.
9900 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->containsErrors()) ||
9901 (OrderedLoopCountExpr && OrderedLoopCountExpr->containsErrors()))
9902 return 0;
9903
9904 unsigned NestedLoopCount = 1;
9905 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9907 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopVarDecls;
9908
9909 if (CollapseLoopCountExpr) {
9910 // Found 'collapse' clause - calculate collapse number.
9911 Expr::EvalResult Result;
9912 if (!CollapseLoopCountExpr->isValueDependent() &&
9913 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9914 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9915
9916 ForVarDeclFinder FVDF{CollapsedLoopVarDecls};
9917 FVDF.TraverseStmt(AStmt);
9918 } else {
9919 Built.clear(/*Size=*/1);
9920 return 1;
9921 }
9922 }
9923 unsigned OrderedLoopCount = 1;
9924 if (OrderedLoopCountExpr) {
9925 // Found 'ordered' clause - calculate collapse number.
9926 Expr::EvalResult EVResult;
9927 if (!OrderedLoopCountExpr->isValueDependent() &&
9928 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9929 SemaRef.getASTContext())) {
9930 llvm::APSInt Result = EVResult.Val.getInt();
9931 if (Result.getLimitedValue() < NestedLoopCount) {
9932 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9933 diag::err_omp_wrong_ordered_loop_count)
9934 << OrderedLoopCountExpr->getSourceRange();
9935 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9936 diag::note_collapse_loop_count)
9937 << CollapseLoopCountExpr->getSourceRange();
9938 }
9939 OrderedLoopCount = Result.getLimitedValue();
9940 } else {
9941 Built.clear(/*Size=*/1);
9942 return 1;
9943 }
9944 }
9945 // This is helper routine for loop directives (e.g., 'for', 'simd',
9946 // 'for simd', etc.).
9947 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9948 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9949 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9950 if (!OMPLoopBasedDirective::doForAllLoops(
9951 AStmt->IgnoreContainers(
9953 SupportsNonPerfectlyNested, NumLoops,
9954 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9955 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9956 &IterSpaces, &Captures,
9957 &CollapsedLoopVarDecls](unsigned Cnt, Stmt *CurStmt) {
9959 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9960 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9961 VarsWithImplicitDSA, IterSpaces, Captures,
9962 CollapsedLoopVarDecls))
9963 return true;
9964 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9965 IterSpaces[Cnt].CounterVar) {
9966 // Handle initialization of captured loop iterator variables.
9967 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9968 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9969 Captures[DRE] = DRE;
9970 }
9971 }
9972 return false;
9973 },
9974 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9975 Stmt *DependentPreInits = Transform->getPreInits();
9976 if (!DependentPreInits)
9977 return;
9978
9979 // Search for pre-init declared variables that need to be captured
9980 // to be referenceable inside the directive.
9981 SmallVector<Stmt *> Constituents;
9982 appendFlattenedStmtList(Constituents, DependentPreInits);
9983 for (Stmt *S : Constituents) {
9984 if (auto *DC = dyn_cast<DeclStmt>(S)) {
9985 for (Decl *C : DC->decls()) {
9986 auto *D = cast<VarDecl>(C);
9988 SemaRef, D, D->getType().getNonReferenceType(),
9989 cast<OMPExecutableDirective>(Transform->getDirective())
9990 ->getBeginLoc());
9991 Captures[Ref] = Ref;
9992 }
9993 }
9994 }
9995 }))
9996 return 0;
9997
9998 Built.clear(/*size=*/NestedLoopCount);
9999
10000 if (SemaRef.CurContext->isDependentContext())
10001 return NestedLoopCount;
10002
10003 // An example of what is generated for the following code:
10004 //
10005 // #pragma omp simd collapse(2) ordered(2)
10006 // for (i = 0; i < NI; ++i)
10007 // for (k = 0; k < NK; ++k)
10008 // for (j = J0; j < NJ; j+=2) {
10009 // <loop body>
10010 // }
10011 //
10012 // We generate the code below.
10013 // Note: the loop body may be outlined in CodeGen.
10014 // Note: some counters may be C++ classes, operator- is used to find number of
10015 // iterations and operator+= to calculate counter value.
10016 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
10017 // or i64 is currently supported).
10018 //
10019 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
10020 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
10021 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
10022 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
10023 // // similar updates for vars in clauses (e.g. 'linear')
10024 // <loop body (using local i and j)>
10025 // }
10026 // i = NI; // assign final values of counters
10027 // j = NJ;
10028 //
10029
10030 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
10031 // the iteration counts of the collapsed for loops.
10032 // Precondition tests if there is at least one iteration (all conditions are
10033 // true).
10034 auto PreCond = ExprResult(IterSpaces[0].PreCond);
10035 Expr *N0 = IterSpaces[0].NumIterations;
10036 ExprResult LastIteration32 = widenIterationCount(
10037 /*Bits=*/32,
10038 SemaRef
10039 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
10041 /*AllowExplicit=*/true)
10042 .get(),
10043 SemaRef);
10044 ExprResult LastIteration64 = widenIterationCount(
10045 /*Bits=*/64,
10046 SemaRef
10047 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
10049 /*AllowExplicit=*/true)
10050 .get(),
10051 SemaRef);
10052
10053 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
10054 return NestedLoopCount;
10055
10056 ASTContext &C = SemaRef.Context;
10057 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
10058
10059 Scope *CurScope = DSA.getCurScope();
10060 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
10061 if (PreCond.isUsable()) {
10062 PreCond =
10063 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
10064 PreCond.get(), IterSpaces[Cnt].PreCond);
10065 }
10066 Expr *N = IterSpaces[Cnt].NumIterations;
10067 SourceLocation Loc = N->getExprLoc();
10068 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
10069 if (LastIteration32.isUsable())
10070 LastIteration32 = SemaRef.BuildBinOp(
10071 CurScope, Loc, BO_Mul, LastIteration32.get(),
10072 SemaRef
10075 /*AllowExplicit=*/true)
10076 .get());
10077 if (LastIteration64.isUsable())
10078 LastIteration64 = SemaRef.BuildBinOp(
10079 CurScope, Loc, BO_Mul, LastIteration64.get(),
10080 SemaRef
10083 /*AllowExplicit=*/true)
10084 .get());
10085 }
10086
10087 // Choose either the 32-bit or 64-bit version.
10088 ExprResult LastIteration = LastIteration64;
10089 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
10090 (LastIteration32.isUsable() &&
10091 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
10092 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
10093 fitsInto(
10094 /*Bits=*/32,
10095 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
10096 LastIteration64.get(), SemaRef))))
10097 LastIteration = LastIteration32;
10098 QualType VType = LastIteration.get()->getType();
10099 QualType RealVType = VType;
10100 QualType StrideVType = VType;
10101 if (isOpenMPTaskLoopDirective(DKind)) {
10102 VType =
10103 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
10104 StrideVType =
10105 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
10106 }
10107
10108 if (!LastIteration.isUsable())
10109 return 0;
10110
10111 // Save the number of iterations.
10112 ExprResult NumIterations = LastIteration;
10113 {
10114 LastIteration = SemaRef.BuildBinOp(
10115 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
10116 LastIteration.get(),
10117 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
10118 if (!LastIteration.isUsable())
10119 return 0;
10120 }
10121
10122 // Calculate the last iteration number beforehand instead of doing this on
10123 // each iteration. Do not do this if the number of iterations may be kfold-ed.
10124 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
10125 ExprResult CalcLastIteration;
10126 if (!IsConstant) {
10127 ExprResult SaveRef =
10128 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
10129 LastIteration = SaveRef;
10130
10131 // Prepare SaveRef + 1.
10132 NumIterations = SemaRef.BuildBinOp(
10133 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
10134 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
10135 if (!NumIterations.isUsable())
10136 return 0;
10137 }
10138
10139 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
10140
10141 // Build variables passed into runtime, necessary for worksharing directives.
10142 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
10147 // Lower bound variable, initialized with zero.
10148 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
10149 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
10150 SemaRef.AddInitializerToDecl(LBDecl,
10151 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10152 /*DirectInit=*/false);
10153
10154 // Upper bound variable, initialized with last iteration number.
10155 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
10156 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
10157 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
10158 /*DirectInit=*/false);
10159
10160 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
10161 // This will be used to implement clause 'lastprivate'.
10162 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
10163 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
10164 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
10165 SemaRef.AddInitializerToDecl(ILDecl,
10166 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10167 /*DirectInit=*/false);
10168
10169 // Stride variable returned by runtime (we initialize it to 1 by default).
10170 VarDecl *STDecl =
10171 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
10172 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
10173 SemaRef.AddInitializerToDecl(STDecl,
10174 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
10175 /*DirectInit=*/false);
10176
10177 // Build expression: UB = min(UB, LastIteration)
10178 // It is necessary for CodeGen of directives with static scheduling.
10179 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
10180 UB.get(), LastIteration.get());
10181 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10182 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
10183 LastIteration.get(), UB.get());
10184 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
10185 CondOp.get());
10186 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue=*/false);
10187
10188 // If we have a combined directive that combines 'distribute', 'for' or
10189 // 'simd' we need to be able to access the bounds of the schedule of the
10190 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
10191 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
10193 // Lower bound variable, initialized with zero.
10194 VarDecl *CombLBDecl =
10195 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
10196 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
10197 SemaRef.AddInitializerToDecl(
10198 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10199 /*DirectInit=*/false);
10200
10201 // Upper bound variable, initialized with last iteration number.
10202 VarDecl *CombUBDecl =
10203 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
10204 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
10205 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
10206 /*DirectInit=*/false);
10207
10208 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
10209 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
10210 ExprResult CombCondOp =
10211 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
10212 LastIteration.get(), CombUB.get());
10213 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
10214 CombCondOp.get());
10215 CombEUB =
10216 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue=*/false);
10217
10218 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
10219 // We expect to have at least 2 more parameters than the 'parallel'
10220 // directive does - the lower and upper bounds of the previous schedule.
10221 assert(CD->getNumParams() >= 4 &&
10222 "Unexpected number of parameters in loop combined directive");
10223
10224 // Set the proper type for the bounds given what we learned from the
10225 // enclosed loops.
10226 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
10227 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
10228
10229 // Previous lower and upper bounds are obtained from the region
10230 // parameters.
10231 PrevLB =
10232 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
10233 PrevUB =
10234 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
10235 }
10236 }
10237
10238 // Build the iteration variable and its initialization before loop.
10239 ExprResult IV;
10240 ExprResult Init, CombInit;
10241 {
10242 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
10243 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
10244 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
10249 ? LB.get()
10250 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10251 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
10252 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue=*/false);
10253
10255 Expr *CombRHS =
10260 ? CombLB.get()
10261 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10262 CombInit =
10263 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
10264 CombInit =
10265 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue=*/false);
10266 }
10267 }
10268
10269 bool UseStrictCompare =
10270 RealVType->hasUnsignedIntegerRepresentation() &&
10271 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
10272 return LIS.IsStrictCompare;
10273 });
10274 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10275 // unsigned IV)) for worksharing loops.
10276 SourceLocation CondLoc = AStmt->getBeginLoc();
10277 Expr *BoundUB = UB.get();
10278 if (UseStrictCompare) {
10279 BoundUB =
10280 SemaRef
10281 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10282 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10283 .get();
10284 BoundUB =
10285 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue=*/false).get();
10286 }
10292 ? SemaRef.BuildBinOp(CurScope, CondLoc,
10293 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
10294 BoundUB)
10295 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10296 NumIterations.get());
10297 ExprResult CombDistCond;
10299 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10300 NumIterations.get());
10301 }
10302
10303 ExprResult CombCond;
10305 Expr *BoundCombUB = CombUB.get();
10306 if (UseStrictCompare) {
10307 BoundCombUB =
10308 SemaRef
10309 .BuildBinOp(
10310 CurScope, CondLoc, BO_Add, BoundCombUB,
10311 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10312 .get();
10313 BoundCombUB =
10314 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue=*/false)
10315 .get();
10316 }
10317 CombCond =
10318 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10319 IV.get(), BoundCombUB);
10320 }
10321 // Loop increment (IV = IV + 1)
10322 SourceLocation IncLoc = AStmt->getBeginLoc();
10323 ExprResult Inc =
10324 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
10325 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
10326 if (!Inc.isUsable())
10327 return 0;
10328 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
10329 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue=*/false);
10330 if (!Inc.isUsable())
10331 return 0;
10332
10333 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10334 // Used for directives with static scheduling.
10335 // In combined construct, add combined version that use CombLB and CombUB
10336 // base variables for the update
10337 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10342 // LB + ST
10343 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
10344 if (!NextLB.isUsable())
10345 return 0;
10346 // LB = LB + ST
10347 NextLB =
10348 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
10349 NextLB =
10350 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue=*/false);
10351 if (!NextLB.isUsable())
10352 return 0;
10353 // UB + ST
10354 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
10355 if (!NextUB.isUsable())
10356 return 0;
10357 // UB = UB + ST
10358 NextUB =
10359 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
10360 NextUB =
10361 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue=*/false);
10362 if (!NextUB.isUsable())
10363 return 0;
10365 CombNextLB =
10366 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
10367 if (!NextLB.isUsable())
10368 return 0;
10369 // LB = LB + ST
10370 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
10371 CombNextLB.get());
10372 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
10373 /*DiscardedValue=*/false);
10374 if (!CombNextLB.isUsable())
10375 return 0;
10376 // UB + ST
10377 CombNextUB =
10378 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
10379 if (!CombNextUB.isUsable())
10380 return 0;
10381 // UB = UB + ST
10382 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
10383 CombNextUB.get());
10384 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
10385 /*DiscardedValue=*/false);
10386 if (!CombNextUB.isUsable())
10387 return 0;
10388 }
10389 }
10390
10391 // Create increment expression for distribute loop when combined in a same
10392 // directive with for as IV = IV + ST; ensure upper bound expression based
10393 // on PrevUB instead of NumIterations - used to implement 'for' when found
10394 // in combination with 'distribute', like in 'distribute parallel for'
10395 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10396 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10398 DistCond = SemaRef.BuildBinOp(
10399 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10400 assert(DistCond.isUsable() && "distribute cond expr was not built");
10401
10402 DistInc =
10403 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10404 assert(DistInc.isUsable() && "distribute inc expr was not built");
10405 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10406 DistInc.get());
10407 DistInc =
10408 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue=*/false);
10409 assert(DistInc.isUsable() && "distribute inc expr was not built");
10410
10411 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10412 // construct
10413 ExprResult NewPrevUB = PrevUB;
10414 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10415 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10416 PrevUB.get()->getType())) {
10417 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10418 DistEUBLoc,
10420 DistEUBLoc, NewPrevUB.get());
10421 if (!NewPrevUB.isUsable())
10422 return 0;
10423 }
10424 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10425 UB.get(), NewPrevUB.get());
10426 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10427 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10428 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10429 CondOp.get());
10430 PrevEUB =
10431 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue=*/false);
10432
10433 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10434 // parallel for is in combination with a distribute directive with
10435 // schedule(static, 1)
10436 Expr *BoundPrevUB = PrevUB.get();
10437 if (UseStrictCompare) {
10438 BoundPrevUB =
10439 SemaRef
10440 .BuildBinOp(
10441 CurScope, CondLoc, BO_Add, BoundPrevUB,
10442 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10443 .get();
10444 BoundPrevUB =
10445 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue=*/false)
10446 .get();
10447 }
10448 ParForInDistCond =
10449 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10450 IV.get(), BoundPrevUB);
10451 }
10452
10453 // Build updates and final values of the loop counters.
10454 bool HasErrors = false;
10455 Built.Counters.resize(NestedLoopCount);
10456 Built.Inits.resize(NestedLoopCount);
10457 Built.Updates.resize(NestedLoopCount);
10458 Built.Finals.resize(NestedLoopCount);
10459 Built.DependentCounters.resize(NestedLoopCount);
10460 Built.DependentInits.resize(NestedLoopCount);
10461 Built.FinalsConditions.resize(NestedLoopCount);
10462 {
10463 // We implement the following algorithm for obtaining the
10464 // original loop iteration variable values based on the
10465 // value of the collapsed loop iteration variable IV.
10466 //
10467 // Let n+1 be the number of collapsed loops in the nest.
10468 // Iteration variables (I0, I1, .... In)
10469 // Iteration counts (N0, N1, ... Nn)
10470 //
10471 // Acc = IV;
10472 //
10473 // To compute Ik for loop k, 0 <= k <= n, generate:
10474 // Prod = N(k+1) * N(k+2) * ... * Nn;
10475 // Ik = Acc / Prod;
10476 // Acc -= Ik * Prod;
10477 //
10478 ExprResult Acc = IV;
10479 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10480 LoopIterationSpace &IS = IterSpaces[Cnt];
10481 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10482 ExprResult Iter;
10483
10484 // Compute prod
10485 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10486 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10487 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10488 IterSpaces[K].NumIterations);
10489
10490 // Iter = Acc / Prod
10491 // If there is at least one more inner loop to avoid
10492 // multiplication by 1.
10493 if (Cnt + 1 < NestedLoopCount)
10494 Iter =
10495 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10496 else
10497 Iter = Acc;
10498 if (!Iter.isUsable()) {
10499 HasErrors = true;
10500 break;
10501 }
10502
10503 // Update Acc:
10504 // Acc -= Iter * Prod
10505 // Check if there is at least one more inner loop to avoid
10506 // multiplication by 1.
10507 if (Cnt + 1 < NestedLoopCount)
10508 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10509 Prod.get());
10510 else
10511 Prod = Iter;
10512 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10513
10514 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10515 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10516 DeclRefExpr *CounterVar = buildDeclRefExpr(
10517 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10518 /*RefersToCapture=*/true);
10520 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10521 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10522 if (!Init.isUsable()) {
10523 HasErrors = true;
10524 break;
10525 }
10527 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10528 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10529 if (!Update.isUsable()) {
10530 HasErrors = true;
10531 break;
10532 }
10533
10534 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10535 ExprResult Final =
10536 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10537 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10538 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10539 if (!Final.isUsable()) {
10540 HasErrors = true;
10541 break;
10542 }
10543
10544 if (!Update.isUsable() || !Final.isUsable()) {
10545 HasErrors = true;
10546 break;
10547 }
10548 // Save results
10549 Built.Counters[Cnt] = IS.CounterVar;
10550 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10551 Built.Inits[Cnt] = Init.get();
10552 Built.Updates[Cnt] = Update.get();
10553 Built.Finals[Cnt] = Final.get();
10554 Built.DependentCounters[Cnt] = nullptr;
10555 Built.DependentInits[Cnt] = nullptr;
10556 Built.FinalsConditions[Cnt] = nullptr;
10557 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10558 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10559 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10560 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10561 }
10562 }
10563 }
10564
10565 if (HasErrors)
10566 return 0;
10567
10568 // Save results
10569 Built.IterationVarRef = IV.get();
10570 Built.LastIteration = LastIteration.get();
10571 Built.NumIterations = NumIterations.get();
10572 Built.CalcLastIteration = SemaRef
10573 .ActOnFinishFullExpr(CalcLastIteration.get(),
10574 /*DiscardedValue=*/false)
10575 .get();
10576 Built.PreCond = PreCond.get();
10577 Built.PreInits = buildPreInits(C, Captures);
10578 Built.Cond = Cond.get();
10579 Built.Init = Init.get();
10580 Built.Inc = Inc.get();
10581 Built.LB = LB.get();
10582 Built.UB = UB.get();
10583 Built.IL = IL.get();
10584 Built.ST = ST.get();
10585 Built.EUB = EUB.get();
10586 Built.NLB = NextLB.get();
10587 Built.NUB = NextUB.get();
10588 Built.PrevLB = PrevLB.get();
10589 Built.PrevUB = PrevUB.get();
10590 Built.DistInc = DistInc.get();
10591 Built.PrevEUB = PrevEUB.get();
10592 Built.DistCombinedFields.LB = CombLB.get();
10593 Built.DistCombinedFields.UB = CombUB.get();
10594 Built.DistCombinedFields.EUB = CombEUB.get();
10595 Built.DistCombinedFields.Init = CombInit.get();
10596 Built.DistCombinedFields.Cond = CombCond.get();
10597 Built.DistCombinedFields.NLB = CombNextLB.get();
10598 Built.DistCombinedFields.NUB = CombNextUB.get();
10599 Built.DistCombinedFields.DistCond = CombDistCond.get();
10600 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10601
10602 return NestedLoopCount;
10603}
10604
10606 auto CollapseClauses =
10607 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10608 if (CollapseClauses.begin() != CollapseClauses.end())
10609 return (*CollapseClauses.begin())->getNumForLoops();
10610 return nullptr;
10611}
10612
10614 auto OrderedClauses =
10615 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10616 if (OrderedClauses.begin() != OrderedClauses.end())
10617 return (*OrderedClauses.begin())->getNumForLoops();
10618 return nullptr;
10619}
10620
10622 const ArrayRef<OMPClause *> Clauses) {
10623 const OMPSafelenClause *Safelen = nullptr;
10624 const OMPSimdlenClause *Simdlen = nullptr;
10625
10626 for (const OMPClause *Clause : Clauses) {
10627 if (Clause->getClauseKind() == OMPC_safelen)
10628 Safelen = cast<OMPSafelenClause>(Clause);
10629 else if (Clause->getClauseKind() == OMPC_simdlen)
10630 Simdlen = cast<OMPSimdlenClause>(Clause);
10631 if (Safelen && Simdlen)
10632 break;
10633 }
10634
10635 if (Simdlen && Safelen) {
10636 const Expr *SimdlenLength = Simdlen->getSimdlen();
10637 const Expr *SafelenLength = Safelen->getSafelen();
10638 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10639 SimdlenLength->isInstantiationDependent() ||
10640 SimdlenLength->containsUnexpandedParameterPack())
10641 return false;
10642 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10643 SafelenLength->isInstantiationDependent() ||
10644 SafelenLength->containsUnexpandedParameterPack())
10645 return false;
10646 Expr::EvalResult SimdlenResult, SafelenResult;
10647 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10648 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10649 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10650 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10651 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10652 // If both simdlen and safelen clauses are specified, the value of the
10653 // simdlen parameter must be less than or equal to the value of the safelen
10654 // parameter.
10655 if (SimdlenRes > SafelenRes) {
10656 S.Diag(SimdlenLength->getExprLoc(),
10657 diag::err_omp_wrong_simdlen_safelen_values)
10658 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10659 return true;
10660 }
10661 }
10662 return false;
10663}
10664
10666 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10667 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10668 if (!AStmt)
10669 return StmtError();
10670
10671 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_simd, AStmt);
10672
10673 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10674 OMPLoopBasedDirective::HelperExprs B;
10675 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10676 // define the nested loops number.
10677 unsigned NestedLoopCount = checkOpenMPLoop(
10678 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10679 CS, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10680 if (NestedLoopCount == 0)
10681 return StmtError();
10682
10683 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10684 return StmtError();
10685
10687 return StmtError();
10688
10689 auto *SimdDirective = OMPSimdDirective::Create(
10690 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10691 return SimdDirective;
10692}
10693
10695 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10696 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10697 if (!AStmt)
10698 return StmtError();
10699
10700 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10701 OMPLoopBasedDirective::HelperExprs B;
10702 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10703 // define the nested loops number.
10704 unsigned NestedLoopCount = checkOpenMPLoop(
10705 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10706 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10707 if (NestedLoopCount == 0)
10708 return StmtError();
10709
10710 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10711 return StmtError();
10712
10713 auto *ForDirective = OMPForDirective::Create(
10714 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10715 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10716 return ForDirective;
10717}
10718
10720 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10721 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10722 if (!AStmt)
10723 return StmtError();
10724
10725 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_for_simd, AStmt);
10726
10727 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10728 OMPLoopBasedDirective::HelperExprs B;
10729 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10730 // define the nested loops number.
10731 unsigned NestedLoopCount =
10732 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10733 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10734 VarsWithImplicitDSA, B);
10735 if (NestedLoopCount == 0)
10736 return StmtError();
10737
10738 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10739 return StmtError();
10740
10742 return StmtError();
10743
10744 return OMPForSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
10745 NestedLoopCount, Clauses, AStmt, B);
10746}
10747
10749 Stmt *AStmt, DSAStackTy *Stack) {
10750 if (!AStmt)
10751 return true;
10752
10753 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10754 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
10755 auto BaseStmt = AStmt;
10756 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10757 BaseStmt = CS->getCapturedStmt();
10758 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10759 auto S = C->children();
10760 if (S.begin() == S.end())
10761 return true;
10762 // All associated statements must be '#pragma omp section' except for
10763 // the first one.
10764 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10765 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10766 if (SectionStmt)
10767 SemaRef.Diag(SectionStmt->getBeginLoc(),
10768 diag::err_omp_sections_substmt_not_section)
10769 << getOpenMPDirectiveName(DKind, OMPVersion);
10770 return true;
10771 }
10772 cast<OMPSectionDirective>(SectionStmt)
10773 ->setHasCancel(Stack->isCancelRegion());
10774 }
10775 } else {
10776 SemaRef.Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10777 << getOpenMPDirectiveName(DKind, OMPVersion);
10778 return true;
10779 }
10780 return false;
10781}
10782
10785 Stmt *AStmt, SourceLocation StartLoc,
10786 SourceLocation EndLoc) {
10787 if (checkSectionsDirective(SemaRef, OMPD_sections, AStmt, DSAStack))
10788 return StmtError();
10789
10790 SemaRef.setFunctionHasBranchProtectedScope();
10791
10792 return OMPSectionsDirective::Create(
10793 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10794 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10795}
10796
10798 SourceLocation StartLoc,
10799 SourceLocation EndLoc) {
10800 if (!AStmt)
10801 return StmtError();
10802
10803 SemaRef.setFunctionHasBranchProtectedScope();
10804 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10805
10806 return OMPSectionDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt,
10807 DSAStack->isCancelRegion());
10808}
10809
10811 E = E->IgnoreParenCasts()->IgnoreImplicit();
10812 if (auto *CE = dyn_cast<CallExpr>(E))
10813 if (CE->getDirectCallee())
10814 return E;
10815 return nullptr;
10816}
10817
10820 Stmt *AStmt, SourceLocation StartLoc,
10821 SourceLocation EndLoc) {
10822 if (!AStmt)
10823 return StmtError();
10824
10825 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10826
10827 // 5.1 OpenMP
10828 // expression-stmt : an expression statement with one of the following forms:
10829 // expression = target-call ( [expression-list] );
10830 // target-call ( [expression-list] );
10831
10832 SourceLocation TargetCallLoc;
10833
10834 if (!SemaRef.CurContext->isDependentContext()) {
10835 Expr *TargetCall = nullptr;
10836
10837 auto *E = dyn_cast<Expr>(S);
10838 if (!E) {
10839 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10840 return StmtError();
10841 }
10842
10843 E = E->IgnoreParenCasts()->IgnoreImplicit();
10844
10845 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10846 if (BO->getOpcode() == BO_Assign)
10847 TargetCall = getDirectCallExpr(BO->getRHS());
10848 } else {
10849 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10850 if (COCE->getOperator() == OO_Equal)
10851 TargetCall = getDirectCallExpr(COCE->getArg(1));
10852 if (!TargetCall)
10853 TargetCall = getDirectCallExpr(E);
10854 }
10855 if (!TargetCall) {
10856 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10857 return StmtError();
10858 }
10859 TargetCallLoc = TargetCall->getExprLoc();
10860 }
10861
10862 SemaRef.setFunctionHasBranchProtectedScope();
10863
10864 return OMPDispatchDirective::Create(getASTContext(), StartLoc, EndLoc,
10865 Clauses, AStmt, TargetCallLoc);
10866}
10867
10870 DSAStackTy *Stack) {
10871 bool ErrorFound = false;
10872 for (OMPClause *C : Clauses) {
10873 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10874 for (Expr *RefExpr : LPC->varlist()) {
10875 SourceLocation ELoc;
10876 SourceRange ERange;
10877 Expr *SimpleRefExpr = RefExpr;
10878 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10879 if (ValueDecl *D = Res.first) {
10880 auto &&Info = Stack->isLoopControlVariable(D);
10881 if (!Info.first) {
10882 unsigned OMPVersion = S.getLangOpts().OpenMP;
10883 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10884 << getOpenMPDirectiveName(K, OMPVersion);
10885 ErrorFound = true;
10886 }
10887 }
10888 }
10889 }
10890 }
10891 return ErrorFound;
10892}
10893
10895 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10896 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10897 if (!AStmt)
10898 return StmtError();
10899
10900 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10901 // A list item may not appear in a lastprivate clause unless it is the
10902 // loop iteration variable of a loop that is associated with the construct.
10903 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack))
10904 return StmtError();
10905
10906 setBranchProtectedScope(SemaRef, OMPD_loop, AStmt);
10907
10908 OMPLoopDirective::HelperExprs B;
10909 // In presence of clause 'collapse', it will define the nested loops number.
10910 unsigned NestedLoopCount = checkOpenMPLoop(
10911 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10912 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10913 if (NestedLoopCount == 0)
10914 return StmtError();
10915
10916 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10917 "omp loop exprs were not built");
10918
10919 return OMPGenericLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
10920 NestedLoopCount, Clauses, AStmt, B);
10921}
10922
10924 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10925 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10926 if (!AStmt)
10927 return StmtError();
10928
10929 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10930 // A list item may not appear in a lastprivate clause unless it is the
10931 // loop iteration variable of a loop that is associated with the construct.
10932 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack))
10933 return StmtError();
10934
10935 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_teams_loop, AStmt);
10936
10937 OMPLoopDirective::HelperExprs B;
10938 // In presence of clause 'collapse', it will define the nested loops number.
10939 unsigned NestedLoopCount =
10940 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10941 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10942 VarsWithImplicitDSA, B);
10943 if (NestedLoopCount == 0)
10944 return StmtError();
10945
10946 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10947 "omp loop exprs were not built");
10948
10949 DSAStack->setParentTeamsRegionLoc(StartLoc);
10950
10952 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10953}
10954
10956 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10957 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10958 if (!AStmt)
10959 return StmtError();
10960
10961 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10962 // A list item may not appear in a lastprivate clause unless it is the
10963 // loop iteration variable of a loop that is associated with the construct.
10964 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop,
10965 DSAStack))
10966 return StmtError();
10967
10968 CapturedStmt *CS =
10969 setBranchProtectedScope(SemaRef, OMPD_target_teams_loop, AStmt);
10970
10971 OMPLoopDirective::HelperExprs B;
10972 // In presence of clause 'collapse', it will define the nested loops number.
10973 unsigned NestedLoopCount =
10974 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10975 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10976 VarsWithImplicitDSA, B);
10977 if (NestedLoopCount == 0)
10978 return StmtError();
10979
10980 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10981 "omp loop exprs were not built");
10982
10984 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10986}
10987
10989 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10990 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10991 if (!AStmt)
10992 return StmtError();
10993
10994 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10995 // A list item may not appear in a lastprivate clause unless it is the
10996 // loop iteration variable of a loop that is associated with the construct.
10997 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_parallel_loop,
10998 DSAStack))
10999 return StmtError();
11000
11001 CapturedStmt *CS =
11002 setBranchProtectedScope(SemaRef, OMPD_parallel_loop, AStmt);
11003
11004 OMPLoopDirective::HelperExprs B;
11005 // In presence of clause 'collapse', it will define the nested loops number.
11006 unsigned NestedLoopCount =
11007 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
11008 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
11009 VarsWithImplicitDSA, B);
11010 if (NestedLoopCount == 0)
11011 return StmtError();
11012
11013 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11014 "omp loop exprs were not built");
11015
11017 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11018}
11019
11021 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11022 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11023 if (!AStmt)
11024 return StmtError();
11025
11026 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11027 // A list item may not appear in a lastprivate clause unless it is the
11028 // loop iteration variable of a loop that is associated with the construct.
11029 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_parallel_loop,
11030 DSAStack))
11031 return StmtError();
11032
11033 CapturedStmt *CS =
11034 setBranchProtectedScope(SemaRef, OMPD_target_parallel_loop, AStmt);
11035
11036 OMPLoopDirective::HelperExprs B;
11037 // In presence of clause 'collapse', it will define the nested loops number.
11038 unsigned NestedLoopCount =
11039 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
11040 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
11041 VarsWithImplicitDSA, B);
11042 if (NestedLoopCount == 0)
11043 return StmtError();
11044
11045 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11046 "omp loop exprs were not built");
11047
11049 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11050}
11051
11053 Stmt *AStmt,
11054 SourceLocation StartLoc,
11055 SourceLocation EndLoc) {
11056 if (!AStmt)
11057 return StmtError();
11058
11059 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11060
11061 SemaRef.setFunctionHasBranchProtectedScope();
11062
11063 // OpenMP [2.7.3, single Construct, Restrictions]
11064 // The copyprivate clause must not be used with the nowait clause.
11065 const OMPClause *Nowait = nullptr;
11066 const OMPClause *Copyprivate = nullptr;
11067 for (const OMPClause *Clause : Clauses) {
11068 if (Clause->getClauseKind() == OMPC_nowait)
11069 Nowait = Clause;
11070 else if (Clause->getClauseKind() == OMPC_copyprivate)
11071 Copyprivate = Clause;
11072 if (Copyprivate && Nowait) {
11073 Diag(Copyprivate->getBeginLoc(),
11074 diag::err_omp_single_copyprivate_with_nowait);
11075 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
11076 return StmtError();
11077 }
11078 }
11079
11080 return OMPSingleDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11081 AStmt);
11082}
11083
11085 SourceLocation StartLoc,
11086 SourceLocation EndLoc) {
11087 if (!AStmt)
11088 return StmtError();
11089
11090 SemaRef.setFunctionHasBranchProtectedScope();
11091
11092 return OMPMasterDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt);
11093}
11094
11096 Stmt *AStmt,
11097 SourceLocation StartLoc,
11098 SourceLocation EndLoc) {
11099 if (!AStmt)
11100 return StmtError();
11101
11102 SemaRef.setFunctionHasBranchProtectedScope();
11103
11104 return OMPMaskedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11105 AStmt);
11106}
11107
11109 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
11110 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
11111 if (!AStmt)
11112 return StmtError();
11113
11114 bool ErrorFound = false;
11115 llvm::APSInt Hint;
11116 SourceLocation HintLoc;
11117 bool DependentHint = false;
11118 for (const OMPClause *C : Clauses) {
11119 if (C->getClauseKind() == OMPC_hint) {
11120 if (!DirName.getName()) {
11121 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
11122 ErrorFound = true;
11123 }
11124 Expr *E = cast<OMPHintClause>(C)->getHint();
11125 if (E->isTypeDependent() || E->isValueDependent() ||
11127 DependentHint = true;
11128 } else {
11130 HintLoc = C->getBeginLoc();
11131 }
11132 }
11133 }
11134 if (ErrorFound)
11135 return StmtError();
11136 const auto Pair = DSAStack->getCriticalWithHint(DirName);
11137 if (Pair.first && DirName.getName() && !DependentHint) {
11138 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
11139 Diag(StartLoc, diag::err_omp_critical_with_hint);
11140 if (HintLoc.isValid())
11141 Diag(HintLoc, diag::note_omp_critical_hint_here)
11142 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
11143 else
11144 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
11145 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
11146 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
11147 << 1
11148 << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()),
11149 /*Radix=*/10, /*Signed=*/false);
11150 } else {
11151 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
11152 }
11153 }
11154 }
11155
11156 SemaRef.setFunctionHasBranchProtectedScope();
11157
11158 auto *Dir = OMPCriticalDirective::Create(getASTContext(), DirName, StartLoc,
11159 EndLoc, Clauses, AStmt);
11160 if (!Pair.first && DirName.getName() && !DependentHint)
11161 DSAStack->addCriticalWithHint(Dir, Hint);
11162 return Dir;
11163}
11164
11166 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11167 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11168 if (!AStmt)
11169 return StmtError();
11170
11171 setBranchProtectedScope(SemaRef, OMPD_parallel_for, AStmt);
11172
11173 OMPLoopBasedDirective::HelperExprs B;
11174 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11175 // define the nested loops number.
11176 unsigned NestedLoopCount =
11177 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
11178 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
11179 VarsWithImplicitDSA, B);
11180 if (NestedLoopCount == 0)
11181 return StmtError();
11182
11183 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11184 return StmtError();
11185
11186 return OMPParallelForDirective::Create(
11187 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11188 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11189}
11190
11192 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11193 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11194 if (!AStmt)
11195 return StmtError();
11196
11197 CapturedStmt *CS =
11198 setBranchProtectedScope(SemaRef, OMPD_parallel_for_simd, AStmt);
11199
11200 OMPLoopBasedDirective::HelperExprs B;
11201 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11202 // define the nested loops number.
11203 unsigned NestedLoopCount =
11204 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
11205 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
11206 VarsWithImplicitDSA, B);
11207 if (NestedLoopCount == 0)
11208 return StmtError();
11209
11210 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11211 return StmtError();
11212
11214 return StmtError();
11215
11216 return OMPParallelForSimdDirective::Create(
11217 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11218}
11219
11221 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11222 SourceLocation EndLoc) {
11223 if (!AStmt)
11224 return StmtError();
11225
11226 setBranchProtectedScope(SemaRef, OMPD_parallel_master, AStmt);
11227
11228 return OMPParallelMasterDirective::Create(
11229 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11230 DSAStack->getTaskgroupReductionRef());
11231}
11232
11234 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11235 SourceLocation EndLoc) {
11236 if (!AStmt)
11237 return StmtError();
11238
11239 setBranchProtectedScope(SemaRef, OMPD_parallel_masked, AStmt);
11240
11241 return OMPParallelMaskedDirective::Create(
11242 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11243 DSAStack->getTaskgroupReductionRef());
11244}
11245
11247 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11248 SourceLocation EndLoc) {
11249 if (checkSectionsDirective(SemaRef, OMPD_parallel_sections, AStmt, DSAStack))
11250 return StmtError();
11251
11252 SemaRef.setFunctionHasBranchProtectedScope();
11253
11254 return OMPParallelSectionsDirective::Create(
11255 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11256 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11257}
11258
11259/// Find and diagnose mutually exclusive clause kinds.
11261 Sema &S, ArrayRef<OMPClause *> Clauses,
11262 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11263 const OMPClause *PrevClause = nullptr;
11264 bool ErrorFound = false;
11265 for (const OMPClause *C : Clauses) {
11266 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
11267 if (!PrevClause) {
11268 PrevClause = C;
11269 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11270 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11271 << getOpenMPClauseNameForDiag(C->getClauseKind())
11272 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11273 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
11274 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11275 ErrorFound = true;
11276 }
11277 }
11278 }
11279 return ErrorFound;
11280}
11281
11283 Stmt *AStmt,
11284 SourceLocation StartLoc,
11285 SourceLocation EndLoc) {
11286 if (!AStmt)
11287 return StmtError();
11288
11289 // OpenMP 5.0, 2.10.1 task Construct
11290 // If a detach clause appears on the directive, then a mergeable clause cannot
11291 // appear on the same directive.
11293 {OMPC_detach, OMPC_mergeable}))
11294 return StmtError();
11295
11296 setBranchProtectedScope(SemaRef, OMPD_task, AStmt);
11297
11298 return OMPTaskDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11299 AStmt, DSAStack->isCancelRegion());
11300}
11301
11303 SourceLocation EndLoc) {
11304 return OMPTaskyieldDirective::Create(getASTContext(), StartLoc, EndLoc);
11305}
11306
11308 SourceLocation EndLoc) {
11309 return OMPBarrierDirective::Create(getASTContext(), StartLoc, EndLoc);
11310}
11311
11313 SourceLocation StartLoc,
11314 SourceLocation EndLoc,
11315 bool InExContext) {
11316 const OMPAtClause *AtC =
11317 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11318
11319 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11320 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11321 return StmtError();
11322 }
11323
11324 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11325 const OMPSeverityClause *SeverityC =
11326 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11327 const OMPMessageClause *MessageC =
11328 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11329 std::optional<std::string> SL =
11330 MessageC ? MessageC->tryEvaluateString(getASTContext()) : std::nullopt;
11331
11332 if (MessageC && !SL)
11333 Diag(MessageC->getMessageString()->getBeginLoc(),
11334 diag::warn_clause_expected_string)
11335 << getOpenMPClauseNameForDiag(OMPC_message) << 1;
11336 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11337 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11338 << SL.value_or("WARNING");
11339 else
11340 Diag(StartLoc, diag::err_diagnose_if_succeeded) << SL.value_or("ERROR");
11341 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11342 return StmtError();
11343 }
11344
11345 return OMPErrorDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11346}
11347
11350 SourceLocation StartLoc,
11351 SourceLocation EndLoc) {
11352 const OMPNowaitClause *NowaitC =
11353 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11354 bool HasDependC =
11355 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11356 .empty();
11357 if (NowaitC && !HasDependC) {
11358 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11359 return StmtError();
11360 }
11361
11362 return OMPTaskwaitDirective::Create(getASTContext(), StartLoc, EndLoc,
11363 Clauses);
11364}
11365
11368 Stmt *AStmt, SourceLocation StartLoc,
11369 SourceLocation EndLoc) {
11370 if (!AStmt)
11371 return StmtError();
11372
11373 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11374
11375 SemaRef.setFunctionHasBranchProtectedScope();
11376
11377 return OMPTaskgroupDirective::Create(getASTContext(), StartLoc, EndLoc,
11378 Clauses, AStmt,
11379 DSAStack->getTaskgroupReductionRef());
11380}
11381
11383 SourceLocation StartLoc,
11384 SourceLocation EndLoc) {
11385 OMPFlushClause *FC = nullptr;
11386 OMPClause *OrderClause = nullptr;
11387 for (OMPClause *C : Clauses) {
11388 if (C->getClauseKind() == OMPC_flush)
11389 FC = cast<OMPFlushClause>(C);
11390 else
11391 OrderClause = C;
11392 }
11393 unsigned OMPVersion = getLangOpts().OpenMP;
11394 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11395 SourceLocation MemOrderLoc;
11396 for (const OMPClause *C : Clauses) {
11397 if (C->getClauseKind() == OMPC_acq_rel ||
11398 C->getClauseKind() == OMPC_acquire ||
11399 C->getClauseKind() == OMPC_release ||
11400 C->getClauseKind() == OMPC_seq_cst /*OpenMP 5.1*/) {
11401 if (MemOrderKind != OMPC_unknown) {
11402 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11403 << getOpenMPDirectiveName(OMPD_flush, OMPVersion) << 1
11404 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11405 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11406 << getOpenMPClauseNameForDiag(MemOrderKind);
11407 } else {
11408 MemOrderKind = C->getClauseKind();
11409 MemOrderLoc = C->getBeginLoc();
11410 }
11411 }
11412 }
11413 if (FC && OrderClause) {
11414 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11415 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11416 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11417 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11418 return StmtError();
11419 }
11420 return OMPFlushDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11421}
11422
11424 SourceLocation StartLoc,
11425 SourceLocation EndLoc) {
11426 if (Clauses.empty()) {
11427 Diag(StartLoc, diag::err_omp_depobj_expected);
11428 return StmtError();
11429 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11430 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11431 return StmtError();
11432 }
11433 // Only depobj expression and another single clause is allowed.
11434 if (Clauses.size() > 2) {
11435 Diag(Clauses[2]->getBeginLoc(),
11436 diag::err_omp_depobj_single_clause_expected);
11437 return StmtError();
11438 } else if (Clauses.size() < 1) {
11439 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11440 return StmtError();
11441 }
11442 return OMPDepobjDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11443}
11444
11446 SourceLocation StartLoc,
11447 SourceLocation EndLoc) {
11448 // Check that exactly one clause is specified.
11449 if (Clauses.size() != 1) {
11450 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11451 diag::err_omp_scan_single_clause_expected);
11452 return StmtError();
11453 }
11454 // Check that scan directive is used in the scope of the OpenMP loop body.
11455 if (Scope *S = DSAStack->getCurScope()) {
11456 Scope *ParentS = S->getParent();
11457 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11458 !ParentS->getBreakParent()->isOpenMPLoopScope()) {
11459 unsigned OMPVersion = getLangOpts().OpenMP;
11460 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11461 << getOpenMPDirectiveName(OMPD_scan, OMPVersion) << 5);
11462 }
11463 }
11464 // Check that only one instance of scan directives is used in the same outer
11465 // region.
11466 if (DSAStack->doesParentHasScanDirective()) {
11467 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11468 Diag(DSAStack->getParentScanDirectiveLoc(),
11469 diag::note_omp_previous_directive)
11470 << "scan";
11471 return StmtError();
11472 }
11473 DSAStack->setParentHasScanDirective(StartLoc);
11474 return OMPScanDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11475}
11476
11479 Stmt *AStmt, SourceLocation StartLoc,
11480 SourceLocation EndLoc) {
11481 const OMPClause *DependFound = nullptr;
11482 const OMPClause *DependSourceClause = nullptr;
11483 const OMPClause *DependSinkClause = nullptr;
11484 const OMPClause *DoacrossFound = nullptr;
11485 const OMPClause *DoacrossSourceClause = nullptr;
11486 const OMPClause *DoacrossSinkClause = nullptr;
11487 bool ErrorFound = false;
11488 const OMPThreadsClause *TC = nullptr;
11489 const OMPSIMDClause *SC = nullptr;
11490 for (const OMPClause *C : Clauses) {
11491 auto DOC = dyn_cast<OMPDoacrossClause>(C);
11492 auto DC = dyn_cast<OMPDependClause>(C);
11493 if (DC || DOC) {
11494 DependFound = DC ? C : nullptr;
11495 DoacrossFound = DOC ? C : nullptr;
11496 OMPDoacrossKind ODK;
11497 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11498 (DOC && (ODK.isSource(DOC)))) {
11499 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11500 unsigned OMPVersion = getLangOpts().OpenMP;
11501 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11502 << getOpenMPDirectiveName(OMPD_ordered, OMPVersion)
11503 << getOpenMPClauseNameForDiag(DC ? OMPC_depend : OMPC_doacross)
11504 << 2;
11505 ErrorFound = true;
11506 } else {
11507 if (DC)
11508 DependSourceClause = C;
11509 else
11510 DoacrossSourceClause = C;
11511 }
11512 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11513 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11514 << (DC ? "depend" : "doacross") << 0;
11515 ErrorFound = true;
11516 }
11517 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11518 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11519 if (DependSourceClause || DoacrossSourceClause) {
11520 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11521 << (DC ? "depend" : "doacross") << 1;
11522 ErrorFound = true;
11523 }
11524 if (DC)
11525 DependSinkClause = C;
11526 else
11527 DoacrossSinkClause = C;
11528 }
11529 } else if (C->getClauseKind() == OMPC_threads) {
11531 } else if (C->getClauseKind() == OMPC_simd) {
11532 SC = cast<OMPSIMDClause>(C);
11533 }
11534 }
11535 if (!ErrorFound && !SC &&
11536 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11537 // OpenMP [2.8.1,simd Construct, Restrictions]
11538 // An ordered construct with the simd clause is the only OpenMP construct
11539 // that can appear in the simd region.
11540 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11541 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11542 ErrorFound = true;
11543 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11544 SourceLocation Loc =
11545 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11546 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11547 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend : OMPC_doacross)
11548 << getOpenMPClauseNameForDiag(TC ? TC->getClauseKind()
11549 : SC->getClauseKind());
11550 ErrorFound = true;
11551 } else if ((DependFound || DoacrossFound) &&
11552 !DSAStack->getParentOrderedRegionParam().first) {
11553 SourceLocation Loc =
11554 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11555 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11556 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend
11557 : OMPC_doacross);
11558 ErrorFound = true;
11559 } else if (TC || Clauses.empty()) {
11560 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11561 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11562 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11563 << (TC != nullptr);
11564 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11565 ErrorFound = true;
11566 }
11567 }
11568 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11569 return StmtError();
11570
11571 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11572 // During execution of an iteration of a worksharing-loop or a loop nest
11573 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11574 // must not execute more than one ordered region corresponding to an ordered
11575 // construct without a depend clause.
11576 if (!DependFound && !DoacrossFound) {
11577 if (DSAStack->doesParentHasOrderedDirective()) {
11578 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11579 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11580 diag::note_omp_previous_directive)
11581 << "ordered";
11582 return StmtError();
11583 }
11584 DSAStack->setParentHasOrderedDirective(StartLoc);
11585 }
11586
11587 if (AStmt) {
11588 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11589
11590 SemaRef.setFunctionHasBranchProtectedScope();
11591 }
11592
11593 return OMPOrderedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11594 AStmt);
11595}
11596
11597namespace {
11598/// Helper class for checking expression in 'omp atomic [update]'
11599/// construct.
11600class OpenMPAtomicUpdateChecker {
11601 /// Error results for atomic update expressions.
11602 enum ExprAnalysisErrorCode {
11603 /// A statement is not an expression statement.
11604 NotAnExpression,
11605 /// Expression is not builtin binary or unary operation.
11606 NotABinaryOrUnaryExpression,
11607 /// Unary operation is not post-/pre- increment/decrement operation.
11608 NotAnUnaryIncDecExpression,
11609 /// An expression is not of scalar type.
11610 NotAScalarType,
11611 /// A binary operation is not an assignment operation.
11612 NotAnAssignmentOp,
11613 /// RHS part of the binary operation is not a binary expression.
11614 NotABinaryExpression,
11615 /// RHS part is not additive/multiplicative/shift/bitwise binary
11616 /// expression.
11617 NotABinaryOperator,
11618 /// RHS binary operation does not have reference to the updated LHS
11619 /// part.
11620 NotAnUpdateExpression,
11621 /// An expression contains semantical error not related to
11622 /// 'omp atomic [update]'
11623 NotAValidExpression,
11624 /// No errors is found.
11625 NoError
11626 };
11627 /// Reference to Sema.
11628 Sema &SemaRef;
11629 /// A location for note diagnostics (when error is found).
11630 SourceLocation NoteLoc;
11631 /// 'x' lvalue part of the source atomic expression.
11632 Expr *X;
11633 /// 'expr' rvalue part of the source atomic expression.
11634 Expr *E;
11635 /// Helper expression of the form
11636 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11637 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11638 Expr *UpdateExpr;
11639 /// Is 'x' a LHS in a RHS part of full update expression. It is
11640 /// important for non-associative operations.
11641 bool IsXLHSInRHSPart;
11643 SourceLocation OpLoc;
11644 /// true if the source expression is a postfix unary operation, false
11645 /// if it is a prefix unary operation.
11646 bool IsPostfixUpdate;
11647
11648public:
11649 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11650 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11651 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11652 /// Check specified statement that it is suitable for 'atomic update'
11653 /// constructs and extract 'x', 'expr' and Operation from the original
11654 /// expression. If DiagId and NoteId == 0, then only check is performed
11655 /// without error notification.
11656 /// \param DiagId Diagnostic which should be emitted if error is found.
11657 /// \param NoteId Diagnostic note for the main error message.
11658 /// \return true if statement is not an update expression, false otherwise.
11659 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11660 /// Return the 'x' lvalue part of the source atomic expression.
11661 Expr *getX() const { return X; }
11662 /// Return the 'expr' rvalue part of the source atomic expression.
11663 Expr *getExpr() const { return E; }
11664 /// Return the update expression used in calculation of the updated
11665 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11666 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11667 Expr *getUpdateExpr() const { return UpdateExpr; }
11668 /// Return true if 'x' is LHS in RHS part of full update expression,
11669 /// false otherwise.
11670 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11671
11672 /// true if the source expression is a postfix unary operation, false
11673 /// if it is a prefix unary operation.
11674 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11675
11676private:
11677 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11678 unsigned NoteId = 0);
11679};
11680
11681bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11682 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11683 ExprAnalysisErrorCode ErrorFound = NoError;
11684 SourceLocation ErrorLoc, NoteLoc;
11685 SourceRange ErrorRange, NoteRange;
11686 // Allowed constructs are:
11687 // x = x binop expr;
11688 // x = expr binop x;
11689 if (AtomicBinOp->getOpcode() == BO_Assign) {
11690 X = AtomicBinOp->getLHS();
11691 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11692 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11693 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11694 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11695 AtomicInnerBinOp->isBitwiseOp()) {
11696 Op = AtomicInnerBinOp->getOpcode();
11697 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11698 Expr *LHS = AtomicInnerBinOp->getLHS();
11699 Expr *RHS = AtomicInnerBinOp->getRHS();
11700 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11701 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11702 /*Canonical=*/true);
11703 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11704 /*Canonical=*/true);
11705 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11706 /*Canonical=*/true);
11707 if (XId == LHSId) {
11708 E = RHS;
11709 IsXLHSInRHSPart = true;
11710 } else if (XId == RHSId) {
11711 E = LHS;
11712 IsXLHSInRHSPart = false;
11713 } else {
11714 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11715 ErrorRange = AtomicInnerBinOp->getSourceRange();
11716 NoteLoc = X->getExprLoc();
11717 NoteRange = X->getSourceRange();
11718 ErrorFound = NotAnUpdateExpression;
11719 }
11720 } else {
11721 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11722 ErrorRange = AtomicInnerBinOp->getSourceRange();
11723 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11724 NoteRange = SourceRange(NoteLoc, NoteLoc);
11725 ErrorFound = NotABinaryOperator;
11726 }
11727 } else {
11728 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11729 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11730 ErrorFound = NotABinaryExpression;
11731 }
11732 } else {
11733 ErrorLoc = AtomicBinOp->getExprLoc();
11734 ErrorRange = AtomicBinOp->getSourceRange();
11735 NoteLoc = AtomicBinOp->getOperatorLoc();
11736 NoteRange = SourceRange(NoteLoc, NoteLoc);
11737 ErrorFound = NotAnAssignmentOp;
11738 }
11739 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11740 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11741 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11742 return true;
11743 }
11744 if (SemaRef.CurContext->isDependentContext())
11745 E = X = UpdateExpr = nullptr;
11746 return ErrorFound != NoError;
11747}
11748
11749bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11750 unsigned NoteId) {
11751 ExprAnalysisErrorCode ErrorFound = NoError;
11752 SourceLocation ErrorLoc, NoteLoc;
11753 SourceRange ErrorRange, NoteRange;
11754 // Allowed constructs are:
11755 // x++;
11756 // x--;
11757 // ++x;
11758 // --x;
11759 // x binop= expr;
11760 // x = x binop expr;
11761 // x = expr binop x;
11762 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11763 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11764 if (AtomicBody->getType()->isScalarType() ||
11765 AtomicBody->isInstantiationDependent()) {
11766 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11767 AtomicBody->IgnoreParenImpCasts())) {
11768 // Check for Compound Assignment Operation
11770 AtomicCompAssignOp->getOpcode());
11771 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11772 E = AtomicCompAssignOp->getRHS();
11773 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11774 IsXLHSInRHSPart = true;
11775 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11776 AtomicBody->IgnoreParenImpCasts())) {
11777 // Check for Binary Operation
11778 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11779 return true;
11780 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11781 AtomicBody->IgnoreParenImpCasts())) {
11782 // Check for Unary Operation
11783 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11784 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11785 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11786 OpLoc = AtomicUnaryOp->getOperatorLoc();
11787 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11788 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11789 IsXLHSInRHSPart = true;
11790 } else {
11791 ErrorFound = NotAnUnaryIncDecExpression;
11792 ErrorLoc = AtomicUnaryOp->getExprLoc();
11793 ErrorRange = AtomicUnaryOp->getSourceRange();
11794 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11795 NoteRange = SourceRange(NoteLoc, NoteLoc);
11796 }
11797 } else if (!AtomicBody->isInstantiationDependent()) {
11798 ErrorFound = NotABinaryOrUnaryExpression;
11799 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11800 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11801 } else if (AtomicBody->containsErrors()) {
11802 ErrorFound = NotAValidExpression;
11803 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11804 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11805 }
11806 } else {
11807 ErrorFound = NotAScalarType;
11808 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11809 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11810 }
11811 } else {
11812 ErrorFound = NotAnExpression;
11813 NoteLoc = ErrorLoc = S->getBeginLoc();
11814 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11815 }
11816 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11817 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11818 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11819 return true;
11820 }
11821 if (SemaRef.CurContext->isDependentContext())
11822 E = X = UpdateExpr = nullptr;
11823 if (ErrorFound == NoError && E && X) {
11824 // Build an update expression of form 'OpaqueValueExpr(x) binop
11825 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11826 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11827 auto *OVEX = new (SemaRef.getASTContext())
11828 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11829 auto *OVEExpr = new (SemaRef.getASTContext())
11832 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11833 IsXLHSInRHSPart ? OVEExpr : OVEX);
11834 if (Update.isInvalid())
11835 return true;
11836 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11838 if (Update.isInvalid())
11839 return true;
11840 UpdateExpr = Update.get();
11841 }
11842 return ErrorFound != NoError;
11843}
11844
11845/// Get the node id of the fixed point of an expression \a S.
11846llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11847 llvm::FoldingSetNodeID Id;
11848 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11849 return Id;
11850}
11851
11852/// Check if two expressions are same.
11853bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11854 const Expr *RHS) {
11855 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11856}
11857
11858class OpenMPAtomicCompareChecker {
11859public:
11860 /// All kinds of errors that can occur in `atomic compare`
11861 enum ErrorTy {
11862 /// Empty compound statement.
11863 NoStmt = 0,
11864 /// More than one statement in a compound statement.
11865 MoreThanOneStmt,
11866 /// Not an assignment binary operator.
11867 NotAnAssignment,
11868 /// Not a conditional operator.
11869 NotCondOp,
11870 /// Wrong false expr. According to the spec, 'x' should be at the false
11871 /// expression of a conditional expression.
11872 WrongFalseExpr,
11873 /// The condition of a conditional expression is not a binary operator.
11874 NotABinaryOp,
11875 /// Invalid binary operator (not <, >, or ==).
11876 InvalidBinaryOp,
11877 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11878 InvalidComparison,
11879 /// X is not a lvalue.
11880 XNotLValue,
11881 /// Not a scalar.
11882 NotScalar,
11883 /// Not an integer.
11884 NotInteger,
11885 /// 'else' statement is not expected.
11886 UnexpectedElse,
11887 /// Not an equality operator.
11888 NotEQ,
11889 /// Invalid assignment (not v == x).
11890 InvalidAssignment,
11891 /// Not if statement
11892 NotIfStmt,
11893 /// More than two statements in a compound statement.
11894 MoreThanTwoStmts,
11895 /// Not a compound statement.
11896 NotCompoundStmt,
11897 /// No else statement.
11898 NoElse,
11899 /// Not 'if (r)'.
11900 InvalidCondition,
11901 /// No error.
11902 NoError,
11903 };
11904
11905 struct ErrorInfoTy {
11906 ErrorTy Error;
11907 SourceLocation ErrorLoc;
11908 SourceRange ErrorRange;
11909 SourceLocation NoteLoc;
11910 SourceRange NoteRange;
11911 };
11912
11913 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11914
11915 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11916 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11917
11918 Expr *getX() const { return X; }
11919 Expr *getE() const { return E; }
11920 Expr *getD() const { return D; }
11921 Expr *getCond() const { return C; }
11922 bool isXBinopExpr() const { return IsXBinopExpr; }
11923
11924protected:
11925 /// Reference to ASTContext
11926 ASTContext &ContextRef;
11927 /// 'x' lvalue part of the source atomic expression.
11928 Expr *X = nullptr;
11929 /// 'expr' or 'e' rvalue part of the source atomic expression.
11930 Expr *E = nullptr;
11931 /// 'd' rvalue part of the source atomic expression.
11932 Expr *D = nullptr;
11933 /// 'cond' part of the source atomic expression. It is in one of the following
11934 /// forms:
11935 /// expr ordop x
11936 /// x ordop expr
11937 /// x == e
11938 /// e == x
11939 Expr *C = nullptr;
11940 /// True if the cond expr is in the form of 'x ordop expr'.
11941 bool IsXBinopExpr = true;
11942
11943 /// Check if it is a valid conditional update statement (cond-update-stmt).
11944 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11945
11946 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11947 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11948
11949 /// Check if all captured values have right type.
11950 bool checkType(ErrorInfoTy &ErrorInfo) const;
11951
11952 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11953 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11954 if (E->isInstantiationDependent())
11955 return true;
11956
11957 if (ShouldBeLValue && !E->isLValue()) {
11958 ErrorInfo.Error = ErrorTy::XNotLValue;
11959 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11960 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11961 return false;
11962 }
11963
11964 QualType QTy = E->getType();
11965 if (!QTy->isScalarType()) {
11966 ErrorInfo.Error = ErrorTy::NotScalar;
11967 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11968 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11969 return false;
11970 }
11971 if (ShouldBeInteger && !QTy->isIntegerType()) {
11972 ErrorInfo.Error = ErrorTy::NotInteger;
11973 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11974 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11975 return false;
11976 }
11977
11978 return true;
11979 }
11980};
11981
11982bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11983 ErrorInfoTy &ErrorInfo) {
11984 auto *Then = S->getThen();
11985 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11986 if (CS->body_empty()) {
11987 ErrorInfo.Error = ErrorTy::NoStmt;
11988 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11989 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11990 return false;
11991 }
11992 if (CS->size() > 1) {
11993 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11994 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11995 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11996 return false;
11997 }
11998 Then = CS->body_front();
11999 }
12000
12001 auto *BO = dyn_cast<BinaryOperator>(Then);
12002 if (!BO) {
12003 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12004 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12005 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12006 return false;
12007 }
12008 if (BO->getOpcode() != BO_Assign) {
12009 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12010 ErrorInfo.ErrorLoc = BO->getExprLoc();
12011 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12012 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12013 return false;
12014 }
12015
12016 X = BO->getLHS();
12017
12018 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12019 auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
12020 Expr *LHS = nullptr;
12021 Expr *RHS = nullptr;
12022 if (Cond) {
12023 LHS = Cond->getLHS();
12024 RHS = Cond->getRHS();
12025 } else if (Call) {
12026 LHS = Call->getArg(0);
12027 RHS = Call->getArg(1);
12028 } else {
12029 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12030 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12031 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12032 return false;
12033 }
12034
12035 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12036 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12037 C = S->getCond();
12038 D = BO->getRHS();
12039 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12040 E = RHS;
12041 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12042 E = LHS;
12043 } else {
12044 ErrorInfo.Error = ErrorTy::InvalidComparison;
12045 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12046 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12047 S->getCond()->getSourceRange();
12048 return false;
12049 }
12050 } else if ((Cond &&
12051 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12052 (Call &&
12053 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12054 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12055 E = BO->getRHS();
12056 if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
12057 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12058 C = S->getCond();
12059 } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12060 checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12061 C = S->getCond();
12062 IsXBinopExpr = false;
12063 } else {
12064 ErrorInfo.Error = ErrorTy::InvalidComparison;
12065 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12066 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12067 S->getCond()->getSourceRange();
12068 return false;
12069 }
12070 } else {
12071 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12072 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12073 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12074 return false;
12075 }
12076
12077 if (S->getElse()) {
12078 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12079 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
12080 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
12081 return false;
12082 }
12083
12084 return true;
12085}
12086
12087bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
12088 ErrorInfoTy &ErrorInfo) {
12089 auto *BO = dyn_cast<BinaryOperator>(S);
12090 if (!BO) {
12091 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12092 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12093 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12094 return false;
12095 }
12096 if (BO->getOpcode() != BO_Assign) {
12097 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12098 ErrorInfo.ErrorLoc = BO->getExprLoc();
12099 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12100 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12101 return false;
12102 }
12103
12104 X = BO->getLHS();
12105
12106 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
12107 if (!CO) {
12108 ErrorInfo.Error = ErrorTy::NotCondOp;
12109 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12110 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12111 return false;
12112 }
12113
12114 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
12115 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12116 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12117 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12118 CO->getFalseExpr()->getSourceRange();
12119 return false;
12120 }
12121
12122 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
12123 auto *Call = dyn_cast<CXXOperatorCallExpr>(CO->getCond());
12124 Expr *LHS = nullptr;
12125 Expr *RHS = nullptr;
12126 if (Cond) {
12127 LHS = Cond->getLHS();
12128 RHS = Cond->getRHS();
12129 } else if (Call) {
12130 LHS = Call->getArg(0);
12131 RHS = Call->getArg(1);
12132 } else {
12133 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12134 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12135 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12136 CO->getCond()->getSourceRange();
12137 return false;
12138 }
12139
12140 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12141 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12142 C = CO->getCond();
12143 D = CO->getTrueExpr();
12144 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12145 E = RHS;
12146 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12147 E = LHS;
12148 } else {
12149 ErrorInfo.Error = ErrorTy::InvalidComparison;
12150 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12151 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12152 CO->getCond()->getSourceRange();
12153 return false;
12154 }
12155 } else if ((Cond &&
12156 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12157 (Call &&
12158 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12159 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12160
12161 E = CO->getTrueExpr();
12162 if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
12163 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12164 C = CO->getCond();
12165 } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12166 checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12167 C = CO->getCond();
12168 IsXBinopExpr = false;
12169 } else {
12170 ErrorInfo.Error = ErrorTy::InvalidComparison;
12171 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12172 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12173 CO->getCond()->getSourceRange();
12174 return false;
12175 }
12176 } else {
12177 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12178 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12179 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12180 CO->getCond()->getSourceRange();
12181 return false;
12182 }
12183
12184 return true;
12185}
12186
12187bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
12188 // 'x' and 'e' cannot be nullptr
12189 assert(X && E && "X and E cannot be nullptr");
12190
12191 if (!CheckValue(X, ErrorInfo, true))
12192 return false;
12193
12194 if (!CheckValue(E, ErrorInfo, false))
12195 return false;
12196
12197 if (D && !CheckValue(D, ErrorInfo, false))
12198 return false;
12199
12200 return true;
12201}
12202
12203bool OpenMPAtomicCompareChecker::checkStmt(
12204 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12205 auto *CS = dyn_cast<CompoundStmt>(S);
12206 if (CS) {
12207 if (CS->body_empty()) {
12208 ErrorInfo.Error = ErrorTy::NoStmt;
12209 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12210 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12211 return false;
12212 }
12213
12214 if (CS->size() != 1) {
12215 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12216 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12217 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12218 return false;
12219 }
12220 S = CS->body_front();
12221 }
12222
12223 auto Res = false;
12224
12225 if (auto *IS = dyn_cast<IfStmt>(S)) {
12226 // Check if the statement is in one of the following forms
12227 // (cond-update-stmt):
12228 // if (expr ordop x) { x = expr; }
12229 // if (x ordop expr) { x = expr; }
12230 // if (x == e) { x = d; }
12231 Res = checkCondUpdateStmt(IS, ErrorInfo);
12232 } else {
12233 // Check if the statement is in one of the following forms (cond-expr-stmt):
12234 // x = expr ordop x ? expr : x;
12235 // x = x ordop expr ? expr : x;
12236 // x = x == e ? d : x;
12237 Res = checkCondExprStmt(S, ErrorInfo);
12238 }
12239
12240 if (!Res)
12241 return false;
12242
12243 return checkType(ErrorInfo);
12244}
12245
12246class OpenMPAtomicCompareCaptureChecker final
12247 : public OpenMPAtomicCompareChecker {
12248public:
12249 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12250
12251 Expr *getV() const { return V; }
12252 Expr *getR() const { return R; }
12253 bool isFailOnly() const { return IsFailOnly; }
12254 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12255
12256 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12257 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12258
12259private:
12260 bool checkType(ErrorInfoTy &ErrorInfo);
12261
12262 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12263 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12264 // spec p.p. 82:
12265 // (1) { v = x; cond-update-stmt }
12266 // (2) { cond-update-stmt v = x; }
12267 // (3) if(x == e) { x = d; } else { v = x; }
12268 // (4) { r = x == e; if(r) { x = d; } }
12269 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12270
12271 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12272 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12273
12274 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12275 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12276 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12277
12278 /// 'v' lvalue part of the source atomic expression.
12279 Expr *V = nullptr;
12280 /// 'r' lvalue part of the source atomic expression.
12281 Expr *R = nullptr;
12282 /// If 'v' is only updated when the comparison fails.
12283 bool IsFailOnly = false;
12284 /// If original value of 'x' must be stored in 'v', not an updated one.
12285 bool IsPostfixUpdate = false;
12286};
12287
12288bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12289 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12290 return false;
12291
12292 if (V && !CheckValue(V, ErrorInfo, true))
12293 return false;
12294
12295 if (R && !CheckValue(R, ErrorInfo, true, true))
12296 return false;
12297
12298 return true;
12299}
12300
12301bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12302 ErrorInfoTy &ErrorInfo) {
12303 IsFailOnly = true;
12304
12305 auto *Then = S->getThen();
12306 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12307 if (CS->body_empty()) {
12308 ErrorInfo.Error = ErrorTy::NoStmt;
12309 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12310 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12311 return false;
12312 }
12313 if (CS->size() > 1) {
12314 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12315 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12316 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12317 return false;
12318 }
12319 Then = CS->body_front();
12320 }
12321
12322 auto *BO = dyn_cast<BinaryOperator>(Then);
12323 if (!BO) {
12324 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12325 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12326 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12327 return false;
12328 }
12329 if (BO->getOpcode() != BO_Assign) {
12330 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12331 ErrorInfo.ErrorLoc = BO->getExprLoc();
12332 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12333 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12334 return false;
12335 }
12336
12337 X = BO->getLHS();
12338 D = BO->getRHS();
12339
12340 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12341 auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
12342 Expr *LHS = nullptr;
12343 Expr *RHS = nullptr;
12344 if (Cond) {
12345 LHS = Cond->getLHS();
12346 RHS = Cond->getRHS();
12347 } else if (Call) {
12348 LHS = Call->getArg(0);
12349 RHS = Call->getArg(1);
12350 } else {
12351 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12352 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12353 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12354 return false;
12355 }
12356 if ((Cond && Cond->getOpcode() != BO_EQ) ||
12357 (Call && Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12358 ErrorInfo.Error = ErrorTy::NotEQ;
12359 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12360 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12361 return false;
12362 }
12363
12364 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12365 E = RHS;
12366 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12367 E = LHS;
12368 } else {
12369 ErrorInfo.Error = ErrorTy::InvalidComparison;
12370 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12371 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12372 return false;
12373 }
12374
12375 C = S->getCond();
12376
12377 if (!S->getElse()) {
12378 ErrorInfo.Error = ErrorTy::NoElse;
12379 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12380 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12381 return false;
12382 }
12383
12384 auto *Else = S->getElse();
12385 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12386 if (CS->body_empty()) {
12387 ErrorInfo.Error = ErrorTy::NoStmt;
12388 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12389 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12390 return false;
12391 }
12392 if (CS->size() > 1) {
12393 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12394 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12395 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12396 return false;
12397 }
12398 Else = CS->body_front();
12399 }
12400
12401 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12402 if (!ElseBO) {
12403 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12404 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12405 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12406 return false;
12407 }
12408 if (ElseBO->getOpcode() != BO_Assign) {
12409 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12410 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12411 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12412 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12413 return false;
12414 }
12415
12416 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12417 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12418 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12419 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12420 ElseBO->getRHS()->getSourceRange();
12421 return false;
12422 }
12423
12424 V = ElseBO->getLHS();
12425
12426 return checkType(ErrorInfo);
12427}
12428
12429bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12430 ErrorInfoTy &ErrorInfo) {
12431 // We don't check here as they should be already done before call this
12432 // function.
12433 auto *CS = cast<CompoundStmt>(S);
12434 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12435 auto *S1 = cast<BinaryOperator>(CS->body_front());
12436 auto *S2 = cast<IfStmt>(CS->body_back());
12437 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12438
12439 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12440 ErrorInfo.Error = ErrorTy::InvalidCondition;
12441 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12442 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12443 return false;
12444 }
12445
12446 R = S1->getLHS();
12447
12448 auto *Then = S2->getThen();
12449 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12450 if (ThenCS->body_empty()) {
12451 ErrorInfo.Error = ErrorTy::NoStmt;
12452 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12453 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12454 return false;
12455 }
12456 if (ThenCS->size() > 1) {
12457 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12458 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12459 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12460 return false;
12461 }
12462 Then = ThenCS->body_front();
12463 }
12464
12465 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12466 if (!ThenBO) {
12467 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12468 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12469 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12470 return false;
12471 }
12472 if (ThenBO->getOpcode() != BO_Assign) {
12473 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12474 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12475 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12476 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12477 return false;
12478 }
12479
12480 X = ThenBO->getLHS();
12481 D = ThenBO->getRHS();
12482
12483 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12484 if (BO->getOpcode() != BO_EQ) {
12485 ErrorInfo.Error = ErrorTy::NotEQ;
12486 ErrorInfo.ErrorLoc = BO->getExprLoc();
12487 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12488 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12489 return false;
12490 }
12491
12492 C = BO;
12493
12494 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12495 E = BO->getRHS();
12496 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12497 E = BO->getLHS();
12498 } else {
12499 ErrorInfo.Error = ErrorTy::InvalidComparison;
12500 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12501 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12502 return false;
12503 }
12504
12505 if (S2->getElse()) {
12506 IsFailOnly = true;
12507
12508 auto *Else = S2->getElse();
12509 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12510 if (ElseCS->body_empty()) {
12511 ErrorInfo.Error = ErrorTy::NoStmt;
12512 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12513 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12514 return false;
12515 }
12516 if (ElseCS->size() > 1) {
12517 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12518 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12519 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12520 return false;
12521 }
12522 Else = ElseCS->body_front();
12523 }
12524
12525 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12526 if (!ElseBO) {
12527 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12528 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12529 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12530 return false;
12531 }
12532 if (ElseBO->getOpcode() != BO_Assign) {
12533 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12534 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12535 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12536 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12537 return false;
12538 }
12539 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12540 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12541 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12542 ErrorInfo.NoteLoc = X->getExprLoc();
12543 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12544 ErrorInfo.NoteRange = X->getSourceRange();
12545 return false;
12546 }
12547
12548 V = ElseBO->getLHS();
12549 }
12550
12551 return checkType(ErrorInfo);
12552}
12553
12554bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12555 ErrorInfoTy &ErrorInfo) {
12556 // if(x == e) { x = d; } else { v = x; }
12557 if (auto *IS = dyn_cast<IfStmt>(S))
12558 return checkForm3(IS, ErrorInfo);
12559
12560 auto *CS = dyn_cast<CompoundStmt>(S);
12561 if (!CS) {
12562 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12563 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12564 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12565 return false;
12566 }
12567 if (CS->body_empty()) {
12568 ErrorInfo.Error = ErrorTy::NoStmt;
12569 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12570 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12571 return false;
12572 }
12573
12574 // { if(x == e) { x = d; } else { v = x; } }
12575 if (CS->size() == 1) {
12576 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12577 if (!IS) {
12578 ErrorInfo.Error = ErrorTy::NotIfStmt;
12579 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12580 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12581 CS->body_front()->getSourceRange();
12582 return false;
12583 }
12584
12585 return checkForm3(IS, ErrorInfo);
12586 } else if (CS->size() == 2) {
12587 auto *S1 = CS->body_front();
12588 auto *S2 = CS->body_back();
12589
12590 Stmt *UpdateStmt = nullptr;
12591 Stmt *CondUpdateStmt = nullptr;
12592 Stmt *CondExprStmt = nullptr;
12593
12594 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12595 // It could be one of the following cases:
12596 // { v = x; cond-update-stmt }
12597 // { v = x; cond-expr-stmt }
12598 // { cond-expr-stmt; v = x; }
12599 // form 45
12600 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12601 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12602 // check if form 45
12603 if (isa<IfStmt>(S2))
12604 return checkForm45(CS, ErrorInfo);
12605 // { cond-expr-stmt; v = x; }
12606 CondExprStmt = S1;
12607 UpdateStmt = S2;
12608 } else {
12609 IsPostfixUpdate = true;
12610 UpdateStmt = S1;
12611 if (isa<IfStmt>(S2)) {
12612 // { v = x; cond-update-stmt }
12613 CondUpdateStmt = S2;
12614 } else {
12615 // { v = x; cond-expr-stmt }
12616 CondExprStmt = S2;
12617 }
12618 }
12619 } else {
12620 // { cond-update-stmt v = x; }
12621 UpdateStmt = S2;
12622 CondUpdateStmt = S1;
12623 }
12624
12625 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12626 auto *IS = dyn_cast<IfStmt>(CUS);
12627 if (!IS) {
12628 ErrorInfo.Error = ErrorTy::NotIfStmt;
12629 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12630 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12631 return false;
12632 }
12633
12634 return checkCondUpdateStmt(IS, ErrorInfo);
12635 };
12636
12637 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12638 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12639 auto *BO = dyn_cast<BinaryOperator>(US);
12640 if (!BO) {
12641 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12642 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12643 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12644 return false;
12645 }
12646 if (BO->getOpcode() != BO_Assign) {
12647 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12648 ErrorInfo.ErrorLoc = BO->getExprLoc();
12649 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12650 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12651 return false;
12652 }
12653 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12654 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12655 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12656 ErrorInfo.NoteLoc = this->X->getExprLoc();
12657 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12658 ErrorInfo.NoteRange = this->X->getSourceRange();
12659 return false;
12660 }
12661
12662 this->V = BO->getLHS();
12663
12664 return true;
12665 };
12666
12667 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12668 return false;
12669 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12670 return false;
12671 if (!CheckUpdateStmt(UpdateStmt))
12672 return false;
12673 } else {
12674 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12675 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12676 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12677 return false;
12678 }
12679
12680 return checkType(ErrorInfo);
12681}
12682} // namespace
12683
12685 Stmt *AStmt,
12686 SourceLocation StartLoc,
12687 SourceLocation EndLoc) {
12688 ASTContext &Context = getASTContext();
12689 unsigned OMPVersion = getLangOpts().OpenMP;
12690 // Register location of the first atomic directive.
12691 DSAStack->addAtomicDirectiveLoc(StartLoc);
12692 if (!AStmt)
12693 return StmtError();
12694
12695 // 1.2.2 OpenMP Language Terminology
12696 // Structured block - An executable statement with a single entry at the
12697 // top and a single exit at the bottom.
12698 // The point of exit cannot be a branch out of the structured block.
12699 // longjmp() and throw() must not violate the entry/exit criteria.
12700 OpenMPClauseKind AtomicKind = OMPC_unknown;
12701 SourceLocation AtomicKindLoc;
12702 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12703 SourceLocation MemOrderLoc;
12704 bool MutexClauseEncountered = false;
12705 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12706 for (const OMPClause *C : Clauses) {
12707 switch (C->getClauseKind()) {
12708 case OMPC_read:
12709 case OMPC_write:
12710 case OMPC_update:
12711 MutexClauseEncountered = true;
12712 [[fallthrough]];
12713 case OMPC_capture:
12714 case OMPC_compare: {
12715 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12716 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12717 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12718 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12719 << getOpenMPClauseNameForDiag(AtomicKind);
12720 } else {
12721 AtomicKind = C->getClauseKind();
12722 AtomicKindLoc = C->getBeginLoc();
12723 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12724 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12725 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12726 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12727 << getOpenMPClauseNameForDiag(AtomicKind);
12728 }
12729 }
12730 break;
12731 }
12732 case OMPC_weak:
12733 case OMPC_fail: {
12734 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12735 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12736 << getOpenMPClauseNameForDiag(C->getClauseKind())
12737 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12738 return StmtError();
12739 }
12740 break;
12741 }
12742 case OMPC_seq_cst:
12743 case OMPC_acq_rel:
12744 case OMPC_acquire:
12745 case OMPC_release:
12746 case OMPC_relaxed: {
12747 if (MemOrderKind != OMPC_unknown) {
12748 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12749 << getOpenMPDirectiveName(OMPD_atomic, OMPVersion) << 0
12750 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12751 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12752 << getOpenMPClauseNameForDiag(MemOrderKind);
12753 } else {
12754 MemOrderKind = C->getClauseKind();
12755 MemOrderLoc = C->getBeginLoc();
12756 }
12757 break;
12758 }
12759 // The following clauses are allowed, but we don't need to do anything here.
12760 case OMPC_hint:
12761 break;
12762 default:
12763 llvm_unreachable("unknown clause is encountered");
12764 }
12765 }
12766 bool IsCompareCapture = false;
12767 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12768 EncounteredAtomicKinds.contains(OMPC_capture)) {
12769 IsCompareCapture = true;
12770 AtomicKind = OMPC_compare;
12771 }
12772 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12773 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12774 // release.
12775 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12776 // acquire.
12777 // If atomic-clause is update or not present then memory-order-clause must not
12778 // be acq_rel or acquire.
12779 if ((AtomicKind == OMPC_read &&
12780 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12781 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12782 AtomicKind == OMPC_unknown) &&
12783 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12784 SourceLocation Loc = AtomicKindLoc;
12785 if (AtomicKind == OMPC_unknown)
12786 Loc = StartLoc;
12787 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12788 << getOpenMPClauseNameForDiag(AtomicKind)
12789 << (AtomicKind == OMPC_unknown ? 1 : 0)
12790 << getOpenMPClauseNameForDiag(MemOrderKind);
12791 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12792 << getOpenMPClauseNameForDiag(MemOrderKind);
12793 }
12794
12795 Stmt *Body = AStmt;
12796 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12797 Body = EWC->getSubExpr();
12798
12799 Expr *X = nullptr;
12800 Expr *V = nullptr;
12801 Expr *E = nullptr;
12802 Expr *UE = nullptr;
12803 Expr *D = nullptr;
12804 Expr *CE = nullptr;
12805 Expr *R = nullptr;
12806 bool IsXLHSInRHSPart = false;
12807 bool IsPostfixUpdate = false;
12808 bool IsFailOnly = false;
12809 // OpenMP [2.12.6, atomic Construct]
12810 // In the next expressions:
12811 // * x and v (as applicable) are both l-value expressions with scalar type.
12812 // * During the execution of an atomic region, multiple syntactic
12813 // occurrences of x must designate the same storage location.
12814 // * Neither of v and expr (as applicable) may access the storage location
12815 // designated by x.
12816 // * Neither of x and expr (as applicable) may access the storage location
12817 // designated by v.
12818 // * expr is an expression with scalar type.
12819 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12820 // * binop, binop=, ++, and -- are not overloaded operators.
12821 // * The expression x binop expr must be numerically equivalent to x binop
12822 // (expr). This requirement is satisfied if the operators in expr have
12823 // precedence greater than binop, or by using parentheses around expr or
12824 // subexpressions of expr.
12825 // * The expression expr binop x must be numerically equivalent to (expr)
12826 // binop x. This requirement is satisfied if the operators in expr have
12827 // precedence equal to or greater than binop, or by using parentheses around
12828 // expr or subexpressions of expr.
12829 // * For forms that allow multiple occurrences of x, the number of times
12830 // that x is evaluated is unspecified.
12831 if (AtomicKind == OMPC_read) {
12832 enum {
12833 NotAnExpression,
12834 NotAnAssignmentOp,
12835 NotAScalarType,
12836 NotAnLValue,
12837 NoError
12838 } ErrorFound = NoError;
12839 SourceLocation ErrorLoc, NoteLoc;
12840 SourceRange ErrorRange, NoteRange;
12841 // If clause is read:
12842 // v = x;
12843 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12844 const auto *AtomicBinOp =
12845 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12846 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12847 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12848 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12849 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12850 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12851 if (!X->isLValue() || !V->isLValue()) {
12852 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12853 ErrorFound = NotAnLValue;
12854 ErrorLoc = AtomicBinOp->getExprLoc();
12855 ErrorRange = AtomicBinOp->getSourceRange();
12856 NoteLoc = NotLValueExpr->getExprLoc();
12857 NoteRange = NotLValueExpr->getSourceRange();
12858 }
12859 } else if (!X->isInstantiationDependent() ||
12860 !V->isInstantiationDependent()) {
12861 const Expr *NotScalarExpr =
12862 (X->isInstantiationDependent() || X->getType()->isScalarType())
12863 ? V
12864 : X;
12865 ErrorFound = NotAScalarType;
12866 ErrorLoc = AtomicBinOp->getExprLoc();
12867 ErrorRange = AtomicBinOp->getSourceRange();
12868 NoteLoc = NotScalarExpr->getExprLoc();
12869 NoteRange = NotScalarExpr->getSourceRange();
12870 }
12871 } else if (!AtomicBody->isInstantiationDependent()) {
12872 ErrorFound = NotAnAssignmentOp;
12873 ErrorLoc = AtomicBody->getExprLoc();
12874 ErrorRange = AtomicBody->getSourceRange();
12875 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12876 : AtomicBody->getExprLoc();
12877 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12878 : AtomicBody->getSourceRange();
12879 }
12880 } else {
12881 ErrorFound = NotAnExpression;
12882 NoteLoc = ErrorLoc = Body->getBeginLoc();
12883 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12884 }
12885 if (ErrorFound != NoError) {
12886 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12887 << ErrorRange;
12888 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12889 << ErrorFound << NoteRange;
12890 return StmtError();
12891 }
12892 if (SemaRef.CurContext->isDependentContext())
12893 V = X = nullptr;
12894 } else if (AtomicKind == OMPC_write) {
12895 enum {
12896 NotAnExpression,
12897 NotAnAssignmentOp,
12898 NotAScalarType,
12899 NotAnLValue,
12900 NoError
12901 } ErrorFound = NoError;
12902 SourceLocation ErrorLoc, NoteLoc;
12903 SourceRange ErrorRange, NoteRange;
12904 // If clause is write:
12905 // x = expr;
12906 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12907 const auto *AtomicBinOp =
12908 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12909 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12910 X = AtomicBinOp->getLHS();
12911 E = AtomicBinOp->getRHS();
12912 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12913 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
12914 if (!X->isLValue()) {
12915 ErrorFound = NotAnLValue;
12916 ErrorLoc = AtomicBinOp->getExprLoc();
12917 ErrorRange = AtomicBinOp->getSourceRange();
12918 NoteLoc = X->getExprLoc();
12919 NoteRange = X->getSourceRange();
12920 }
12921 } else if (!X->isInstantiationDependent() ||
12923 const Expr *NotScalarExpr =
12924 (X->isInstantiationDependent() || X->getType()->isScalarType())
12925 ? E
12926 : X;
12927 ErrorFound = NotAScalarType;
12928 ErrorLoc = AtomicBinOp->getExprLoc();
12929 ErrorRange = AtomicBinOp->getSourceRange();
12930 NoteLoc = NotScalarExpr->getExprLoc();
12931 NoteRange = NotScalarExpr->getSourceRange();
12932 }
12933 } else if (!AtomicBody->isInstantiationDependent()) {
12934 ErrorFound = NotAnAssignmentOp;
12935 ErrorLoc = AtomicBody->getExprLoc();
12936 ErrorRange = AtomicBody->getSourceRange();
12937 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12938 : AtomicBody->getExprLoc();
12939 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12940 : AtomicBody->getSourceRange();
12941 }
12942 } else {
12943 ErrorFound = NotAnExpression;
12944 NoteLoc = ErrorLoc = Body->getBeginLoc();
12945 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12946 }
12947 if (ErrorFound != NoError) {
12948 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12949 << ErrorRange;
12950 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12951 << ErrorFound << NoteRange;
12952 return StmtError();
12953 }
12954 if (SemaRef.CurContext->isDependentContext())
12955 E = X = nullptr;
12956 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12957 // If clause is update:
12958 // x++;
12959 // x--;
12960 // ++x;
12961 // --x;
12962 // x binop= expr;
12963 // x = x binop expr;
12964 // x = expr binop x;
12965 OpenMPAtomicUpdateChecker Checker(SemaRef);
12966 if (Checker.checkStatement(
12967 Body,
12968 (AtomicKind == OMPC_update)
12969 ? diag::err_omp_atomic_update_not_expression_statement
12970 : diag::err_omp_atomic_not_expression_statement,
12971 diag::note_omp_atomic_update))
12972 return StmtError();
12973 if (!SemaRef.CurContext->isDependentContext()) {
12974 E = Checker.getExpr();
12975 X = Checker.getX();
12976 UE = Checker.getUpdateExpr();
12977 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12978 }
12979 } else if (AtomicKind == OMPC_capture) {
12980 enum {
12981 NotAnAssignmentOp,
12982 NotACompoundStatement,
12983 NotTwoSubstatements,
12984 NotASpecificExpression,
12985 NoError
12986 } ErrorFound = NoError;
12987 SourceLocation ErrorLoc, NoteLoc;
12988 SourceRange ErrorRange, NoteRange;
12989 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12990 // If clause is a capture:
12991 // v = x++;
12992 // v = x--;
12993 // v = ++x;
12994 // v = --x;
12995 // v = x binop= expr;
12996 // v = x = x binop expr;
12997 // v = x = expr binop x;
12998 const auto *AtomicBinOp =
12999 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
13000 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
13001 V = AtomicBinOp->getLHS();
13002 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
13003 OpenMPAtomicUpdateChecker Checker(SemaRef);
13004 if (Checker.checkStatement(
13005 Body, diag::err_omp_atomic_capture_not_expression_statement,
13006 diag::note_omp_atomic_update))
13007 return StmtError();
13008 E = Checker.getExpr();
13009 X = Checker.getX();
13010 UE = Checker.getUpdateExpr();
13011 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13012 IsPostfixUpdate = Checker.isPostfixUpdate();
13013 } else if (!AtomicBody->isInstantiationDependent()) {
13014 ErrorLoc = AtomicBody->getExprLoc();
13015 ErrorRange = AtomicBody->getSourceRange();
13016 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13017 : AtomicBody->getExprLoc();
13018 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13019 : AtomicBody->getSourceRange();
13020 ErrorFound = NotAnAssignmentOp;
13021 }
13022 if (ErrorFound != NoError) {
13023 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
13024 << ErrorRange;
13025 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13026 return StmtError();
13027 }
13028 if (SemaRef.CurContext->isDependentContext())
13029 UE = V = E = X = nullptr;
13030 } else {
13031 // If clause is a capture:
13032 // { v = x; x = expr; }
13033 // { v = x; x++; }
13034 // { v = x; x--; }
13035 // { v = x; ++x; }
13036 // { v = x; --x; }
13037 // { v = x; x binop= expr; }
13038 // { v = x; x = x binop expr; }
13039 // { v = x; x = expr binop x; }
13040 // { x++; v = x; }
13041 // { x--; v = x; }
13042 // { ++x; v = x; }
13043 // { --x; v = x; }
13044 // { x binop= expr; v = x; }
13045 // { x = x binop expr; v = x; }
13046 // { x = expr binop x; v = x; }
13047 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
13048 // Check that this is { expr1; expr2; }
13049 if (CS->size() == 2) {
13050 Stmt *First = CS->body_front();
13051 Stmt *Second = CS->body_back();
13052 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
13053 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13054 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
13055 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13056 // Need to find what subexpression is 'v' and what is 'x'.
13057 OpenMPAtomicUpdateChecker Checker(SemaRef);
13058 bool IsUpdateExprFound = !Checker.checkStatement(Second);
13059 BinaryOperator *BinOp = nullptr;
13060 if (IsUpdateExprFound) {
13061 BinOp = dyn_cast<BinaryOperator>(First);
13062 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13063 }
13064 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
13065 // { v = x; x++; }
13066 // { v = x; x--; }
13067 // { v = x; ++x; }
13068 // { v = x; --x; }
13069 // { v = x; x binop= expr; }
13070 // { v = x; x = x binop expr; }
13071 // { v = x; x = expr binop x; }
13072 // Check that the first expression has form v = x.
13073 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13074 llvm::FoldingSetNodeID XId, PossibleXId;
13075 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13076 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13077 IsUpdateExprFound = XId == PossibleXId;
13078 if (IsUpdateExprFound) {
13079 V = BinOp->getLHS();
13080 X = Checker.getX();
13081 E = Checker.getExpr();
13082 UE = Checker.getUpdateExpr();
13083 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13084 IsPostfixUpdate = true;
13085 }
13086 }
13087 if (!IsUpdateExprFound) {
13088 IsUpdateExprFound = !Checker.checkStatement(First);
13089 BinOp = nullptr;
13090 if (IsUpdateExprFound) {
13091 BinOp = dyn_cast<BinaryOperator>(Second);
13092 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13093 }
13094 if (IsUpdateExprFound &&
13095 !SemaRef.CurContext->isDependentContext()) {
13096 // { x++; v = x; }
13097 // { x--; v = x; }
13098 // { ++x; v = x; }
13099 // { --x; v = x; }
13100 // { x binop= expr; v = x; }
13101 // { x = x binop expr; v = x; }
13102 // { x = expr binop x; v = x; }
13103 // Check that the second expression has form v = x.
13104 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13105 llvm::FoldingSetNodeID XId, PossibleXId;
13106 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13107 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13108 IsUpdateExprFound = XId == PossibleXId;
13109 if (IsUpdateExprFound) {
13110 V = BinOp->getLHS();
13111 X = Checker.getX();
13112 E = Checker.getExpr();
13113 UE = Checker.getUpdateExpr();
13114 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13115 IsPostfixUpdate = false;
13116 }
13117 }
13118 }
13119 if (!IsUpdateExprFound) {
13120 // { v = x; x = expr; }
13121 auto *FirstExpr = dyn_cast<Expr>(First);
13122 auto *SecondExpr = dyn_cast<Expr>(Second);
13123 if (!FirstExpr || !SecondExpr ||
13124 !(FirstExpr->isInstantiationDependent() ||
13125 SecondExpr->isInstantiationDependent())) {
13126 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
13127 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13128 ErrorFound = NotAnAssignmentOp;
13129 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13130 : First->getBeginLoc();
13131 NoteRange = ErrorRange = FirstBinOp
13132 ? FirstBinOp->getSourceRange()
13133 : SourceRange(ErrorLoc, ErrorLoc);
13134 } else {
13135 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
13136 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13137 ErrorFound = NotAnAssignmentOp;
13138 NoteLoc = ErrorLoc = SecondBinOp
13139 ? SecondBinOp->getOperatorLoc()
13140 : Second->getBeginLoc();
13141 NoteRange = ErrorRange =
13142 SecondBinOp ? SecondBinOp->getSourceRange()
13143 : SourceRange(ErrorLoc, ErrorLoc);
13144 } else {
13145 Expr *PossibleXRHSInFirst =
13146 FirstBinOp->getRHS()->IgnoreParenImpCasts();
13147 Expr *PossibleXLHSInSecond =
13148 SecondBinOp->getLHS()->IgnoreParenImpCasts();
13149 llvm::FoldingSetNodeID X1Id, X2Id;
13150 PossibleXRHSInFirst->Profile(X1Id, Context,
13151 /*Canonical=*/true);
13152 PossibleXLHSInSecond->Profile(X2Id, Context,
13153 /*Canonical=*/true);
13154 IsUpdateExprFound = X1Id == X2Id;
13155 if (IsUpdateExprFound) {
13156 V = FirstBinOp->getLHS();
13157 X = SecondBinOp->getLHS();
13158 E = SecondBinOp->getRHS();
13159 UE = nullptr;
13160 IsXLHSInRHSPart = false;
13161 IsPostfixUpdate = true;
13162 } else {
13163 ErrorFound = NotASpecificExpression;
13164 ErrorLoc = FirstBinOp->getExprLoc();
13165 ErrorRange = FirstBinOp->getSourceRange();
13166 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13167 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13168 }
13169 }
13170 }
13171 }
13172 }
13173 } else {
13174 NoteLoc = ErrorLoc = Body->getBeginLoc();
13175 NoteRange = ErrorRange =
13176 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13177 ErrorFound = NotTwoSubstatements;
13178 }
13179 } else {
13180 NoteLoc = ErrorLoc = Body->getBeginLoc();
13181 NoteRange = ErrorRange =
13182 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13183 ErrorFound = NotACompoundStatement;
13184 }
13185 }
13186 if (ErrorFound != NoError) {
13187 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
13188 << ErrorRange;
13189 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13190 return StmtError();
13191 }
13192 if (SemaRef.CurContext->isDependentContext())
13193 UE = V = E = X = nullptr;
13194 } else if (AtomicKind == OMPC_compare) {
13195 if (IsCompareCapture) {
13196 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13197 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
13198 if (!Checker.checkStmt(Body, ErrorInfo)) {
13199 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
13200 << ErrorInfo.ErrorRange;
13201 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13202 << ErrorInfo.Error << ErrorInfo.NoteRange;
13203 return StmtError();
13204 }
13205 X = Checker.getX();
13206 E = Checker.getE();
13207 D = Checker.getD();
13208 CE = Checker.getCond();
13209 V = Checker.getV();
13210 R = Checker.getR();
13211 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13212 IsXLHSInRHSPart = Checker.isXBinopExpr();
13213 IsFailOnly = Checker.isFailOnly();
13214 IsPostfixUpdate = Checker.isPostfixUpdate();
13215 } else {
13216 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13217 OpenMPAtomicCompareChecker Checker(SemaRef);
13218 if (!Checker.checkStmt(Body, ErrorInfo)) {
13219 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
13220 << ErrorInfo.ErrorRange;
13221 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13222 << ErrorInfo.Error << ErrorInfo.NoteRange;
13223 return StmtError();
13224 }
13225 X = Checker.getX();
13226 E = Checker.getE();
13227 D = Checker.getD();
13228 CE = Checker.getCond();
13229 // The weak clause may only appear if the resulting atomic operation is
13230 // an atomic conditional update for which the comparison tests for
13231 // equality. It was not possible to do this check in
13232 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
13233 // could not be performed (Clauses are not available).
13234 auto *It = find_if(Clauses, [](OMPClause *C) {
13235 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13236 });
13237 if (It != Clauses.end()) {
13238 auto *Cond = dyn_cast<BinaryOperator>(CE);
13239 if (Cond->getOpcode() != BO_EQ) {
13240 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13241 ErrorInfo.ErrorLoc = Cond->getExprLoc();
13242 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
13243 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
13244
13245 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
13246 << ErrorInfo.ErrorRange;
13247 return StmtError();
13248 }
13249 }
13250 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13251 IsXLHSInRHSPart = Checker.isXBinopExpr();
13252 }
13253 }
13254
13255 SemaRef.setFunctionHasBranchProtectedScope();
13256
13257 return OMPAtomicDirective::Create(
13258 Context, StartLoc, EndLoc, Clauses, AStmt,
13259 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
13260}
13261
13263 Stmt *AStmt,
13264 SourceLocation StartLoc,
13265 SourceLocation EndLoc) {
13266 if (!AStmt)
13267 return StmtError();
13268
13269 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target, AStmt);
13270
13271 // OpenMP [2.16, Nesting of Regions]
13272 // If specified, a teams construct must be contained within a target
13273 // construct. That target construct must contain no statements or directives
13274 // outside of the teams construct.
13275 if (DSAStack->hasInnerTeamsRegion()) {
13276 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13277 bool OMPTeamsFound = true;
13278 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
13279 auto I = CS->body_begin();
13280 while (I != CS->body_end()) {
13281 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13282 bool IsTeams = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13283 if (!IsTeams || I != CS->body_begin()) {
13284 OMPTeamsFound = false;
13285 if (IsTeams && I != CS->body_begin()) {
13286 // This is the two teams case. Since the InnerTeamsRegionLoc will
13287 // point to this second one reset the iterator to the other teams.
13288 --I;
13289 }
13290 break;
13291 }
13292 ++I;
13293 }
13294 assert(I != CS->body_end() && "Not found statement");
13295 S = *I;
13296 } else {
13297 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13298 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13299 }
13300 if (!OMPTeamsFound) {
13301 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13302 Diag(DSAStack->getInnerTeamsRegionLoc(),
13303 diag::note_omp_nested_teams_construct_here);
13304 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
13306 return StmtError();
13307 }
13308 }
13309
13310 return OMPTargetDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13311 AStmt);
13312}
13313
13315 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13316 SourceLocation EndLoc) {
13317 if (!AStmt)
13318 return StmtError();
13319
13320 setBranchProtectedScope(SemaRef, OMPD_target_parallel, AStmt);
13321
13323 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
13324 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13325}
13326
13328 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13329 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13330 if (!AStmt)
13331 return StmtError();
13332
13333 CapturedStmt *CS =
13334 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for, AStmt);
13335
13336 OMPLoopBasedDirective::HelperExprs B;
13337 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13338 // define the nested loops number.
13339 unsigned NestedLoopCount =
13340 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13341 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13342 VarsWithImplicitDSA, B);
13343 if (NestedLoopCount == 0)
13344 return StmtError();
13345
13346 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13347 return StmtError();
13348
13350 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13351 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13352}
13353
13354/// Check for existence of a map clause in the list of clauses.
13356 const OpenMPClauseKind K) {
13357 return llvm::any_of(
13358 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13359}
13360
13361template <typename... Params>
13363 const Params... ClauseTypes) {
13364 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13365}
13366
13367/// Check if the variables in the mapping clause are externally visible.
13369 for (const OMPClause *C : Clauses) {
13370 if (auto *TC = dyn_cast<OMPToClause>(C))
13371 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13372 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13373 (VD->isExternallyVisible() &&
13374 VD->getVisibility() != HiddenVisibility);
13375 });
13376 else if (auto *FC = dyn_cast<OMPFromClause>(C))
13377 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13378 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13379 (VD->isExternallyVisible() &&
13380 VD->getVisibility() != HiddenVisibility);
13381 });
13382 }
13383
13384 return true;
13385}
13386
13389 Stmt *AStmt, SourceLocation StartLoc,
13390 SourceLocation EndLoc) {
13391 if (!AStmt)
13392 return StmtError();
13393
13394 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13395
13396 // OpenMP [2.12.2, target data Construct, Restrictions]
13397 // At least one map, use_device_addr or use_device_ptr clause must appear on
13398 // the directive.
13399 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13400 (getLangOpts().OpenMP < 50 ||
13401 !hasClauses(Clauses, OMPC_use_device_addr))) {
13402 StringRef Expected;
13403 if (getLangOpts().OpenMP < 50)
13404 Expected = "'map' or 'use_device_ptr'";
13405 else
13406 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13407 unsigned OMPVersion = getLangOpts().OpenMP;
13408 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13409 << Expected << getOpenMPDirectiveName(OMPD_target_data, OMPVersion);
13410 return StmtError();
13411 }
13412
13413 SemaRef.setFunctionHasBranchProtectedScope();
13414
13415 return OMPTargetDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13416 Clauses, AStmt);
13417}
13418
13420 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13421 SourceLocation EndLoc, Stmt *AStmt) {
13422 if (!AStmt)
13423 return StmtError();
13424
13425 setBranchProtectedScope(SemaRef, OMPD_target_enter_data, AStmt);
13426
13427 // OpenMP [2.10.2, Restrictions, p. 99]
13428 // At least one map clause must appear on the directive.
13429 if (!hasClauses(Clauses, OMPC_map)) {
13430 unsigned OMPVersion = getLangOpts().OpenMP;
13431 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13432 << "'map'"
13433 << getOpenMPDirectiveName(OMPD_target_enter_data, OMPVersion);
13434 return StmtError();
13435 }
13436
13437 return OMPTargetEnterDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13438 Clauses, AStmt);
13439}
13440
13442 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13443 SourceLocation EndLoc, Stmt *AStmt) {
13444 if (!AStmt)
13445 return StmtError();
13446
13447 setBranchProtectedScope(SemaRef, OMPD_target_exit_data, AStmt);
13448
13449 // OpenMP [2.10.3, Restrictions, p. 102]
13450 // At least one map clause must appear on the directive.
13451 if (!hasClauses(Clauses, OMPC_map)) {
13452 unsigned OMPVersion = getLangOpts().OpenMP;
13453 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13454 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data, OMPVersion);
13455 return StmtError();
13456 }
13457
13458 return OMPTargetExitDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13459 Clauses, AStmt);
13460}
13461
13463 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13464 SourceLocation EndLoc, Stmt *AStmt) {
13465 if (!AStmt)
13466 return StmtError();
13467
13468 setBranchProtectedScope(SemaRef, OMPD_target_update, AStmt);
13469
13470 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13471 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13472 return StmtError();
13473 }
13474
13475 if (!isClauseMappable(Clauses)) {
13476 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13477 return StmtError();
13478 }
13479
13480 return OMPTargetUpdateDirective::Create(getASTContext(), StartLoc, EndLoc,
13481 Clauses, AStmt);
13482}
13483
13484/// This checks whether a \p ClauseType clause \p C has at most \p Max
13485/// expression. If not, a diag of number \p Diag will be emitted.
13486template <typename ClauseType>
13487static bool checkNumExprsInClause(SemaBase &SemaRef,
13488 ArrayRef<OMPClause *> Clauses,
13489 unsigned MaxNum, unsigned Diag) {
13490 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13491 if (ClauseItr == Clauses.end())
13492 return true;
13493 const auto *C = cast<ClauseType>(*ClauseItr);
13494 auto VarList = C->getVarRefs();
13495 if (VarList.size() > MaxNum) {
13496 SemaRef.Diag(VarList[MaxNum]->getBeginLoc(), Diag)
13497 << getOpenMPClauseNameForDiag(C->getClauseKind());
13498 return false;
13499 }
13500 return true;
13501}
13502
13504 Stmt *AStmt,
13505 SourceLocation StartLoc,
13506 SourceLocation EndLoc) {
13507 if (!AStmt)
13508 return StmtError();
13509
13511 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
13513 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
13514 return StmtError();
13515
13516 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13517 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13518 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13519
13520 setBranchProtectedScope(SemaRef, OMPD_teams, AStmt);
13521
13522 DSAStack->setParentTeamsRegionLoc(StartLoc);
13523
13524 return OMPTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13525 AStmt);
13526}
13527
13529 SourceLocation StartLoc, SourceLocation EndLoc,
13530 OpenMPDirectiveKind CancelRegion) {
13531 if (DSAStack->isParentNowaitRegion()) {
13532 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13533 return StmtError();
13534 }
13535 if (DSAStack->isParentOrderedRegion()) {
13536 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13537 return StmtError();
13538 }
13540 EndLoc, CancelRegion);
13541}
13542
13544 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13545 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13546 if (DSAStack->isParentNowaitRegion()) {
13547 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13548 return StmtError();
13549 }
13550 if (DSAStack->isParentOrderedRegion()) {
13551 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13552 return StmtError();
13553 }
13554 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13555 return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13556 CancelRegion);
13557}
13558
13560 ArrayRef<OMPClause *> Clauses) {
13561 const OMPClause *ReductionClause = nullptr;
13562 const OMPClause *NogroupClause = nullptr;
13563 for (const OMPClause *C : Clauses) {
13564 if (C->getClauseKind() == OMPC_reduction) {
13565 ReductionClause = C;
13566 if (NogroupClause)
13567 break;
13568 continue;
13569 }
13570 if (C->getClauseKind() == OMPC_nogroup) {
13571 NogroupClause = C;
13572 if (ReductionClause)
13573 break;
13574 continue;
13575 }
13576 }
13577 if (ReductionClause && NogroupClause) {
13578 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13579 << SourceRange(NogroupClause->getBeginLoc(),
13580 NogroupClause->getEndLoc());
13581 return true;
13582 }
13583 return false;
13584}
13585
13587 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13588 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13589 if (!AStmt)
13590 return StmtError();
13591
13592 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13593 OMPLoopBasedDirective::HelperExprs B;
13594 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13595 // define the nested loops number.
13596 unsigned NestedLoopCount =
13597 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13598 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13599 *DSAStack, VarsWithImplicitDSA, B);
13600 if (NestedLoopCount == 0)
13601 return StmtError();
13602
13603 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13604 "omp for loop exprs were not built");
13605
13606 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13607 // The grainsize clause and num_tasks clause are mutually exclusive and may
13608 // not appear on the same taskloop directive.
13610 {OMPC_grainsize, OMPC_num_tasks}))
13611 return StmtError();
13612 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13613 // If a reduction clause is present on the taskloop directive, the nogroup
13614 // clause must not be specified.
13616 return StmtError();
13617
13618 SemaRef.setFunctionHasBranchProtectedScope();
13619 return OMPTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13620 NestedLoopCount, Clauses, AStmt, B,
13621 DSAStack->isCancelRegion());
13622}
13623
13625 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13626 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13627 if (!AStmt)
13628 return StmtError();
13629
13630 CapturedStmt *CS =
13631 setBranchProtectedScope(SemaRef, OMPD_taskloop_simd, AStmt);
13632
13633 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13634 OMPLoopBasedDirective::HelperExprs B;
13635 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13636 // define the nested loops number.
13637 unsigned NestedLoopCount =
13638 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13639 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13640 VarsWithImplicitDSA, B);
13641 if (NestedLoopCount == 0)
13642 return StmtError();
13643
13644 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13645 return StmtError();
13646
13647 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13648 // The grainsize clause and num_tasks clause are mutually exclusive and may
13649 // not appear on the same taskloop directive.
13651 {OMPC_grainsize, OMPC_num_tasks}))
13652 return StmtError();
13653 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13654 // If a reduction clause is present on the taskloop directive, the nogroup
13655 // clause must not be specified.
13657 return StmtError();
13659 return StmtError();
13660
13661 return OMPTaskLoopSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13662 NestedLoopCount, Clauses, AStmt, B);
13663}
13664
13666 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13667 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13668 if (!AStmt)
13669 return StmtError();
13670
13671 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13672 OMPLoopBasedDirective::HelperExprs B;
13673 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13674 // define the nested loops number.
13675 unsigned NestedLoopCount =
13676 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13677 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13678 *DSAStack, VarsWithImplicitDSA, B);
13679 if (NestedLoopCount == 0)
13680 return StmtError();
13681
13682 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13683 "omp for loop exprs were not built");
13684
13685 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13686 // The grainsize clause and num_tasks clause are mutually exclusive and may
13687 // not appear on the same taskloop directive.
13689 {OMPC_grainsize, OMPC_num_tasks}))
13690 return StmtError();
13691 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13692 // If a reduction clause is present on the taskloop directive, the nogroup
13693 // clause must not be specified.
13695 return StmtError();
13696
13697 SemaRef.setFunctionHasBranchProtectedScope();
13698 return OMPMasterTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13699 NestedLoopCount, Clauses, AStmt, B,
13700 DSAStack->isCancelRegion());
13701}
13702
13704 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13705 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13706 if (!AStmt)
13707 return StmtError();
13708
13709 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13710 OMPLoopBasedDirective::HelperExprs B;
13711 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13712 // define the nested loops number.
13713 unsigned NestedLoopCount =
13714 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13715 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13716 *DSAStack, VarsWithImplicitDSA, B);
13717 if (NestedLoopCount == 0)
13718 return StmtError();
13719
13720 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13721 "omp for loop exprs were not built");
13722
13723 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13724 // The grainsize clause and num_tasks clause are mutually exclusive and may
13725 // not appear on the same taskloop directive.
13727 {OMPC_grainsize, OMPC_num_tasks}))
13728 return StmtError();
13729 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13730 // If a reduction clause is present on the taskloop directive, the nogroup
13731 // clause must not be specified.
13733 return StmtError();
13734
13735 SemaRef.setFunctionHasBranchProtectedScope();
13736 return OMPMaskedTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13737 NestedLoopCount, Clauses, AStmt, B,
13738 DSAStack->isCancelRegion());
13739}
13740
13742 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13743 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13744 if (!AStmt)
13745 return StmtError();
13746
13747 CapturedStmt *CS =
13748 setBranchProtectedScope(SemaRef, OMPD_master_taskloop_simd, AStmt);
13749
13750 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13751 OMPLoopBasedDirective::HelperExprs B;
13752 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13753 // define the nested loops number.
13754 unsigned NestedLoopCount =
13755 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13756 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13757 VarsWithImplicitDSA, B);
13758 if (NestedLoopCount == 0)
13759 return StmtError();
13760
13761 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13762 return StmtError();
13763
13764 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13765 // The grainsize clause and num_tasks clause are mutually exclusive and may
13766 // not appear on the same taskloop directive.
13768 {OMPC_grainsize, OMPC_num_tasks}))
13769 return StmtError();
13770 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13771 // If a reduction clause is present on the taskloop directive, the nogroup
13772 // clause must not be specified.
13774 return StmtError();
13776 return StmtError();
13777
13779 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13780}
13781
13783 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13784 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13785 if (!AStmt)
13786 return StmtError();
13787
13788 CapturedStmt *CS =
13789 setBranchProtectedScope(SemaRef, OMPD_masked_taskloop_simd, AStmt);
13790
13791 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13792 OMPLoopBasedDirective::HelperExprs B;
13793 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13794 // define the nested loops number.
13795 unsigned NestedLoopCount =
13796 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13797 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13798 VarsWithImplicitDSA, B);
13799 if (NestedLoopCount == 0)
13800 return StmtError();
13801
13802 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13803 return StmtError();
13804
13805 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13806 // The grainsize clause and num_tasks clause are mutually exclusive and may
13807 // not appear on the same taskloop directive.
13809 {OMPC_grainsize, OMPC_num_tasks}))
13810 return StmtError();
13811 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13812 // If a reduction clause is present on the taskloop directive, the nogroup
13813 // clause must not be specified.
13815 return StmtError();
13817 return StmtError();
13818
13820 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13821}
13822
13824 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13825 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13826 if (!AStmt)
13827 return StmtError();
13828
13829 CapturedStmt *CS =
13830 setBranchProtectedScope(SemaRef, OMPD_parallel_master_taskloop, AStmt);
13831
13832 OMPLoopBasedDirective::HelperExprs B;
13833 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13834 // define the nested loops number.
13835 unsigned NestedLoopCount = checkOpenMPLoop(
13836 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13837 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13838 VarsWithImplicitDSA, B);
13839 if (NestedLoopCount == 0)
13840 return StmtError();
13841
13842 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13843 "omp for loop exprs were not built");
13844
13845 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13846 // The grainsize clause and num_tasks clause are mutually exclusive and may
13847 // not appear on the same taskloop directive.
13849 {OMPC_grainsize, OMPC_num_tasks}))
13850 return StmtError();
13851 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13852 // If a reduction clause is present on the taskloop directive, the nogroup
13853 // clause must not be specified.
13855 return StmtError();
13856
13858 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13859 DSAStack->isCancelRegion());
13860}
13861
13863 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13864 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13865 if (!AStmt)
13866 return StmtError();
13867
13868 CapturedStmt *CS =
13869 setBranchProtectedScope(SemaRef, OMPD_parallel_masked_taskloop, AStmt);
13870
13871 OMPLoopBasedDirective::HelperExprs B;
13872 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13873 // define the nested loops number.
13874 unsigned NestedLoopCount = checkOpenMPLoop(
13875 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13876 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13877 VarsWithImplicitDSA, B);
13878 if (NestedLoopCount == 0)
13879 return StmtError();
13880
13881 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13882 "omp for loop exprs were not built");
13883
13884 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13885 // The grainsize clause and num_tasks clause are mutually exclusive and may
13886 // not appear on the same taskloop directive.
13888 {OMPC_grainsize, OMPC_num_tasks}))
13889 return StmtError();
13890 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13891 // If a reduction clause is present on the taskloop directive, the nogroup
13892 // clause must not be specified.
13894 return StmtError();
13895
13897 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13898 DSAStack->isCancelRegion());
13899}
13900
13902 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13903 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13904 if (!AStmt)
13905 return StmtError();
13906
13908 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13909
13910 OMPLoopBasedDirective::HelperExprs B;
13911 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13912 // define the nested loops number.
13913 unsigned NestedLoopCount = checkOpenMPLoop(
13914 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13915 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13916 VarsWithImplicitDSA, B);
13917 if (NestedLoopCount == 0)
13918 return StmtError();
13919
13920 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13921 return StmtError();
13922
13923 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13924 // The grainsize clause and num_tasks clause are mutually exclusive and may
13925 // not appear on the same taskloop directive.
13927 {OMPC_grainsize, OMPC_num_tasks}))
13928 return StmtError();
13929 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13930 // If a reduction clause is present on the taskloop directive, the nogroup
13931 // clause must not be specified.
13933 return StmtError();
13935 return StmtError();
13936
13938 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13939}
13940
13942 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13943 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13944 if (!AStmt)
13945 return StmtError();
13946
13948 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13949
13950 OMPLoopBasedDirective::HelperExprs B;
13951 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13952 // define the nested loops number.
13953 unsigned NestedLoopCount = checkOpenMPLoop(
13954 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13955 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13956 VarsWithImplicitDSA, B);
13957 if (NestedLoopCount == 0)
13958 return StmtError();
13959
13960 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13961 return StmtError();
13962
13963 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13964 // The grainsize clause and num_tasks clause are mutually exclusive and may
13965 // not appear on the same taskloop directive.
13967 {OMPC_grainsize, OMPC_num_tasks}))
13968 return StmtError();
13969 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13970 // If a reduction clause is present on the taskloop directive, the nogroup
13971 // clause must not be specified.
13973 return StmtError();
13975 return StmtError();
13976
13978 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13979}
13980
13982 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13983 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13984 if (!AStmt)
13985 return StmtError();
13986
13987 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13988 OMPLoopBasedDirective::HelperExprs B;
13989 // In presence of clause 'collapse' with number of loops, it will
13990 // define the nested loops number.
13991 unsigned NestedLoopCount =
13992 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
13993 nullptr /*ordered not a clause on distribute*/, AStmt,
13994 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13995 if (NestedLoopCount == 0)
13996 return StmtError();
13997
13998 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13999 "omp for loop exprs were not built");
14000
14001 SemaRef.setFunctionHasBranchProtectedScope();
14002 auto *DistributeDirective = OMPDistributeDirective::Create(
14003 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14004 return DistributeDirective;
14005}
14006
14008 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14009 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14010 if (!AStmt)
14011 return StmtError();
14012
14013 CapturedStmt *CS =
14014 setBranchProtectedScope(SemaRef, OMPD_distribute_parallel_for, AStmt);
14015
14016 OMPLoopBasedDirective::HelperExprs B;
14017 // In presence of clause 'collapse' with number of loops, it will
14018 // define the nested loops number.
14019 unsigned NestedLoopCount = checkOpenMPLoop(
14020 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14021 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14022 VarsWithImplicitDSA, B);
14023 if (NestedLoopCount == 0)
14024 return StmtError();
14025
14026 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14027 "omp for loop exprs were not built");
14028
14030 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14031 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14032}
14033
14035 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14036 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14037 if (!AStmt)
14038 return StmtError();
14039
14041 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
14042
14043 OMPLoopBasedDirective::HelperExprs B;
14044 // In presence of clause 'collapse' with number of loops, it will
14045 // define the nested loops number.
14046 unsigned NestedLoopCount = checkOpenMPLoop(
14047 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14048 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14049 VarsWithImplicitDSA, B);
14050 if (NestedLoopCount == 0)
14051 return StmtError();
14052
14053 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14054 return StmtError();
14055
14057 return StmtError();
14058
14060 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14061}
14062
14064 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14065 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14066 if (!AStmt)
14067 return StmtError();
14068
14069 CapturedStmt *CS =
14070 setBranchProtectedScope(SemaRef, OMPD_distribute_simd, AStmt);
14071
14072 OMPLoopBasedDirective::HelperExprs B;
14073 // In presence of clause 'collapse' with number of loops, it will
14074 // define the nested loops number.
14075 unsigned NestedLoopCount =
14076 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
14077 nullptr /*ordered not a clause on distribute*/, CS,
14078 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14079 if (NestedLoopCount == 0)
14080 return StmtError();
14081
14082 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14083 return StmtError();
14084
14086 return StmtError();
14087
14088 return OMPDistributeSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
14089 NestedLoopCount, Clauses, AStmt, B);
14090}
14091
14093 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14094 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14095 if (!AStmt)
14096 return StmtError();
14097
14098 CapturedStmt *CS =
14099 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for_simd, AStmt);
14100
14101 OMPLoopBasedDirective::HelperExprs B;
14102 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14103 // define the nested loops number.
14104 unsigned NestedLoopCount = checkOpenMPLoop(
14105 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
14106 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
14107 VarsWithImplicitDSA, B);
14108 if (NestedLoopCount == 0)
14109 return StmtError();
14110
14111 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14112 return StmtError();
14113
14115 return StmtError();
14116
14118 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14119}
14120
14122 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14123 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14124 if (!AStmt)
14125 return StmtError();
14126
14127 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target_simd, AStmt);
14128
14129 OMPLoopBasedDirective::HelperExprs B;
14130 // In presence of clause 'collapse' with number of loops, it will define the
14131 // nested loops number.
14132 unsigned NestedLoopCount =
14133 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
14134 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
14135 VarsWithImplicitDSA, B);
14136 if (NestedLoopCount == 0)
14137 return StmtError();
14138
14139 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14140 return StmtError();
14141
14143 return StmtError();
14144
14145 return OMPTargetSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
14146 NestedLoopCount, Clauses, AStmt, B);
14147}
14148
14150 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14151 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14152 if (!AStmt)
14153 return StmtError();
14154
14155 CapturedStmt *CS =
14156 setBranchProtectedScope(SemaRef, OMPD_teams_distribute, AStmt);
14157
14158 OMPLoopBasedDirective::HelperExprs B;
14159 // In presence of clause 'collapse' with number of loops, it will
14160 // define the nested loops number.
14161 unsigned NestedLoopCount =
14162 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
14163 nullptr /*ordered not a clause on distribute*/, CS,
14164 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14165 if (NestedLoopCount == 0)
14166 return StmtError();
14167
14168 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14169 "omp teams distribute loop exprs were not built");
14170
14171 DSAStack->setParentTeamsRegionLoc(StartLoc);
14172
14174 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14175}
14176
14178 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14179 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14180 if (!AStmt)
14181 return StmtError();
14182
14183 CapturedStmt *CS =
14184 setBranchProtectedScope(SemaRef, OMPD_teams_distribute_simd, AStmt);
14185
14186 OMPLoopBasedDirective::HelperExprs B;
14187 // In presence of clause 'collapse' with number of loops, it will
14188 // define the nested loops number.
14189 unsigned NestedLoopCount = checkOpenMPLoop(
14190 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14191 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14192 VarsWithImplicitDSA, B);
14193 if (NestedLoopCount == 0)
14194 return StmtError();
14195
14196 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14197 return StmtError();
14198
14200 return StmtError();
14201
14202 DSAStack->setParentTeamsRegionLoc(StartLoc);
14203
14205 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14206}
14207
14209 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14210 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14211 if (!AStmt)
14212 return StmtError();
14213
14215 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
14216
14217 OMPLoopBasedDirective::HelperExprs B;
14218 // In presence of clause 'collapse' with number of loops, it will
14219 // define the nested loops number.
14220 unsigned NestedLoopCount = checkOpenMPLoop(
14221 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14222 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14223 VarsWithImplicitDSA, B);
14224 if (NestedLoopCount == 0)
14225 return StmtError();
14226
14227 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14228 return StmtError();
14229
14231 return StmtError();
14232
14233 DSAStack->setParentTeamsRegionLoc(StartLoc);
14234
14236 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14237}
14238
14240 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14241 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14242 if (!AStmt)
14243 return StmtError();
14244
14246 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
14247
14248 OMPLoopBasedDirective::HelperExprs B;
14249 // In presence of clause 'collapse' with number of loops, it will
14250 // define the nested loops number.
14251 unsigned NestedLoopCount = checkOpenMPLoop(
14252 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14253 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14254 VarsWithImplicitDSA, B);
14255
14256 if (NestedLoopCount == 0)
14257 return StmtError();
14258
14259 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14260 "omp for loop exprs were not built");
14261
14262 DSAStack->setParentTeamsRegionLoc(StartLoc);
14263
14265 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14266 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14267}
14268
14270 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14271 SourceLocation EndLoc) {
14272 if (!AStmt)
14273 return StmtError();
14274
14275 setBranchProtectedScope(SemaRef, OMPD_target_teams, AStmt);
14276
14277 const OMPClause *BareClause = nullptr;
14278 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) &&
14279 hasClauses(Clauses, OMPC_thread_limit);
14280 bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) {
14281 BareClause = C;
14282 return C->getClauseKind() == OMPC_ompx_bare;
14283 });
14284
14285 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14286 Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
14287 return StmtError();
14288 }
14289
14290 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
14291 unsigned DiagNo = HasBareClause
14292 ? diag::err_ompx_more_than_three_expr_not_allowed
14293 : diag::err_omp_multi_expr_not_allowed;
14294 if (!checkNumExprsInClause<OMPNumTeamsClause>(*this, Clauses,
14295 ClauseMaxNumExprs, DiagNo) ||
14297 ClauseMaxNumExprs, DiagNo))
14298 return StmtError();
14299
14300 return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc,
14301 Clauses, AStmt);
14302}
14303
14305 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14306 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14307 if (!AStmt)
14308 return StmtError();
14309
14311 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14313 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14314 return StmtError();
14315
14316 CapturedStmt *CS =
14317 setBranchProtectedScope(SemaRef, OMPD_target_teams_distribute, AStmt);
14318
14319 OMPLoopBasedDirective::HelperExprs B;
14320 // In presence of clause 'collapse' with number of loops, it will
14321 // define the nested loops number.
14322 unsigned NestedLoopCount = checkOpenMPLoop(
14323 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14324 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14325 VarsWithImplicitDSA, B);
14326 if (NestedLoopCount == 0)
14327 return StmtError();
14328
14329 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14330 "omp target teams distribute loop exprs were not built");
14331
14333 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14334}
14335
14337 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14338 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14339 if (!AStmt)
14340 return StmtError();
14341
14343 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14345 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14346 return StmtError();
14347
14349 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14350
14351 OMPLoopBasedDirective::HelperExprs B;
14352 // In presence of clause 'collapse' with number of loops, it will
14353 // define the nested loops number.
14354 unsigned NestedLoopCount = checkOpenMPLoop(
14355 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14356 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14357 VarsWithImplicitDSA, B);
14358 if (NestedLoopCount == 0)
14359 return StmtError();
14360
14361 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14362 return StmtError();
14363
14365 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14366 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14367}
14368
14370 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14371 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14372 if (!AStmt)
14373 return StmtError();
14374
14376 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14378 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14379 return StmtError();
14380
14382 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14383
14384 OMPLoopBasedDirective::HelperExprs B;
14385 // In presence of clause 'collapse' with number of loops, it will
14386 // define the nested loops number.
14387 unsigned NestedLoopCount =
14388 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14389 getCollapseNumberExpr(Clauses),
14390 nullptr /*ordered not a clause on distribute*/, CS,
14391 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14392 if (NestedLoopCount == 0)
14393 return StmtError();
14394
14395 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14396 return StmtError();
14397
14399 return StmtError();
14400
14402 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14403}
14404
14406 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14407 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14408 if (!AStmt)
14409 return StmtError();
14410
14412 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14414 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14415 return StmtError();
14416
14418 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14419
14420 OMPLoopBasedDirective::HelperExprs B;
14421 // In presence of clause 'collapse' with number of loops, it will
14422 // define the nested loops number.
14423 unsigned NestedLoopCount = checkOpenMPLoop(
14424 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14425 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14426 VarsWithImplicitDSA, B);
14427 if (NestedLoopCount == 0)
14428 return StmtError();
14429
14430 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14431 return StmtError();
14432
14434 return StmtError();
14435
14437 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14438}
14439
14440/// Updates OriginalInits by checking Transform against loop transformation
14441/// directives and appending their pre-inits if a match is found.
14443 SmallVectorImpl<Stmt *> &PreInits) {
14444 Stmt *Dir = Transform->getDirective();
14445 switch (Dir->getStmtClass()) {
14446#define STMT(CLASS, PARENT)
14447#define ABSTRACT_STMT(CLASS)
14448#define COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT) \
14449 case Stmt::CLASS##Class: \
14450 appendFlattenedStmtList(PreInits, \
14451 static_cast<const CLASS *>(Dir)->getPreInits()); \
14452 break;
14453#define OMPCANONICALLOOPNESTTRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14454 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14455#define OMPCANONICALLOOPSEQUENCETRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14456 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14457#include "clang/AST/StmtNodes.inc"
14458#undef COMMON_OMP_LOOP_TRANSFORMATION
14459 default:
14460 llvm_unreachable("Not a loop transformation");
14461 }
14462}
14463
14464bool SemaOpenMP::checkTransformableLoopNest(
14465 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14467 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *>> &OriginalInits) {
14468 OriginalInits.emplace_back();
14469 bool Result = OMPLoopBasedDirective::doForAllLoops(
14470 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14471 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14472 Stmt *CurStmt) {
14473 VarsWithInheritedDSAType TmpDSA;
14474 unsigned SingleNumLoops =
14475 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14476 TmpDSA, LoopHelpers[Cnt]);
14477 if (SingleNumLoops == 0)
14478 return true;
14479 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14480 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14481 OriginalInits.back().push_back(For->getInit());
14482 Body = For->getBody();
14483 } else {
14484 assert(isa<CXXForRangeStmt>(CurStmt) &&
14485 "Expected canonical for or range-based for loops.");
14486 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14487 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14488 Body = CXXFor->getBody();
14489 }
14490 OriginalInits.emplace_back();
14491 return false;
14492 },
14493 [&OriginalInits](OMPLoopTransformationDirective *Transform) {
14494 updatePreInits(Transform, OriginalInits.back());
14495 });
14496 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14497 OriginalInits.pop_back();
14498 return Result;
14499}
14500
14501/// Counts the total number of OpenMP canonical nested loops, including the
14502/// outermost loop (the original loop). PRECONDITION of this visitor is that it
14503/// must be invoked from the original loop to be analyzed. The traversal stops
14504/// for Decl's and Expr's given that they may contain inner loops that must not
14505/// be counted.
14506///
14507/// Example AST structure for the code:
14508///
14509/// int main() {
14510/// #pragma omp fuse
14511/// {
14512/// for (int i = 0; i < 100; i++) { <-- Outer loop
14513/// []() {
14514/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (1)
14515/// };
14516/// for(int j = 0; j < 5; ++j) {} <-- Inner loop
14517/// }
14518/// for (int r = 0; i < 100; i++) { <-- Outer loop
14519/// struct LocalClass {
14520/// void bar() {
14521/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (2)
14522/// }
14523/// };
14524/// for(int k = 0; k < 10; ++k) {} <-- Inner loop
14525/// {x = 5; for(k = 0; k < 10; ++k) x += k; x}; <-- NOT A LOOP (3)
14526/// }
14527/// }
14528/// }
14529/// (1) because in a different function (here: a lambda)
14530/// (2) because in a different function (here: class method)
14531/// (3) because considered to be intervening-code of non-perfectly nested loop
14532/// Result: Loop 'i' contains 2 loops, Loop 'r' also contains 2 loops.
14534private:
14535 unsigned NestedLoopCount = 0;
14536
14537public:
14538 explicit NestedLoopCounterVisitor() = default;
14539
14540 unsigned getNestedLoopCount() const { return NestedLoopCount; }
14541
14542 bool VisitForStmt(ForStmt *FS) override {
14543 ++NestedLoopCount;
14544 return true;
14545 }
14546
14548 ++NestedLoopCount;
14549 return true;
14550 }
14551
14552 bool TraverseStmt(Stmt *S) override {
14553 if (!S)
14554 return true;
14555
14556 // Skip traversal of all expressions, including special cases like
14557 // LambdaExpr, StmtExpr, BlockExpr, and RequiresExpr. These expressions
14558 // may contain inner statements (and even loops), but they are not part
14559 // of the syntactic body of the surrounding loop structure.
14560 // Therefore must not be counted.
14561 if (isa<Expr>(S))
14562 return true;
14563
14564 // Only recurse into CompoundStmt (block {}) and loop bodies.
14567 }
14568
14569 // Stop traversal of the rest of statements, that break perfect
14570 // loop nesting, such as control flow (IfStmt, SwitchStmt...).
14571 return true;
14572 }
14573
14574 bool TraverseDecl(Decl *D) override {
14575 // Stop in the case of finding a declaration, it is not important
14576 // in order to find nested loops (Possible CXXRecordDecl, RecordDecl,
14577 // FunctionDecl...).
14578 return true;
14579 }
14580};
14581
14582bool SemaOpenMP::analyzeLoopSequence(Stmt *LoopSeqStmt,
14583 LoopSequenceAnalysis &SeqAnalysis,
14584 ASTContext &Context,
14585 OpenMPDirectiveKind Kind) {
14587 // Helper Lambda to handle storing initialization and body statements for
14588 // both ForStmt and CXXForRangeStmt.
14589 auto StoreLoopStatements = [](LoopAnalysis &Analysis, Stmt *LoopStmt) {
14590 if (auto *For = dyn_cast<ForStmt>(LoopStmt)) {
14591 Analysis.OriginalInits.push_back(For->getInit());
14592 Analysis.TheForStmt = For;
14593 } else {
14594 auto *CXXFor = cast<CXXForRangeStmt>(LoopStmt);
14595 Analysis.OriginalInits.push_back(CXXFor->getBeginStmt());
14596 Analysis.TheForStmt = CXXFor;
14597 }
14598 };
14599
14600 // Helper lambda functions to encapsulate the processing of different
14601 // derivations of the canonical loop sequence grammar
14602 // Modularized code for handling loop generation and transformations.
14603 auto AnalyzeLoopGeneration = [&](Stmt *Child) {
14604 auto *LoopTransform = cast<OMPLoopTransformationDirective>(Child);
14605 Stmt *TransformedStmt = LoopTransform->getTransformedStmt();
14606 unsigned NumGeneratedTopLevelLoops =
14607 LoopTransform->getNumGeneratedTopLevelLoops();
14608 // Handle the case where transformed statement is not available due to
14609 // dependent contexts
14610 if (!TransformedStmt) {
14611 if (NumGeneratedTopLevelLoops > 0) {
14612 SeqAnalysis.LoopSeqSize += NumGeneratedTopLevelLoops;
14613 return true;
14614 }
14615 // Unroll full (0 loops produced)
14616 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14617 << 0 << getOpenMPDirectiveName(Kind);
14618 return false;
14619 }
14620 // Handle loop transformations with multiple loop nests
14621 // Unroll full
14622 if (!NumGeneratedTopLevelLoops) {
14623 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14624 << 0 << getOpenMPDirectiveName(Kind);
14625 return false;
14626 }
14627 // Loop transformatons such as split or loopranged fuse
14628 if (NumGeneratedTopLevelLoops > 1) {
14629 // Get the preinits related to this loop sequence generating
14630 // loop transformation (i.e loopranged fuse, split...)
14631 // These preinits differ slightly from regular inits/pre-inits related
14632 // to single loop generating loop transformations (interchange, unroll)
14633 // given that they are not bounded to a particular loop nest
14634 // so they need to be treated independently
14635 updatePreInits(LoopTransform, SeqAnalysis.LoopSequencePreInits);
14636 return analyzeLoopSequence(TransformedStmt, SeqAnalysis, Context, Kind);
14637 }
14638 // Vast majority: (Tile, Unroll, Stripe, Reverse, Interchange, Fuse all)
14639 // Process the transformed loop statement
14640 LoopAnalysis &NewTransformedSingleLoop =
14641 SeqAnalysis.Loops.emplace_back(Child);
14642 unsigned IsCanonical = checkOpenMPLoop(
14643 Kind, nullptr, nullptr, TransformedStmt, SemaRef, *DSAStack, TmpDSA,
14644 NewTransformedSingleLoop.HelperExprs);
14645
14646 if (!IsCanonical)
14647 return false;
14648
14649 StoreLoopStatements(NewTransformedSingleLoop, TransformedStmt);
14650 updatePreInits(LoopTransform, NewTransformedSingleLoop.TransformsPreInits);
14651
14652 SeqAnalysis.LoopSeqSize++;
14653 return true;
14654 };
14655
14656 // Modularized code for handling regular canonical loops.
14657 auto AnalyzeRegularLoop = [&](Stmt *Child) {
14658 LoopAnalysis &NewRegularLoop = SeqAnalysis.Loops.emplace_back(Child);
14659 unsigned IsCanonical =
14660 checkOpenMPLoop(Kind, nullptr, nullptr, Child, SemaRef, *DSAStack,
14661 TmpDSA, NewRegularLoop.HelperExprs);
14662
14663 if (!IsCanonical)
14664 return false;
14665
14666 StoreLoopStatements(NewRegularLoop, Child);
14667 NestedLoopCounterVisitor NLCV;
14668 NLCV.TraverseStmt(Child);
14669 return true;
14670 };
14671
14672 // High level grammar validation.
14673 for (Stmt *Child : LoopSeqStmt->children()) {
14674 if (!Child)
14675 continue;
14676 // Skip over non-loop-sequence statements.
14677 if (!LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14678 Child = Child->IgnoreContainers();
14679 // Ignore empty compound statement.
14680 if (!Child)
14681 continue;
14682 // In the case of a nested loop sequence ignoring containers would not
14683 // be enough, a recurisve transversal of the loop sequence is required.
14684 if (isa<CompoundStmt>(Child)) {
14685 if (!analyzeLoopSequence(Child, SeqAnalysis, Context, Kind))
14686 return false;
14687 // Already been treated, skip this children
14688 continue;
14689 }
14690 }
14691 // Regular loop sequence handling.
14692 if (LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14693 if (LoopAnalysis::isLoopTransformation(Child)) {
14694 if (!AnalyzeLoopGeneration(Child))
14695 return false;
14696 // AnalyzeLoopGeneration updates SeqAnalysis.LoopSeqSize accordingly.
14697 } else {
14698 if (!AnalyzeRegularLoop(Child))
14699 return false;
14700 SeqAnalysis.LoopSeqSize++;
14701 }
14702 } else {
14703 // Report error for invalid statement inside canonical loop sequence.
14704 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14705 << 0 << getOpenMPDirectiveName(Kind);
14706 return false;
14707 }
14708 }
14709 return true;
14710}
14711
14712bool SemaOpenMP::checkTransformableLoopSequence(
14713 OpenMPDirectiveKind Kind, Stmt *AStmt, LoopSequenceAnalysis &SeqAnalysis,
14714 ASTContext &Context) {
14715 // Following OpenMP 6.0 API Specification, a Canonical Loop Sequence follows
14716 // the grammar:
14717 //
14718 // canonical-loop-sequence:
14719 // {
14720 // loop-sequence+
14721 // }
14722 // where loop-sequence can be any of the following:
14723 // 1. canonical-loop-sequence
14724 // 2. loop-nest
14725 // 3. loop-sequence-generating-construct (i.e OMPLoopTransformationDirective)
14726 //
14727 // To recognise and traverse this structure the helper function
14728 // analyzeLoopSequence serves as the recurisve entry point
14729 // and tries to match the input AST to the canonical loop sequence grammar
14730 // structure. This function will perform both a semantic and syntactical
14731 // analysis of the given statement according to OpenMP 6.0 definition of
14732 // the aforementioned canonical loop sequence.
14733
14734 // We expect an outer compound statement.
14735 if (!isa<CompoundStmt>(AStmt)) {
14736 Diag(AStmt->getBeginLoc(), diag::err_omp_not_a_loop_sequence)
14737 << getOpenMPDirectiveName(Kind);
14738 return false;
14739 }
14740
14741 // Recursive entry point to process the main loop sequence
14742 if (!analyzeLoopSequence(AStmt, SeqAnalysis, Context, Kind))
14743 return false;
14744
14745 // Diagnose an empty loop sequence.
14746 if (!SeqAnalysis.LoopSeqSize) {
14747 Diag(AStmt->getBeginLoc(), diag::err_omp_empty_loop_sequence)
14748 << getOpenMPDirectiveName(Kind);
14749 return false;
14750 }
14751 return true;
14752}
14753
14754/// Add preinit statements that need to be propagated from the selected loop.
14755static void addLoopPreInits(ASTContext &Context,
14756 OMPLoopBasedDirective::HelperExprs &LoopHelper,
14757 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
14758 SmallVectorImpl<Stmt *> &PreInits) {
14759
14760 // For range-based for-statements, ensure that their syntactic sugar is
14761 // executed by adding them as pre-init statements.
14762 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14763 Stmt *RangeInit = CXXRangeFor->getInit();
14764 if (RangeInit)
14765 PreInits.push_back(RangeInit);
14766
14767 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14768 PreInits.push_back(new (Context) DeclStmt(RangeStmt->getDeclGroup(),
14769 RangeStmt->getBeginLoc(),
14770 RangeStmt->getEndLoc()));
14771
14772 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14773 PreInits.push_back(new (Context) DeclStmt(RangeEnd->getDeclGroup(),
14774 RangeEnd->getBeginLoc(),
14775 RangeEnd->getEndLoc()));
14776 }
14777
14778 llvm::append_range(PreInits, OriginalInit);
14779
14780 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
14781 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
14782 PreInits.push_back(new (Context) DeclStmt(
14783 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14784 }
14785
14786 // Gather declarations for the data members used as counters.
14787 for (Expr *CounterRef : LoopHelper.Counters) {
14788 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14789 if (isa<OMPCapturedExprDecl>(CounterDecl))
14790 PreInits.push_back(new (Context) DeclStmt(
14791 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
14792 }
14793}
14794
14795/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
14796/// loop of a construct.
14797static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) {
14798 size_t NumLoops = LoopStmts.size();
14799 OMPLoopBasedDirective::doForAllLoops(
14800 AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
14801 [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
14802 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
14803 LoopStmts[Cnt] = CurStmt;
14804 return false;
14805 });
14806 assert(!is_contained(LoopStmts, nullptr) &&
14807 "Expecting a loop statement for each affected loop");
14808}
14809
14810/// Build and return a DeclRefExpr for the floor induction variable using the
14811/// SemaRef and the provided parameters.
14812static Expr *makeFloorIVRef(Sema &SemaRef, ArrayRef<VarDecl *> FloorIndVars,
14813 int I, QualType IVTy, DeclRefExpr *OrigCntVar) {
14814 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14815 OrigCntVar->getExprLoc());
14816}
14817
14819 Stmt *AStmt,
14820 SourceLocation StartLoc,
14821 SourceLocation EndLoc) {
14822 ASTContext &Context = getASTContext();
14823 Scope *CurScope = SemaRef.getCurScope();
14824
14825 const auto *SizesClause =
14826 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14827 if (!SizesClause ||
14828 llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; }))
14829 return StmtError();
14830 unsigned NumLoops = SizesClause->getNumSizes();
14831
14832 // Empty statement should only be possible if there already was an error.
14833 if (!AStmt)
14834 return StmtError();
14835
14836 // Verify and diagnose loop nest.
14838 Stmt *Body = nullptr;
14839 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
14840 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14841 OriginalInits))
14842 return StmtError();
14843
14844 // Delay tiling to when template is completely instantiated.
14845 if (SemaRef.CurContext->isDependentContext())
14846 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14847 NumLoops, AStmt, nullptr, nullptr);
14848
14849 assert(LoopHelpers.size() == NumLoops &&
14850 "Expecting loop iteration space dimensionality to match number of "
14851 "affected loops");
14852 assert(OriginalInits.size() == NumLoops &&
14853 "Expecting loop iteration space dimensionality to match number of "
14854 "affected loops");
14855
14856 // Collect all affected loop statements.
14857 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14858 collectLoopStmts(AStmt, LoopStmts);
14859
14860 SmallVector<Stmt *, 4> PreInits;
14861 CaptureVars CopyTransformer(SemaRef);
14862
14863 // Create iteration variables for the generated loops.
14864 SmallVector<VarDecl *, 4> FloorIndVars;
14865 SmallVector<VarDecl *, 4> TileIndVars;
14866 FloorIndVars.resize(NumLoops);
14867 TileIndVars.resize(NumLoops);
14868 for (unsigned I = 0; I < NumLoops; ++I) {
14869 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14870
14871 assert(LoopHelper.Counters.size() == 1 &&
14872 "Expect single-dimensional loop iteration space");
14873 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14874 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14875 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14876 QualType CntTy = IterVarRef->getType();
14877
14878 // Iteration variable for the floor (i.e. outer) loop.
14879 {
14880 std::string FloorCntName =
14881 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14882 VarDecl *FloorCntDecl =
14883 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14884 FloorIndVars[I] = FloorCntDecl;
14885 }
14886
14887 // Iteration variable for the tile (i.e. inner) loop.
14888 {
14889 std::string TileCntName =
14890 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14891
14892 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14893 // used by the expressions to derive the original iteration variable's
14894 // value from the logical iteration number.
14895 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14896 TileCntDecl->setDeclName(
14897 &SemaRef.PP.getIdentifierTable().get(TileCntName));
14898 TileIndVars[I] = TileCntDecl;
14899 }
14900
14901 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
14902 PreInits);
14903 }
14904
14905 // Once the original iteration values are set, append the innermost body.
14906 Stmt *Inner = Body;
14907
14908 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
14909 SizesClause, CurScope](int I) -> Expr * {
14910 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14911
14912 if (DimTileSizeExpr->containsErrors())
14913 return nullptr;
14914
14915 if (isa<ConstantExpr>(DimTileSizeExpr))
14916 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14917
14918 // When the tile size is not a constant but a variable, it is possible to
14919 // pass non-positive numbers. For instance:
14920 // \code{c}
14921 // int a = 0;
14922 // #pragma omp tile sizes(a)
14923 // for (int i = 0; i < 42; ++i)
14924 // body(i);
14925 // \endcode
14926 // Although there is no meaningful interpretation of the tile size, the body
14927 // should still be executed 42 times to avoid surprises. To preserve the
14928 // invariant that every loop iteration is executed exactly once and not
14929 // cause an infinite loop, apply a minimum tile size of one.
14930 // Build expr:
14931 // \code{c}
14932 // (TS <= 0) ? 1 : TS
14933 // \endcode
14934 QualType DimTy = DimTileSizeExpr->getType();
14935 uint64_t DimWidth = Context.getTypeSize(DimTy);
14937 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14938 IntegerLiteral *One =
14939 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
14940 Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
14941 CurScope, {}, BO_LE,
14942 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
14943 Expr *MinOne = new (Context) ConditionalOperator(
14944 Cond, {}, One, {},
14945 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14947 return MinOne;
14948 };
14949
14950 // Create tile loops from the inside to the outside.
14951 for (int I = NumLoops - 1; I >= 0; --I) {
14952 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14953 Expr *NumIterations = LoopHelper.NumIterations;
14954 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14955 QualType IVTy = NumIterations->getType();
14956 Stmt *LoopStmt = LoopStmts[I];
14957
14958 // Commonly used variables. One of the constraints of an AST is that every
14959 // node object must appear at most once, hence we define a lambda that
14960 // creates a new AST node at every use.
14961 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
14962 OrigCntVar]() {
14963 return buildDeclRefExpr(SemaRef, TileIndVars[I], IVTy,
14964 OrigCntVar->getExprLoc());
14965 };
14966
14967 // For init-statement: auto .tile.iv = .floor.iv
14968 SemaRef.AddInitializerToDecl(
14969 TileIndVars[I],
14970 SemaRef
14971 .DefaultLvalueConversion(
14972 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
14973 .get(),
14974 /*DirectInit=*/false);
14975 Decl *CounterDecl = TileIndVars[I];
14976 StmtResult InitStmt = new (Context)
14977 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14978 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14979 if (!InitStmt.isUsable())
14980 return StmtError();
14981
14982 // For cond-expression:
14983 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
14984 Expr *DimTileSize = MakeDimTileSize(I);
14985 if (!DimTileSize)
14986 return StmtError();
14987 ExprResult EndOfTile = SemaRef.BuildBinOp(
14988 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14989 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14990 DimTileSize);
14991 if (!EndOfTile.isUsable())
14992 return StmtError();
14993 ExprResult IsPartialTile =
14994 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14995 NumIterations, EndOfTile.get());
14996 if (!IsPartialTile.isUsable())
14997 return StmtError();
14998 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
14999 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15000 IsPartialTile.get(), NumIterations, EndOfTile.get());
15001 if (!MinTileAndIterSpace.isUsable())
15002 return StmtError();
15003 ExprResult CondExpr =
15004 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15005 MakeTileIVRef(), MinTileAndIterSpace.get());
15006 if (!CondExpr.isUsable())
15007 return StmtError();
15008
15009 // For incr-statement: ++.tile.iv
15010 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15011 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
15012 if (!IncrStmt.isUsable())
15013 return StmtError();
15014
15015 // Statements to set the original iteration variable's value from the
15016 // logical iteration number.
15017 // Generated for loop is:
15018 // \code
15019 // Original_for_init;
15020 // for (auto .tile.iv = .floor.iv;
15021 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
15022 // ++.tile.iv) {
15023 // Original_Body;
15024 // Original_counter_update;
15025 // }
15026 // \endcode
15027 // FIXME: If the innermost body is an loop itself, inserting these
15028 // statements stops it being recognized as a perfectly nested loop (e.g.
15029 // for applying tiling again). If this is the case, sink the expressions
15030 // further into the inner loop.
15031 SmallVector<Stmt *, 4> BodyParts;
15032 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15033 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15034 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15035 BodyParts.push_back(Inner);
15036 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15037 Inner->getBeginLoc(), Inner->getEndLoc());
15038 Inner = new (Context)
15039 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15040 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15041 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15042 }
15043
15044 // Create floor loops from the inside to the outside.
15045 for (int I = NumLoops - 1; I >= 0; --I) {
15046 auto &LoopHelper = LoopHelpers[I];
15047 Expr *NumIterations = LoopHelper.NumIterations;
15048 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15049 QualType IVTy = NumIterations->getType();
15050
15051 // For init-statement: auto .floor.iv = 0
15052 SemaRef.AddInitializerToDecl(
15053 FloorIndVars[I],
15054 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15055 /*DirectInit=*/false);
15056 Decl *CounterDecl = FloorIndVars[I];
15057 StmtResult InitStmt = new (Context)
15058 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15059 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15060 if (!InitStmt.isUsable())
15061 return StmtError();
15062
15063 // For cond-expression: .floor.iv < NumIterations
15064 ExprResult CondExpr = SemaRef.BuildBinOp(
15065 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15066 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15067 NumIterations);
15068 if (!CondExpr.isUsable())
15069 return StmtError();
15070
15071 // For incr-statement: .floor.iv += DimTileSize
15072 Expr *DimTileSize = MakeDimTileSize(I);
15073 if (!DimTileSize)
15074 return StmtError();
15075 ExprResult IncrStmt = SemaRef.BuildBinOp(
15076 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15077 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15078 DimTileSize);
15079 if (!IncrStmt.isUsable())
15080 return StmtError();
15081
15082 Inner = new (Context)
15083 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15084 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15085 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15086 }
15087
15088 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
15089 AStmt, Inner,
15090 buildPreInits(Context, PreInits));
15091}
15092
15094 Stmt *AStmt,
15095 SourceLocation StartLoc,
15096 SourceLocation EndLoc) {
15097 ASTContext &Context = getASTContext();
15098 Scope *CurScope = SemaRef.getCurScope();
15099
15100 const auto *SizesClause =
15101 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
15102 if (!SizesClause ||
15103 llvm::any_of(SizesClause->getSizesRefs(), [](const Expr *SizeExpr) {
15104 return !SizeExpr || SizeExpr->containsErrors();
15105 }))
15106 return StmtError();
15107 unsigned NumLoops = SizesClause->getNumSizes();
15108
15109 // Empty statement should only be possible if there already was an error.
15110 if (!AStmt)
15111 return StmtError();
15112
15113 // Verify and diagnose loop nest.
15115 Stmt *Body = nullptr;
15116 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
15117 if (!checkTransformableLoopNest(OMPD_stripe, AStmt, NumLoops, LoopHelpers,
15118 Body, OriginalInits))
15119 return StmtError();
15120
15121 // Delay striping to when template is completely instantiated.
15122 if (SemaRef.CurContext->isDependentContext())
15123 return OMPStripeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15124 NumLoops, AStmt, nullptr, nullptr);
15125
15126 assert(LoopHelpers.size() == NumLoops &&
15127 "Expecting loop iteration space dimensionality to match number of "
15128 "affected loops");
15129 assert(OriginalInits.size() == NumLoops &&
15130 "Expecting loop iteration space dimensionality to match number of "
15131 "affected loops");
15132
15133 // Collect all affected loop statements.
15134 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15135 collectLoopStmts(AStmt, LoopStmts);
15136
15137 SmallVector<Stmt *, 4> PreInits;
15138 CaptureVars CopyTransformer(SemaRef);
15139
15140 // Create iteration variables for the generated loops.
15141 SmallVector<VarDecl *, 4> FloorIndVars;
15142 SmallVector<VarDecl *, 4> StripeIndVars;
15143 FloorIndVars.resize(NumLoops);
15144 StripeIndVars.resize(NumLoops);
15145 for (unsigned I : llvm::seq<unsigned>(NumLoops)) {
15146 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15147
15148 assert(LoopHelper.Counters.size() == 1 &&
15149 "Expect single-dimensional loop iteration space");
15150 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15151 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15152 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15153 QualType CntTy = IterVarRef->getType();
15154
15155 // Iteration variable for the stripe (i.e. outer) loop.
15156 {
15157 std::string FloorCntName =
15158 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15159 VarDecl *FloorCntDecl =
15160 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
15161 FloorIndVars[I] = FloorCntDecl;
15162 }
15163
15164 // Iteration variable for the stripe (i.e. inner) loop.
15165 {
15166 std::string StripeCntName =
15167 (Twine(".stripe_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15168
15169 // Reuse the iteration variable created by checkOpenMPLoop. It is also
15170 // used by the expressions to derive the original iteration variable's
15171 // value from the logical iteration number.
15172 auto *StripeCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15173 StripeCntDecl->setDeclName(
15174 &SemaRef.PP.getIdentifierTable().get(StripeCntName));
15175 StripeIndVars[I] = StripeCntDecl;
15176 }
15177
15178 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
15179 PreInits);
15180 }
15181
15182 // Once the original iteration values are set, append the innermost body.
15183 Stmt *Inner = Body;
15184
15185 auto MakeDimStripeSize = [&](int I) -> Expr * {
15186 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
15187 if (isa<ConstantExpr>(DimStripeSizeExpr))
15188 return AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr));
15189
15190 // When the stripe size is not a constant but a variable, it is possible to
15191 // pass non-positive numbers. For instance:
15192 // \code{c}
15193 // int a = 0;
15194 // #pragma omp stripe sizes(a)
15195 // for (int i = 0; i < 42; ++i)
15196 // body(i);
15197 // \endcode
15198 // Although there is no meaningful interpretation of the stripe size, the
15199 // body should still be executed 42 times to avoid surprises. To preserve
15200 // the invariant that every loop iteration is executed exactly once and not
15201 // cause an infinite loop, apply a minimum stripe size of one.
15202 // Build expr:
15203 // \code{c}
15204 // (TS <= 0) ? 1 : TS
15205 // \endcode
15206 QualType DimTy = DimStripeSizeExpr->getType();
15207 uint64_t DimWidth = Context.getTypeSize(DimTy);
15209 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
15210 IntegerLiteral *One =
15211 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
15212 Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
15213 CurScope, {}, BO_LE,
15214 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), Zero));
15215 Expr *MinOne = new (Context) ConditionalOperator(
15216 Cond, {}, One, {},
15217 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), DimTy,
15219 return MinOne;
15220 };
15221
15222 // Create stripe loops from the inside to the outside.
15223 for (int I = NumLoops - 1; I >= 0; --I) {
15224 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15225 Expr *NumIterations = LoopHelper.NumIterations;
15226 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15227 QualType IVTy = NumIterations->getType();
15228 Stmt *LoopStmt = LoopStmts[I];
15229
15230 // For init-statement: auto .stripe.iv = .floor.iv
15231 SemaRef.AddInitializerToDecl(
15232 StripeIndVars[I],
15233 SemaRef
15234 .DefaultLvalueConversion(
15235 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
15236 .get(),
15237 /*DirectInit=*/false);
15238 Decl *CounterDecl = StripeIndVars[I];
15239 StmtResult InitStmt = new (Context)
15240 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15241 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15242 if (!InitStmt.isUsable())
15243 return StmtError();
15244
15245 // For cond-expression:
15246 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations)
15247 ExprResult EndOfStripe = SemaRef.BuildBinOp(
15248 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15249 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15250 MakeDimStripeSize(I));
15251 if (!EndOfStripe.isUsable())
15252 return StmtError();
15253 ExprResult IsPartialStripe =
15254 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15255 NumIterations, EndOfStripe.get());
15256 if (!IsPartialStripe.isUsable())
15257 return StmtError();
15258 ExprResult MinStripeAndIterSpace = SemaRef.ActOnConditionalOp(
15259 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15260 IsPartialStripe.get(), NumIterations, EndOfStripe.get());
15261 if (!MinStripeAndIterSpace.isUsable())
15262 return StmtError();
15263 ExprResult CondExpr = SemaRef.BuildBinOp(
15264 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15265 makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar),
15266 MinStripeAndIterSpace.get());
15267 if (!CondExpr.isUsable())
15268 return StmtError();
15269
15270 // For incr-statement: ++.stripe.iv
15271 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15272 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc,
15273 makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar));
15274 if (!IncrStmt.isUsable())
15275 return StmtError();
15276
15277 // Statements to set the original iteration variable's value from the
15278 // logical iteration number.
15279 // Generated for loop is:
15280 // \code
15281 // Original_for_init;
15282 // for (auto .stripe.iv = .floor.iv;
15283 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations);
15284 // ++.stripe.iv) {
15285 // Original_Body;
15286 // Original_counter_update;
15287 // }
15288 // \endcode
15289 // FIXME: If the innermost body is a loop itself, inserting these
15290 // statements stops it being recognized as a perfectly nested loop (e.g.
15291 // for applying another loop transformation). If this is the case, sink the
15292 // expressions further into the inner loop.
15293 SmallVector<Stmt *, 4> BodyParts;
15294 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15295 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15296 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15297 BodyParts.push_back(Inner);
15298 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15299 Inner->getBeginLoc(), Inner->getEndLoc());
15300 Inner = new (Context)
15301 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15302 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15303 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15304 }
15305
15306 // Create grid loops from the inside to the outside.
15307 for (int I = NumLoops - 1; I >= 0; --I) {
15308 auto &LoopHelper = LoopHelpers[I];
15309 Expr *NumIterations = LoopHelper.NumIterations;
15310 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15311 QualType IVTy = NumIterations->getType();
15312
15313 // For init-statement: auto .grid.iv = 0
15314 SemaRef.AddInitializerToDecl(
15315 FloorIndVars[I],
15316 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15317 /*DirectInit=*/false);
15318 Decl *CounterDecl = FloorIndVars[I];
15319 StmtResult InitStmt = new (Context)
15320 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15321 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15322 if (!InitStmt.isUsable())
15323 return StmtError();
15324
15325 // For cond-expression: .floor.iv < NumIterations
15326 ExprResult CondExpr = SemaRef.BuildBinOp(
15327 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15328 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15329 NumIterations);
15330 if (!CondExpr.isUsable())
15331 return StmtError();
15332
15333 // For incr-statement: .floor.iv += DimStripeSize
15334 ExprResult IncrStmt = SemaRef.BuildBinOp(
15335 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15336 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15337 MakeDimStripeSize(I));
15338 if (!IncrStmt.isUsable())
15339 return StmtError();
15340
15341 Inner = new (Context)
15342 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15343 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15344 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15345 }
15346
15347 return OMPStripeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15348 NumLoops, AStmt, Inner,
15349 buildPreInits(Context, PreInits));
15350}
15351
15353 Stmt *AStmt,
15354 SourceLocation StartLoc,
15355 SourceLocation EndLoc) {
15356 ASTContext &Context = getASTContext();
15357 Scope *CurScope = SemaRef.getCurScope();
15358 // Empty statement should only be possible if there already was an error.
15359 if (!AStmt)
15360 return StmtError();
15361
15363 {OMPC_partial, OMPC_full}))
15364 return StmtError();
15365
15366 const OMPFullClause *FullClause =
15367 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15368 const OMPPartialClause *PartialClause =
15369 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15370 assert(!(FullClause && PartialClause) &&
15371 "mutual exclusivity must have been checked before");
15372
15373 constexpr unsigned NumLoops = 1;
15374 Stmt *Body = nullptr;
15376 NumLoops);
15377 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
15378 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15379 Body, OriginalInits))
15380 return StmtError();
15381
15382 unsigned NumGeneratedTopLevelLoops = PartialClause ? 1 : 0;
15383
15384 // Delay unrolling to when template is completely instantiated.
15385 if (SemaRef.CurContext->isDependentContext())
15386 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15387 NumGeneratedTopLevelLoops, nullptr,
15388 nullptr);
15389
15390 assert(LoopHelpers.size() == NumLoops &&
15391 "Expecting a single-dimensional loop iteration space");
15392 assert(OriginalInits.size() == NumLoops &&
15393 "Expecting a single-dimensional loop iteration space");
15394 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15395
15396 if (FullClause) {
15398 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
15399 /*SuppressExprDiags=*/true)
15400 .isUsable()) {
15401 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
15402 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
15403 << "#pragma omp unroll full";
15404 return StmtError();
15405 }
15406 }
15407
15408 // The generated loop may only be passed to other loop-associated directive
15409 // when a partial clause is specified. Without the requirement it is
15410 // sufficient to generate loop unroll metadata at code-generation.
15411 if (NumGeneratedTopLevelLoops == 0)
15412 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15413 NumGeneratedTopLevelLoops, nullptr,
15414 nullptr);
15415
15416 // Otherwise, we need to provide a de-sugared/transformed AST that can be
15417 // associated with another loop directive.
15418 //
15419 // The canonical loop analysis return by checkTransformableLoopNest assumes
15420 // the following structure to be the same loop without transformations or
15421 // directives applied: \code OriginalInits; LoopHelper.PreInits;
15422 // LoopHelper.Counters;
15423 // for (; IV < LoopHelper.NumIterations; ++IV) {
15424 // LoopHelper.Updates;
15425 // Body;
15426 // }
15427 // \endcode
15428 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
15429 // and referenced by LoopHelper.IterationVarRef.
15430 //
15431 // The unrolling directive transforms this into the following loop:
15432 // \code
15433 // OriginalInits; \
15434 // LoopHelper.PreInits; > NewPreInits
15435 // LoopHelper.Counters; /
15436 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
15437 // #pragma clang loop unroll_count(Factor)
15438 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
15439 // {
15440 // LoopHelper.Updates;
15441 // Body;
15442 // }
15443 // }
15444 // \endcode
15445 // where UIV is a new logical iteration counter. IV must be the same VarDecl
15446 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
15447 // references it. If the partially unrolled loop is associated with another
15448 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
15449 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
15450 // OpenMP canonical loop. The inner loop is not an associable canonical loop
15451 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
15452 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
15453 // property of the OMPLoopBasedDirective instead of statements in
15454 // CompoundStatement. This is to allow the loop to become a non-outermost loop
15455 // of a canonical loop nest where these PreInits are emitted before the
15456 // outermost directive.
15457
15458 // Find the loop statement.
15459 Stmt *LoopStmt = nullptr;
15460 collectLoopStmts(AStmt, {LoopStmt});
15461
15462 // Determine the PreInit declarations.
15463 SmallVector<Stmt *, 4> PreInits;
15464 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15465
15466 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15467 QualType IVTy = IterationVarRef->getType();
15468 assert(LoopHelper.Counters.size() == 1 &&
15469 "Expecting a single-dimensional loop iteration space");
15470 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15471
15472 // Determine the unroll factor.
15473 uint64_t Factor;
15474 SourceLocation FactorLoc;
15475 if (Expr *FactorVal = PartialClause->getFactor();
15476 FactorVal && !FactorVal->containsErrors()) {
15477 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15478 FactorLoc = FactorVal->getExprLoc();
15479 } else {
15480 // TODO: Use a better profitability model.
15481 Factor = 2;
15482 }
15483 assert(Factor > 0 && "Expected positive unroll factor");
15484 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
15486 getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor),
15487 IVTy, FactorLoc);
15488 };
15489
15490 // Iteration variable SourceLocations.
15491 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15492 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15493 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15494
15495 // Internal variable names.
15496 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15497 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
15498 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
15499
15500 // Create the iteration variable for the unrolled loop.
15501 VarDecl *OuterIVDecl =
15502 buildVarDecl(SemaRef, {}, IVTy, OuterIVName, nullptr, OrigVar);
15503 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
15504 return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc);
15505 };
15506
15507 // Iteration variable for the inner loop: Reuse the iteration variable created
15508 // by checkOpenMPLoop.
15509 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15510 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(InnerIVName));
15511 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
15512 return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc);
15513 };
15514
15515 // Make a copy of the NumIterations expression for each use: By the AST
15516 // constraints, every expression object in a DeclContext must be unique.
15517 CaptureVars CopyTransformer(SemaRef);
15518 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15519 return AssertSuccess(
15520 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15521 };
15522
15523 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15524 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(MakeOuterRef());
15525 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(),
15526 /*DirectInit=*/false);
15527 StmtResult InnerInit = new (Context)
15528 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15529 if (!InnerInit.isUsable())
15530 return StmtError();
15531
15532 // Inner For cond-expression:
15533 // \code
15534 // .unroll_inner.iv < .unrolled.iv + Factor &&
15535 // .unroll_inner.iv < NumIterations
15536 // \endcode
15537 // This conjunction of two conditions allows ScalarEvolution to derive the
15538 // maximum trip count of the inner loop.
15539 ExprResult EndOfTile =
15540 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15541 MakeOuterRef(), MakeFactorExpr());
15542 if (!EndOfTile.isUsable())
15543 return StmtError();
15544 ExprResult InnerCond1 =
15545 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15546 MakeInnerRef(), EndOfTile.get());
15547 if (!InnerCond1.isUsable())
15548 return StmtError();
15549 ExprResult InnerCond2 =
15550 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15551 MakeInnerRef(), MakeNumIterations());
15552 if (!InnerCond2.isUsable())
15553 return StmtError();
15554 ExprResult InnerCond =
15555 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15556 InnerCond1.get(), InnerCond2.get());
15557 if (!InnerCond.isUsable())
15558 return StmtError();
15559
15560 // Inner For incr-statement: ++.unroll_inner.iv
15561 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
15562 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
15563 if (!InnerIncr.isUsable())
15564 return StmtError();
15565
15566 // Inner For statement.
15567 SmallVector<Stmt *> InnerBodyStmts;
15568 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15569 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15570 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15571 InnerBodyStmts.push_back(Body);
15572 CompoundStmt *InnerBody =
15574 Body->getBeginLoc(), Body->getEndLoc());
15575 ForStmt *InnerFor = new (Context)
15576 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15577 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15578 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15579
15580 // Unroll metadata for the inner loop.
15581 // This needs to take into account the remainder portion of the unrolled loop,
15582 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15583 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15584 // the maximum trip count, which will also generate a remainder loop. Just
15585 // `unroll(enable)` (which could have been useful if the user has not
15586 // specified a concrete factor; even though the outer loop cannot be
15587 // influenced anymore, would avoid more code bloat than necessary) will refuse
15588 // the loop because "Won't unroll; remainder loop could not be generated when
15589 // assuming runtime trip count". Even if it did work, it must not choose a
15590 // larger unroll factor than the maximum loop length, or it would always just
15591 // execute the remainder loop.
15592 LoopHintAttr *UnrollHintAttr =
15593 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15594 LoopHintAttr::Numeric, MakeFactorExpr());
15595 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
15596 getASTContext(), StartLoc, {UnrollHintAttr}, InnerFor);
15597
15598 // Outer For init-statement: auto .unrolled.iv = 0
15599 SemaRef.AddInitializerToDecl(
15600 OuterIVDecl,
15601 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15602 /*DirectInit=*/false);
15603 StmtResult OuterInit = new (Context)
15604 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15605 if (!OuterInit.isUsable())
15606 return StmtError();
15607
15608 // Outer For cond-expression: .unrolled.iv < NumIterations
15609 ExprResult OuterConde =
15610 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15611 MakeOuterRef(), MakeNumIterations());
15612 if (!OuterConde.isUsable())
15613 return StmtError();
15614
15615 // Outer For incr-statement: .unrolled.iv += Factor
15616 ExprResult OuterIncr =
15617 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15618 MakeOuterRef(), MakeFactorExpr());
15619 if (!OuterIncr.isUsable())
15620 return StmtError();
15621
15622 // Outer For statement.
15623 ForStmt *OuterFor = new (Context)
15624 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15625 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15626 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15627
15628 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15629 NumGeneratedTopLevelLoops, OuterFor,
15630 buildPreInits(Context, PreInits));
15631}
15632
15634 SourceLocation StartLoc,
15635 SourceLocation EndLoc) {
15636 ASTContext &Context = getASTContext();
15637 Scope *CurScope = SemaRef.getCurScope();
15638
15639 // Empty statement should only be possible if there already was an error.
15640 if (!AStmt)
15641 return StmtError();
15642
15643 constexpr unsigned NumLoops = 1;
15644 Stmt *Body = nullptr;
15646 NumLoops);
15647 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
15648 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
15649 Body, OriginalInits))
15650 return StmtError();
15651
15652 // Delay applying the transformation to when template is completely
15653 // instantiated.
15654 if (SemaRef.CurContext->isDependentContext())
15655 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
15656 NumLoops, nullptr, nullptr);
15657
15658 assert(LoopHelpers.size() == NumLoops &&
15659 "Expecting a single-dimensional loop iteration space");
15660 assert(OriginalInits.size() == NumLoops &&
15661 "Expecting a single-dimensional loop iteration space");
15662 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15663
15664 // Find the loop statement.
15665 Stmt *LoopStmt = nullptr;
15666 collectLoopStmts(AStmt, {LoopStmt});
15667
15668 // Determine the PreInit declarations.
15669 SmallVector<Stmt *> PreInits;
15670 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15671
15672 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15673 QualType IVTy = IterationVarRef->getType();
15674 uint64_t IVWidth = Context.getTypeSize(IVTy);
15675 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15676
15677 // Iteration variable SourceLocations.
15678 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15679 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15680 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15681
15682 // Locations pointing to the transformation.
15683 SourceLocation TransformLoc = StartLoc;
15684 SourceLocation TransformLocBegin = StartLoc;
15685 SourceLocation TransformLocEnd = EndLoc;
15686
15687 // Internal variable names.
15688 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15689 SmallString<64> ForwardIVName(".forward.iv.");
15690 ForwardIVName += OrigVarName;
15691 SmallString<64> ReversedIVName(".reversed.iv.");
15692 ReversedIVName += OrigVarName;
15693
15694 // LoopHelper.Updates will read the logical iteration number from
15695 // LoopHelper.IterationVarRef, compute the value of the user loop counter of
15696 // that logical iteration from it, then assign it to the user loop counter
15697 // variable. We cannot directly use LoopHelper.IterationVarRef as the
15698 // induction variable of the generated loop because it may cause an underflow:
15699 // \code{.c}
15700 // for (unsigned i = 0; i < n; ++i)
15701 // body(i);
15702 // \endcode
15703 //
15704 // Naive reversal:
15705 // \code{.c}
15706 // for (unsigned i = n-1; i >= 0; --i)
15707 // body(i);
15708 // \endcode
15709 //
15710 // Instead, we introduce a new iteration variable representing the logical
15711 // iteration counter of the original loop, convert it to the logical iteration
15712 // number of the reversed loop, then let LoopHelper.Updates compute the user's
15713 // loop iteration variable from it.
15714 // \code{.cpp}
15715 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
15716 // auto .reversed.iv = n - .forward.iv - 1;
15717 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates
15718 // body(i); // Body
15719 // }
15720 // \endcode
15721
15722 // Subexpressions with more than one use. One of the constraints of an AST is
15723 // that every node object must appear at most once, hence we define a lambda
15724 // that creates a new AST node at every use.
15725 CaptureVars CopyTransformer(SemaRef);
15726 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15727 return AssertSuccess(
15728 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15729 };
15730
15731 // Create the iteration variable for the forward loop (from 0 to n-1).
15732 VarDecl *ForwardIVDecl =
15733 buildVarDecl(SemaRef, {}, IVTy, ForwardIVName, nullptr, OrigVar);
15734 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
15735 OrigVarLoc]() {
15736 return buildDeclRefExpr(SemaRef, ForwardIVDecl, IVTy, OrigVarLoc);
15737 };
15738
15739 // Iteration variable for the reversed induction variable (from n-1 downto 0):
15740 // Reuse the iteration variable created by checkOpenMPLoop.
15741 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15742 ReversedIVDecl->setDeclName(
15743 &SemaRef.PP.getIdentifierTable().get(ReversedIVName));
15744
15745 // For init-statement:
15746 // \code{.cpp}
15747 // auto .forward.iv = 0;
15748 // \endcode
15749 auto *Zero = IntegerLiteral::Create(Context, llvm::APInt::getZero(IVWidth),
15750 ForwardIVDecl->getType(), OrigVarLoc);
15751 SemaRef.AddInitializerToDecl(ForwardIVDecl, Zero, /*DirectInit=*/false);
15752 StmtResult Init = new (Context)
15753 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15754 if (!Init.isUsable())
15755 return StmtError();
15756
15757 // Forward iv cond-expression:
15758 // \code{.cpp}
15759 // .forward.iv < MakeNumIterations()
15760 // \endcode
15762 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15763 MakeForwardRef(), MakeNumIterations());
15764 if (!Cond.isUsable())
15765 return StmtError();
15766
15767 // Forward incr-statement:
15768 // \code{.c}
15769 // ++.forward.iv
15770 // \endcode
15771 ExprResult Incr = SemaRef.BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
15772 UO_PreInc, MakeForwardRef());
15773 if (!Incr.isUsable())
15774 return StmtError();
15775
15776 // Reverse the forward-iv:
15777 // \code{.cpp}
15778 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
15779 // \endcode
15780 auto *One = IntegerLiteral::Create(Context, llvm::APInt(IVWidth, 1), IVTy,
15781 TransformLoc);
15782 ExprResult Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub,
15783 MakeNumIterations(), One);
15784 if (!Minus.isUsable())
15785 return StmtError();
15786 Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.get(),
15787 MakeForwardRef());
15788 if (!Minus.isUsable())
15789 return StmtError();
15790 StmtResult InitReversed = new (Context) DeclStmt(
15791 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
15792 if (!InitReversed.isUsable())
15793 return StmtError();
15794 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.get(),
15795 /*DirectInit=*/false);
15796
15797 // The new loop body.
15798 SmallVector<Stmt *, 4> BodyStmts;
15799 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
15800 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
15801 BodyStmts.push_back(InitReversed.get());
15802 llvm::append_range(BodyStmts, LoopHelper.Updates);
15803 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15804 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15805 BodyStmts.push_back(Body);
15806 auto *ReversedBody =
15807 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
15808 Body->getBeginLoc(), Body->getEndLoc());
15809
15810 // Finally create the reversed For-statement.
15811 auto *ReversedFor = new (Context)
15812 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
15813 ReversedBody, LoopHelper.Init->getBeginLoc(),
15814 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15815 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt, NumLoops,
15816 ReversedFor,
15817 buildPreInits(Context, PreInits));
15818}
15819
15821 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15822 SourceLocation EndLoc) {
15823 ASTContext &Context = getASTContext();
15824 DeclContext *CurContext = SemaRef.CurContext;
15825 Scope *CurScope = SemaRef.getCurScope();
15826
15827 // Empty statement should only be possible if there already was an error.
15828 if (!AStmt)
15829 return StmtError();
15830
15831 // interchange without permutation clause swaps two loops.
15832 const OMPPermutationClause *PermutationClause =
15833 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
15834 size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2;
15835
15836 // Verify and diagnose loop nest.
15838 Stmt *Body = nullptr;
15839 SmallVector<SmallVector<Stmt *>, 2> OriginalInits;
15840 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
15841 LoopHelpers, Body, OriginalInits))
15842 return StmtError();
15843
15844 // Delay interchange to when template is completely instantiated.
15845 if (CurContext->isDependentContext())
15846 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15847 NumLoops, AStmt, nullptr, nullptr);
15848
15849 // An invalid expression in the permutation clause is set to nullptr in
15850 // ActOnOpenMPPermutationClause.
15851 if (PermutationClause &&
15852 llvm::is_contained(PermutationClause->getArgsRefs(), nullptr))
15853 return StmtError();
15854
15855 assert(LoopHelpers.size() == NumLoops &&
15856 "Expecting loop iteration space dimensionaly to match number of "
15857 "affected loops");
15858 assert(OriginalInits.size() == NumLoops &&
15859 "Expecting loop iteration space dimensionaly to match number of "
15860 "affected loops");
15861
15862 // Decode the permutation clause.
15863 SmallVector<uint64_t, 2> Permutation;
15864 if (!PermutationClause) {
15865 Permutation = {1, 0};
15866 } else {
15867 ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs();
15868 llvm::BitVector Flags(PermArgs.size());
15869 for (Expr *PermArg : PermArgs) {
15870 std::optional<llvm::APSInt> PermCstExpr =
15871 PermArg->getIntegerConstantExpr(Context);
15872 if (!PermCstExpr)
15873 continue;
15874 uint64_t PermInt = PermCstExpr->getZExtValue();
15875 assert(1 <= PermInt && PermInt <= NumLoops &&
15876 "Must be a permutation; diagnostic emitted in "
15877 "ActOnOpenMPPermutationClause");
15878 if (Flags[PermInt - 1]) {
15879 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
15880 Diag(PermArg->getExprLoc(),
15881 diag::err_omp_interchange_permutation_value_repeated)
15882 << PermInt << ExprRange;
15883 continue;
15884 }
15885 Flags[PermInt - 1] = true;
15886
15887 Permutation.push_back(PermInt - 1);
15888 }
15889
15890 if (Permutation.size() != NumLoops)
15891 return StmtError();
15892 }
15893
15894 // Nothing to transform with trivial permutation.
15895 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](auto P) {
15896 auto [Idx, Arg] = P;
15897 return Idx == Arg;
15898 }))
15899 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15900 NumLoops, AStmt, AStmt, nullptr);
15901
15902 // Find the affected loops.
15903 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15904 collectLoopStmts(AStmt, LoopStmts);
15905
15906 // Collect pre-init statements on the order before the permuation.
15907 SmallVector<Stmt *> PreInits;
15908 for (auto I : llvm::seq<int>(NumLoops)) {
15909 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15910
15911 assert(LoopHelper.Counters.size() == 1 &&
15912 "Single-dimensional loop iteration space expected");
15913
15914 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
15915 PreInits);
15916 }
15917
15918 SmallVector<VarDecl *> PermutedIndVars(NumLoops);
15919 CaptureVars CopyTransformer(SemaRef);
15920
15921 // Create the permuted loops from the inside to the outside of the
15922 // interchanged loop nest. Body of the innermost new loop is the original
15923 // innermost body.
15924 Stmt *Inner = Body;
15925 for (auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
15926 // Get the original loop that belongs to this new position.
15927 uint64_t SourceIdx = Permutation[TargetIdx];
15928 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
15929 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15930 assert(SourceHelper.Counters.size() == 1 &&
15931 "Single-dimensional loop iteration space expected");
15932 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.Counters.front());
15933
15934 // Normalized loop counter variable: From 0 to n-1, always an integer type.
15935 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(SourceHelper.IterationVarRef);
15936 QualType IVTy = IterVarRef->getType();
15937 assert(IVTy->isIntegerType() &&
15938 "Expected the logical iteration counter to be an integer");
15939
15940 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15941 SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
15942
15943 // Make a copy of the NumIterations expression for each use: By the AST
15944 // constraints, every expression object in a DeclContext must be unique.
15945 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
15946 return AssertSuccess(
15947 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
15948 };
15949
15950 // Iteration variable for the permuted loop. Reuse the one from
15951 // checkOpenMPLoop which will also be used to update the original loop
15952 // variable.
15953 SmallString<64> PermutedCntName(".permuted_");
15954 PermutedCntName.append({llvm::utostr(TargetIdx), ".iv.", OrigVarName});
15955 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15956 PermutedCntDecl->setDeclName(
15957 &SemaRef.PP.getIdentifierTable().get(PermutedCntName));
15958 PermutedIndVars[TargetIdx] = PermutedCntDecl;
15959 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
15960 return buildDeclRefExpr(SemaRef, PermutedCntDecl, IVTy, OrigVarLoc);
15961 };
15962
15963 // For init-statement:
15964 // \code
15965 // auto .permuted_{target}.iv = 0
15966 // \endcode
15967 ExprResult Zero = SemaRef.ActOnIntegerConstant(OrigVarLoc, 0);
15968 if (!Zero.isUsable())
15969 return StmtError();
15970 SemaRef.AddInitializerToDecl(PermutedCntDecl, Zero.get(),
15971 /*DirectInit=*/false);
15972 StmtResult InitStmt = new (Context)
15973 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
15974 OrigCntVar->getEndLoc());
15975 if (!InitStmt.isUsable())
15976 return StmtError();
15977
15978 // For cond-expression:
15979 // \code
15980 // .permuted_{target}.iv < MakeNumIterations()
15981 // \endcode
15982 ExprResult CondExpr =
15983 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
15984 MakePermutedRef(), MakeNumIterations());
15985 if (!CondExpr.isUsable())
15986 return StmtError();
15987
15988 // For incr-statement:
15989 // \code
15990 // ++.tile.iv
15991 // \endcode
15992 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15993 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
15994 if (!IncrStmt.isUsable())
15995 return StmtError();
15996
15997 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
15998 SourceHelper.Updates.end());
15999 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
16000 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
16001 BodyParts.push_back(Inner);
16002 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
16003 Inner->getBeginLoc(), Inner->getEndLoc());
16004 Inner = new (Context) ForStmt(
16005 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
16006 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
16007 SourceHelper.Inc->getEndLoc());
16008 }
16009
16010 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
16011 NumLoops, AStmt, Inner,
16012 buildPreInits(Context, PreInits));
16013}
16014
16016 Stmt *AStmt,
16017 SourceLocation StartLoc,
16018 SourceLocation EndLoc) {
16019
16020 ASTContext &Context = getASTContext();
16021 DeclContext *CurrContext = SemaRef.CurContext;
16022 Scope *CurScope = SemaRef.getCurScope();
16023 CaptureVars CopyTransformer(SemaRef);
16024
16025 // Ensure the structured block is not empty
16026 if (!AStmt)
16027 return StmtError();
16028
16029 // Defer transformation in dependent contexts
16030 // The NumLoopNests argument is set to a placeholder 1 (even though
16031 // using looprange fuse could yield up to 3 top level loop nests)
16032 // because a dependent context could prevent determining its true value
16033 if (CurrContext->isDependentContext())
16034 return OMPFuseDirective::Create(Context, StartLoc, EndLoc, Clauses,
16035 /* NumLoops */ 1, AStmt, nullptr, nullptr);
16036
16037 // Validate that the potential loop sequence is transformable for fusion
16038 // Also collect the HelperExprs, Loop Stmts, Inits, and Number of loops
16039 LoopSequenceAnalysis SeqAnalysis;
16040 if (!checkTransformableLoopSequence(OMPD_fuse, AStmt, SeqAnalysis, Context))
16041 return StmtError();
16042
16043 // SeqAnalysis.LoopSeqSize exists mostly to handle dependent contexts,
16044 // otherwise it must be the same as SeqAnalysis.Loops.size().
16045 assert(SeqAnalysis.LoopSeqSize == SeqAnalysis.Loops.size() &&
16046 "Inconsistent size of the loop sequence and the number of loops "
16047 "found in the sequence");
16048
16049 // Handle clauses, which can be any of the following: [looprange, apply]
16050 const auto *LRC =
16051 OMPExecutableDirective::getSingleClause<OMPLoopRangeClause>(Clauses);
16052
16053 // The clause arguments are invalidated if any error arises
16054 // such as non-constant or non-positive arguments
16055 if (LRC && (!LRC->getFirst() || !LRC->getCount()))
16056 return StmtError();
16057
16058 // Delayed semantic check of LoopRange constraint
16059 // Evaluates the loop range arguments and returns the first and count values
16060 auto EvaluateLoopRangeArguments = [&Context](Expr *First, Expr *Count,
16061 uint64_t &FirstVal,
16062 uint64_t &CountVal) {
16063 llvm::APSInt FirstInt = First->EvaluateKnownConstInt(Context);
16064 llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Context);
16065 FirstVal = FirstInt.getZExtValue();
16066 CountVal = CountInt.getZExtValue();
16067 };
16068
16069 // OpenMP [6.0, Restrictions]
16070 // first + count - 1 must not evaluate to a value greater than the
16071 // loop sequence length of the associated canonical loop sequence.
16072 auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal,
16073 unsigned NumLoops) -> bool {
16074 return FirstVal + CountVal - 1 <= NumLoops;
16075 };
16076 uint64_t FirstVal = 1, CountVal = 0, LastVal = SeqAnalysis.LoopSeqSize;
16077
16078 // Validates the loop range after evaluating the semantic information
16079 // and ensures that the range is valid for the given loop sequence size.
16080 // Expressions are evaluated at compile time to obtain constant values.
16081 if (LRC) {
16082 EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal,
16083 CountVal);
16084 if (CountVal == 1)
16085 SemaRef.Diag(LRC->getCountLoc(), diag::warn_omp_redundant_fusion)
16086 << getOpenMPDirectiveName(OMPD_fuse);
16087
16088 if (!ValidLoopRange(FirstVal, CountVal, SeqAnalysis.LoopSeqSize)) {
16089 SemaRef.Diag(LRC->getFirstLoc(), diag::err_omp_invalid_looprange)
16090 << getOpenMPDirectiveName(OMPD_fuse) << FirstVal
16091 << (FirstVal + CountVal - 1) << SeqAnalysis.LoopSeqSize;
16092 return StmtError();
16093 }
16094
16095 LastVal = FirstVal + CountVal - 1;
16096 }
16097
16098 // Complete fusion generates a single canonical loop nest
16099 // However looprange clause may generate several loop nests
16100 unsigned NumGeneratedTopLevelLoops =
16101 LRC ? SeqAnalysis.LoopSeqSize - CountVal + 1 : 1;
16102
16103 // Emit a warning for redundant loop fusion when the sequence contains only
16104 // one loop.
16105 if (SeqAnalysis.LoopSeqSize == 1)
16106 SemaRef.Diag(AStmt->getBeginLoc(), diag::warn_omp_redundant_fusion)
16107 << getOpenMPDirectiveName(OMPD_fuse);
16108
16109 // Select the type with the largest bit width among all induction variables
16110 QualType IVType =
16111 SeqAnalysis.Loops[FirstVal - 1].HelperExprs.IterationVarRef->getType();
16112 for (unsigned I : llvm::seq<unsigned>(FirstVal, LastVal)) {
16113 QualType CurrentIVType =
16114 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef->getType();
16115 if (Context.getTypeSize(CurrentIVType) > Context.getTypeSize(IVType)) {
16116 IVType = CurrentIVType;
16117 }
16118 }
16119 uint64_t IVBitWidth = Context.getIntWidth(IVType);
16120
16121 // Create pre-init declarations for all loops lower bounds, upper bounds,
16122 // strides and num-iterations for every top level loop in the fusion
16123 SmallVector<VarDecl *, 4> LBVarDecls;
16124 SmallVector<VarDecl *, 4> STVarDecls;
16125 SmallVector<VarDecl *, 4> NIVarDecls;
16126 SmallVector<VarDecl *, 4> UBVarDecls;
16127 SmallVector<VarDecl *, 4> IVVarDecls;
16128
16129 // Helper lambda to create variables for bounds, strides, and other
16130 // expressions. Generates both the variable declaration and the corresponding
16131 // initialization statement.
16132 auto CreateHelperVarAndStmt =
16133 [&, &SemaRef = SemaRef](Expr *ExprToCopy, const std::string &BaseName,
16134 unsigned I, bool NeedsNewVD = false) {
16135 Expr *TransformedExpr =
16136 AssertSuccess(CopyTransformer.TransformExpr(ExprToCopy));
16137 if (!TransformedExpr)
16138 return std::pair<VarDecl *, StmtResult>(nullptr, StmtError());
16139
16140 auto Name = (Twine(".omp.") + BaseName + std::to_string(I)).str();
16141
16142 VarDecl *VD;
16143 if (NeedsNewVD) {
16144 VD = buildVarDecl(SemaRef, SourceLocation(), IVType, Name);
16145 SemaRef.AddInitializerToDecl(VD, TransformedExpr, false);
16146 } else {
16147 // Create a unique variable name
16148 DeclRefExpr *DRE = cast<DeclRefExpr>(TransformedExpr);
16149 VD = cast<VarDecl>(DRE->getDecl());
16150 VD->setDeclName(&SemaRef.PP.getIdentifierTable().get(Name));
16151 }
16152 // Create the corresponding declaration statement
16153 StmtResult DeclStmt = new (Context) class DeclStmt(
16155 return std::make_pair(VD, DeclStmt);
16156 };
16157
16158 // PreInits hold a sequence of variable declarations that must be executed
16159 // before the fused loop begins. These include bounds, strides, and other
16160 // helper variables required for the transformation. Other loop transforms
16161 // also contain their own preinits
16162 SmallVector<Stmt *> PreInits;
16163
16164 // Update the general preinits using the preinits generated by loop sequence
16165 // generating loop transformations. These preinits differ slightly from
16166 // single-loop transformation preinits, as they can be detached from a
16167 // specific loop inside multiple generated loop nests. This happens
16168 // because certain helper variables, like '.omp.fuse.max', are introduced to
16169 // handle fused iteration spaces and may not be directly tied to a single
16170 // original loop. The preinit structure must ensure that hidden variables
16171 // like '.omp.fuse.max' are still properly handled.
16172 // Transformations that apply this concept: Loopranged Fuse, Split
16173 llvm::append_range(PreInits, SeqAnalysis.LoopSequencePreInits);
16174
16175 // Process each single loop to generate and collect declarations
16176 // and statements for all helper expressions related to
16177 // particular single loop nests
16178
16179 // Also In the case of the fused loops, we keep track of their original
16180 // inits by appending them to their preinits statement, and in the case of
16181 // transformations, also append their preinits (which contain the original
16182 // loop initialization statement or other statements)
16183
16184 // Firstly we need to set TransformIndex to match the begining of the
16185 // looprange section
16186 unsigned int TransformIndex = 0;
16187 for (unsigned I : llvm::seq<unsigned>(FirstVal - 1)) {
16188 if (SeqAnalysis.Loops[I].isLoopTransformation())
16189 ++TransformIndex;
16190 }
16191
16192 for (unsigned int I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16193 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16194 addLoopPreInits(Context, SeqAnalysis.Loops[I].HelperExprs,
16195 SeqAnalysis.Loops[I].TheForStmt,
16196 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16197 } else if (SeqAnalysis.Loops[I].isLoopTransformation()) {
16198 // For transformed loops, insert both pre-inits and original inits.
16199 // Order matters: pre-inits may define variables used in the original
16200 // inits such as upper bounds...
16201 SmallVector<Stmt *> &TransformPreInit =
16202 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16203 llvm::append_range(PreInits, TransformPreInit);
16204
16205 addLoopPreInits(Context, SeqAnalysis.Loops[I].HelperExprs,
16206 SeqAnalysis.Loops[I].TheForStmt,
16207 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16208 }
16209 auto [UBVD, UBDStmt] =
16210 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.UB, "ub", J);
16211 auto [LBVD, LBDStmt] =
16212 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.LB, "lb", J);
16213 auto [STVD, STDStmt] =
16214 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.ST, "st", J);
16215 auto [NIVD, NIDStmt] = CreateHelperVarAndStmt(
16216 SeqAnalysis.Loops[I].HelperExprs.NumIterations, "ni", J, true);
16217 auto [IVVD, IVDStmt] = CreateHelperVarAndStmt(
16218 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef, "iv", J);
16219
16220 assert(LBVD && STVD && NIVD && IVVD &&
16221 "OpenMP Fuse Helper variables creation failed");
16222
16223 UBVarDecls.push_back(UBVD);
16224 LBVarDecls.push_back(LBVD);
16225 STVarDecls.push_back(STVD);
16226 NIVarDecls.push_back(NIVD);
16227 IVVarDecls.push_back(IVVD);
16228
16229 PreInits.push_back(LBDStmt.get());
16230 PreInits.push_back(STDStmt.get());
16231 PreInits.push_back(NIDStmt.get());
16232 PreInits.push_back(IVDStmt.get());
16233 }
16234
16235 auto MakeVarDeclRef = [&SemaRef = this->SemaRef](VarDecl *VD) {
16236 return buildDeclRefExpr(SemaRef, VD, VD->getType(), VD->getLocation(),
16237 false);
16238 };
16239
16240 // Following up the creation of the final fused loop will be performed
16241 // which has the following shape (considering the selected loops):
16242 //
16243 // for (fuse.index = 0; fuse.index < max(ni0, ni1..., nik); ++fuse.index) {
16244 // if (fuse.index < ni0){
16245 // iv0 = lb0 + st0 * fuse.index;
16246 // original.index0 = iv0
16247 // body(0);
16248 // }
16249 // if (fuse.index < ni1){
16250 // iv1 = lb1 + st1 * fuse.index;
16251 // original.index1 = iv1
16252 // body(1);
16253 // }
16254 //
16255 // ...
16256 //
16257 // if (fuse.index < nik){
16258 // ivk = lbk + stk * fuse.index;
16259 // original.indexk = ivk
16260 // body(k); Expr *InitVal = IntegerLiteral::Create(Context,
16261 // llvm::APInt(IVWidth, 0),
16262 // }
16263
16264 // 1. Create the initialized fuse index
16265 StringRef IndexName = ".omp.fuse.index";
16266 Expr *InitVal = IntegerLiteral::Create(Context, llvm::APInt(IVBitWidth, 0),
16267 IVType, SourceLocation());
16268 VarDecl *IndexDecl =
16269 buildVarDecl(SemaRef, {}, IVType, IndexName, nullptr, nullptr);
16270 SemaRef.AddInitializerToDecl(IndexDecl, InitVal, false);
16271 StmtResult InitStmt = new (Context)
16273
16274 if (!InitStmt.isUsable())
16275 return StmtError();
16276
16277 auto MakeIVRef = [&SemaRef = this->SemaRef, IndexDecl, IVType,
16278 Loc = InitVal->getExprLoc()]() {
16279 return buildDeclRefExpr(SemaRef, IndexDecl, IVType, Loc, false);
16280 };
16281
16282 // 2. Iteratively compute the max number of logical iterations Max(NI_1, NI_2,
16283 // ..., NI_k)
16284 //
16285 // This loop accumulates the maximum value across multiple expressions,
16286 // ensuring each step constructs a unique AST node for correctness. By using
16287 // intermediate temporary variables and conditional operators, we maintain
16288 // distinct nodes and avoid duplicating subtrees, For instance, max(a,b,c):
16289 // omp.temp0 = max(a, b)
16290 // omp.temp1 = max(omp.temp0, c)
16291 // omp.fuse.max = max(omp.temp1, omp.temp0)
16292
16293 ExprResult MaxExpr;
16294 // I is the range of loops in the sequence that we fuse.
16295 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16296 DeclRefExpr *NIRef = MakeVarDeclRef(NIVarDecls[J]);
16297 QualType NITy = NIRef->getType();
16298
16299 if (MaxExpr.isUnset()) {
16300 // Initialize MaxExpr with the first NI expression
16301 MaxExpr = NIRef;
16302 } else {
16303 // Create a new acummulator variable t_i = MaxExpr
16304 std::string TempName = (Twine(".omp.temp.") + Twine(J)).str();
16305 VarDecl *TempDecl =
16306 buildVarDecl(SemaRef, {}, NITy, TempName, nullptr, nullptr);
16307 TempDecl->setInit(MaxExpr.get());
16308 DeclRefExpr *TempRef =
16309 buildDeclRefExpr(SemaRef, TempDecl, NITy, SourceLocation(), false);
16310 DeclRefExpr *TempRef2 =
16311 buildDeclRefExpr(SemaRef, TempDecl, NITy, SourceLocation(), false);
16312 // Add a DeclStmt to PreInits to ensure the variable is declared.
16313 StmtResult TempStmt = new (Context)
16315
16316 if (!TempStmt.isUsable())
16317 return StmtError();
16318 PreInits.push_back(TempStmt.get());
16319
16320 // Build MaxExpr <-(MaxExpr > NIRef ? MaxExpr : NIRef)
16322 SemaRef.BuildBinOp(nullptr, SourceLocation(), BO_GT, TempRef, NIRef);
16323 // Handle any errors in Comparison creation
16324 if (!Comparison.isUsable())
16325 return StmtError();
16326
16327 DeclRefExpr *NIRef2 = MakeVarDeclRef(NIVarDecls[J]);
16328 // Update MaxExpr using a conditional expression to hold the max value
16329 MaxExpr = new (Context) ConditionalOperator(
16330 Comparison.get(), SourceLocation(), TempRef2, SourceLocation(),
16331 NIRef2->getExprStmt(), NITy, VK_LValue, OK_Ordinary);
16332
16333 if (!MaxExpr.isUsable())
16334 return StmtError();
16335 }
16336 }
16337 if (!MaxExpr.isUsable())
16338 return StmtError();
16339
16340 // 3. Declare the max variable
16341 const std::string MaxName = Twine(".omp.fuse.max").str();
16342 VarDecl *MaxDecl =
16343 buildVarDecl(SemaRef, {}, IVType, MaxName, nullptr, nullptr);
16344 MaxDecl->setInit(MaxExpr.get());
16345 DeclRefExpr *MaxRef = buildDeclRefExpr(SemaRef, MaxDecl, IVType, {}, false);
16346 StmtResult MaxStmt = new (Context)
16348
16349 if (MaxStmt.isInvalid())
16350 return StmtError();
16351 PreInits.push_back(MaxStmt.get());
16352
16353 // 4. Create condition Expr: index < n_max
16354 ExprResult CondExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_LT,
16355 MakeIVRef(), MaxRef);
16356 if (!CondExpr.isUsable())
16357 return StmtError();
16358
16359 // 5. Increment Expr: ++index
16360 ExprResult IncrExpr =
16361 SemaRef.BuildUnaryOp(CurScope, SourceLocation(), UO_PreInc, MakeIVRef());
16362 if (!IncrExpr.isUsable())
16363 return StmtError();
16364
16365 // 6. Build the Fused Loop Body
16366 // The final fused loop iterates over the maximum logical range. Inside the
16367 // loop, each original loop's index is calculated dynamically, and its body
16368 // is executed conditionally.
16369 //
16370 // Each sub-loop's body is guarded by a conditional statement to ensure
16371 // it executes only within its logical iteration range:
16372 //
16373 // if (fuse.index < ni_k){
16374 // iv_k = lb_k + st_k * fuse.index;
16375 // original.index = iv_k
16376 // body(k);
16377 // }
16378
16379 CompoundStmt *FusedBody = nullptr;
16380 SmallVector<Stmt *, 4> FusedBodyStmts;
16381 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16382 // Assingment of the original sub-loop index to compute the logical index
16383 // IV_k = LB_k + omp.fuse.index * ST_k
16384 ExprResult IdxExpr =
16385 SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Mul,
16386 MakeVarDeclRef(STVarDecls[J]), MakeIVRef());
16387 if (!IdxExpr.isUsable())
16388 return StmtError();
16389 IdxExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Add,
16390 MakeVarDeclRef(LBVarDecls[J]), IdxExpr.get());
16391
16392 if (!IdxExpr.isUsable())
16393 return StmtError();
16394 IdxExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Assign,
16395 MakeVarDeclRef(IVVarDecls[J]), IdxExpr.get());
16396 if (!IdxExpr.isUsable())
16397 return StmtError();
16398
16399 // Update the original i_k = IV_k
16400 SmallVector<Stmt *, 4> BodyStmts;
16401 BodyStmts.push_back(IdxExpr.get());
16402 llvm::append_range(BodyStmts, SeqAnalysis.Loops[I].HelperExprs.Updates);
16403
16404 // If the loop is a CXXForRangeStmt then the iterator variable is needed
16405 if (auto *SourceCXXFor =
16406 dyn_cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt))
16407 BodyStmts.push_back(SourceCXXFor->getLoopVarStmt());
16408
16409 Stmt *Body =
16410 (isa<ForStmt>(SeqAnalysis.Loops[I].TheForStmt))
16411 ? cast<ForStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody()
16412 : cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody();
16413 BodyStmts.push_back(Body);
16414
16415 CompoundStmt *CombinedBody =
16416 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
16419 SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_LT, MakeIVRef(),
16420 MakeVarDeclRef(NIVarDecls[J]));
16421
16422 if (!Condition.isUsable())
16423 return StmtError();
16424
16425 IfStmt *IfStatement = IfStmt::Create(
16426 Context, SourceLocation(), IfStatementKind::Ordinary, nullptr, nullptr,
16427 Condition.get(), SourceLocation(), SourceLocation(), CombinedBody,
16428 SourceLocation(), nullptr);
16429
16430 FusedBodyStmts.push_back(IfStatement);
16431 }
16432 FusedBody = CompoundStmt::Create(Context, FusedBodyStmts, FPOptionsOverride(),
16434
16435 // 7. Construct the final fused loop
16436 ForStmt *FusedForStmt = new (Context)
16437 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr, IncrExpr.get(),
16438 FusedBody, InitStmt.get()->getBeginLoc(), SourceLocation(),
16439 IncrExpr.get()->getEndLoc());
16440
16441 // In the case of looprange, the result of fuse won't simply
16442 // be a single loop (ForStmt), but rather a loop sequence
16443 // (CompoundStmt) of 3 parts: the pre-fusion loops, the fused loop
16444 // and the post-fusion loops, preserving its original order.
16445 //
16446 // Note: If looprange clause produces a single fused loop nest then
16447 // this compound statement wrapper is unnecessary (Therefore this
16448 // treatment is skipped)
16449
16450 Stmt *FusionStmt = FusedForStmt;
16451 if (LRC && CountVal != SeqAnalysis.LoopSeqSize) {
16452 SmallVector<Stmt *, 4> FinalLoops;
16453
16454 // Reset the transform index
16455 TransformIndex = 0;
16456
16457 // Collect all non-fused loops before and after the fused region.
16458 // Pre-fusion and post-fusion loops are inserted in order exploiting their
16459 // symmetry, along with their corresponding transformation pre-inits if
16460 // needed. The fused loop is added between the two regions.
16461 for (unsigned I : llvm::seq<unsigned>(SeqAnalysis.LoopSeqSize)) {
16462 if (I >= FirstVal - 1 && I < FirstVal + CountVal - 1) {
16463 // Update the Transformation counter to skip already treated
16464 // loop transformations
16465 if (!SeqAnalysis.Loops[I].isLoopTransformation())
16466 ++TransformIndex;
16467 continue;
16468 }
16469
16470 // No need to handle:
16471 // Regular loops: they are kept intact as-is.
16472 // Loop-sequence-generating transformations: already handled earlier.
16473 // Only TransformSingleLoop requires inserting pre-inits here
16474 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16475 const auto &TransformPreInit =
16476 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16477 if (!TransformPreInit.empty())
16478 llvm::append_range(PreInits, TransformPreInit);
16479 }
16480
16481 FinalLoops.push_back(SeqAnalysis.Loops[I].TheForStmt);
16482 }
16483
16484 FinalLoops.insert(FinalLoops.begin() + (FirstVal - 1), FusedForStmt);
16485 FusionStmt = CompoundStmt::Create(Context, FinalLoops, FPOptionsOverride(),
16487 }
16488 return OMPFuseDirective::Create(Context, StartLoc, EndLoc, Clauses,
16489 NumGeneratedTopLevelLoops, AStmt, FusionStmt,
16490 buildPreInits(Context, PreInits));
16491}
16492
16494 Expr *Expr,
16495 SourceLocation StartLoc,
16496 SourceLocation LParenLoc,
16497 SourceLocation EndLoc) {
16498 OMPClause *Res = nullptr;
16499 switch (Kind) {
16500 case OMPC_final:
16501 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
16502 break;
16503 case OMPC_safelen:
16504 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
16505 break;
16506 case OMPC_simdlen:
16507 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
16508 break;
16509 case OMPC_allocator:
16510 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
16511 break;
16512 case OMPC_collapse:
16513 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
16514 break;
16515 case OMPC_ordered:
16516 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
16517 break;
16518 case OMPC_nowait:
16519 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc, LParenLoc, Expr);
16520 break;
16521 case OMPC_priority:
16522 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
16523 break;
16524 case OMPC_hint:
16525 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
16526 break;
16527 case OMPC_depobj:
16528 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
16529 break;
16530 case OMPC_detach:
16531 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
16532 break;
16533 case OMPC_novariants:
16534 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
16535 break;
16536 case OMPC_nocontext:
16537 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
16538 break;
16539 case OMPC_filter:
16540 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
16541 break;
16542 case OMPC_partial:
16543 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
16544 break;
16545 case OMPC_message:
16546 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
16547 break;
16548 case OMPC_align:
16549 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
16550 break;
16551 case OMPC_ompx_dyn_cgroup_mem:
16552 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
16553 break;
16554 case OMPC_holds:
16555 Res = ActOnOpenMPHoldsClause(Expr, StartLoc, LParenLoc, EndLoc);
16556 break;
16557 case OMPC_transparent:
16558 Res = ActOnOpenMPTransparentClause(Expr, StartLoc, LParenLoc, EndLoc);
16559 break;
16560 case OMPC_dyn_groupprivate:
16561 case OMPC_grainsize:
16562 case OMPC_num_tasks:
16563 case OMPC_num_threads:
16564 case OMPC_device:
16565 case OMPC_if:
16566 case OMPC_default:
16567 case OMPC_proc_bind:
16568 case OMPC_schedule:
16569 case OMPC_private:
16570 case OMPC_firstprivate:
16571 case OMPC_lastprivate:
16572 case OMPC_shared:
16573 case OMPC_reduction:
16574 case OMPC_task_reduction:
16575 case OMPC_in_reduction:
16576 case OMPC_linear:
16577 case OMPC_aligned:
16578 case OMPC_copyin:
16579 case OMPC_copyprivate:
16580 case OMPC_untied:
16581 case OMPC_mergeable:
16582 case OMPC_threadprivate:
16583 case OMPC_groupprivate:
16584 case OMPC_sizes:
16585 case OMPC_allocate:
16586 case OMPC_flush:
16587 case OMPC_read:
16588 case OMPC_write:
16589 case OMPC_update:
16590 case OMPC_capture:
16591 case OMPC_compare:
16592 case OMPC_seq_cst:
16593 case OMPC_acq_rel:
16594 case OMPC_acquire:
16595 case OMPC_release:
16596 case OMPC_relaxed:
16597 case OMPC_depend:
16598 case OMPC_threads:
16599 case OMPC_simd:
16600 case OMPC_map:
16601 case OMPC_nogroup:
16602 case OMPC_dist_schedule:
16603 case OMPC_defaultmap:
16604 case OMPC_unknown:
16605 case OMPC_uniform:
16606 case OMPC_to:
16607 case OMPC_from:
16608 case OMPC_use_device_ptr:
16609 case OMPC_use_device_addr:
16610 case OMPC_is_device_ptr:
16611 case OMPC_unified_address:
16612 case OMPC_unified_shared_memory:
16613 case OMPC_reverse_offload:
16614 case OMPC_dynamic_allocators:
16615 case OMPC_atomic_default_mem_order:
16616 case OMPC_self_maps:
16617 case OMPC_device_type:
16618 case OMPC_match:
16619 case OMPC_nontemporal:
16620 case OMPC_order:
16621 case OMPC_at:
16622 case OMPC_severity:
16623 case OMPC_destroy:
16624 case OMPC_inclusive:
16625 case OMPC_exclusive:
16626 case OMPC_uses_allocators:
16627 case OMPC_affinity:
16628 case OMPC_when:
16629 case OMPC_bind:
16630 case OMPC_num_teams:
16631 case OMPC_thread_limit:
16632 default:
16633 llvm_unreachable("Clause is not allowed.");
16634 }
16635 return Res;
16636}
16637
16638// An OpenMP directive such as 'target parallel' has two captured regions:
16639// for the 'target' and 'parallel' respectively. This function returns
16640// the region in which to capture expressions associated with a clause.
16641// A return value of OMPD_unknown signifies that the expression should not
16642// be captured.
16644 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
16645 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
16646 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
16647 "Invalid directive with CKind-clause");
16648
16649 // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
16650 if (NameModifier != OMPD_unknown &&
16651 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
16652 return OMPD_unknown;
16653
16654 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(DKind);
16655
16656 // [5.2:341:24-30]
16657 // If the clauses have expressions on them, such as for various clauses where
16658 // the argument of the clause is an expression, or lower-bound, length, or
16659 // stride expressions inside array sections (or subscript and stride
16660 // expressions in subscript-triplet for Fortran), or linear-step or alignment
16661 // expressions, the expressions are evaluated immediately before the construct
16662 // to which the clause has been split or duplicated per the above rules
16663 // (therefore inside of the outer leaf constructs). However, the expressions
16664 // inside the num_teams and thread_limit clauses are always evaluated before
16665 // the outermost leaf construct.
16666
16667 // Process special cases first.
16668 switch (CKind) {
16669 case OMPC_if:
16670 switch (DKind) {
16671 case OMPD_teams_loop:
16672 case OMPD_target_teams_loop:
16673 // For [target] teams loop, assume capture region is 'teams' so it's
16674 // available for codegen later to use if/when necessary.
16675 return OMPD_teams;
16676 case OMPD_target_update:
16677 case OMPD_target_enter_data:
16678 case OMPD_target_exit_data:
16679 return OMPD_task;
16680 default:
16681 break;
16682 }
16683 break;
16684 case OMPC_num_teams:
16685 case OMPC_thread_limit:
16686 case OMPC_ompx_dyn_cgroup_mem:
16687 case OMPC_dyn_groupprivate:
16688 // TODO: This may need to consider teams too.
16689 if (Leafs[0] == OMPD_target)
16690 return OMPD_target;
16691 break;
16692 case OMPC_device:
16693 if (Leafs[0] == OMPD_target ||
16694 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
16695 OMPD_target_enter_data, OMPD_target_exit_data},
16696 DKind))
16697 return OMPD_task;
16698 break;
16699 case OMPC_novariants:
16700 case OMPC_nocontext:
16701 if (DKind == OMPD_dispatch)
16702 return OMPD_task;
16703 break;
16704 case OMPC_when:
16705 if (DKind == OMPD_metadirective)
16706 return OMPD_metadirective;
16707 break;
16708 case OMPC_filter:
16709 return OMPD_unknown;
16710 default:
16711 break;
16712 }
16713
16714 // If none of the special cases above applied, and DKind is a capturing
16715 // directive, find the innermost enclosing leaf construct that allows the
16716 // clause, and returns the corresponding capture region.
16717
16718 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
16719 // Find the index in "Leafs" of the last leaf that allows the given
16720 // clause. The search will only include indexes [0, EndIdx).
16721 // EndIdx may be set to the index of the NameModifier, if present.
16722 int InnermostIdx = [&]() {
16723 for (int I = EndIdx - 1; I >= 0; --I) {
16724 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
16725 return I;
16726 }
16727 return -1;
16728 }();
16729
16730 // Find the nearest enclosing capture region.
16732 for (int I = InnermostIdx - 1; I >= 0; --I) {
16733 if (!isOpenMPCapturingDirective(Leafs[I]))
16734 continue;
16735 Regions.clear();
16736 getOpenMPCaptureRegions(Regions, Leafs[I]);
16737 if (Regions[0] != OMPD_unknown)
16738 return Regions.back();
16739 }
16740 return OMPD_unknown;
16741 };
16742
16743 if (isOpenMPCapturingDirective(DKind)) {
16744 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
16745 for (int I = 0, E = Leafs.size(); I != E; ++I) {
16746 if (Leafs[I] == Dir)
16747 return I + 1;
16748 }
16749 return 0;
16750 };
16751
16752 int End = NameModifier == OMPD_unknown ? Leafs.size()
16753 : GetLeafIndex(NameModifier);
16754 return GetEnclosingRegion(End, CKind);
16755 }
16756
16757 return OMPD_unknown;
16758}
16759
16761 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
16762 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
16763 SourceLocation ColonLoc, SourceLocation EndLoc) {
16764 Expr *ValExpr = Condition;
16765 Stmt *HelperValStmt = nullptr;
16766 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16767 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16768 !Condition->isInstantiationDependent() &&
16769 !Condition->containsUnexpandedParameterPack()) {
16770 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
16771 if (Val.isInvalid())
16772 return nullptr;
16773
16774 ValExpr = Val.get();
16775
16776 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16777 CaptureRegion = getOpenMPCaptureRegionForClause(
16778 DKind, OMPC_if, getLangOpts().OpenMP, NameModifier);
16779 if (CaptureRegion != OMPD_unknown &&
16780 !SemaRef.CurContext->isDependentContext()) {
16781 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16782 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16783 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16784 HelperValStmt = buildPreInits(getASTContext(), Captures);
16785 }
16786 }
16787
16788 return new (getASTContext())
16789 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16790 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16791}
16792
16794 SourceLocation StartLoc,
16795 SourceLocation LParenLoc,
16796 SourceLocation EndLoc) {
16797 Expr *ValExpr = Condition;
16798 Stmt *HelperValStmt = nullptr;
16799 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16800 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16801 !Condition->isInstantiationDependent() &&
16802 !Condition->containsUnexpandedParameterPack()) {
16803 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
16804 if (Val.isInvalid())
16805 return nullptr;
16806
16807 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
16808
16809 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16810 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final,
16811 getLangOpts().OpenMP);
16812 if (CaptureRegion != OMPD_unknown &&
16813 !SemaRef.CurContext->isDependentContext()) {
16814 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16815 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16816 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16817 HelperValStmt = buildPreInits(getASTContext(), Captures);
16818 }
16819 }
16820
16821 return new (getASTContext()) OMPFinalClause(
16822 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16823}
16824
16827 Expr *Op) {
16828 if (!Op)
16829 return ExprError();
16830
16831 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
16832 public:
16833 IntConvertDiagnoser()
16834 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {}
16835 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
16836 QualType T) override {
16837 return S.Diag(Loc, diag::err_omp_not_integral) << T;
16838 }
16839 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
16840 QualType T) override {
16841 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
16842 }
16843 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
16844 QualType T,
16845 QualType ConvTy) override {
16846 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
16847 }
16848 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
16849 QualType ConvTy) override {
16850 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16851 << ConvTy->isEnumeralType() << ConvTy;
16852 }
16853 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
16854 QualType T) override {
16855 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
16856 }
16857 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
16858 QualType ConvTy) override {
16859 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16860 << ConvTy->isEnumeralType() << ConvTy;
16861 }
16862 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
16863 QualType) override {
16864 llvm_unreachable("conversion functions are permitted");
16865 }
16866 } ConvertDiagnoser;
16867 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16868}
16869
16870static bool
16872 bool StrictlyPositive, bool BuildCapture = false,
16873 OpenMPDirectiveKind DKind = OMPD_unknown,
16874 OpenMPDirectiveKind *CaptureRegion = nullptr,
16875 Stmt **HelperValStmt = nullptr) {
16876 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
16877 !ValExpr->isInstantiationDependent()) {
16878 SourceLocation Loc = ValExpr->getExprLoc();
16880 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
16881 if (Value.isInvalid())
16882 return false;
16883
16884 ValExpr = Value.get();
16885 // The expression must evaluate to a non-negative integer value.
16886 if (std::optional<llvm::APSInt> Result =
16887 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
16888 if (Result->isSigned() &&
16889 !((!StrictlyPositive && Result->isNonNegative()) ||
16890 (StrictlyPositive && Result->isStrictlyPositive()))) {
16891 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
16892 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
16893 << ValExpr->getSourceRange();
16894 return false;
16895 }
16896 }
16897 if (!BuildCapture)
16898 return true;
16899 *CaptureRegion =
16900 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
16901 if (*CaptureRegion != OMPD_unknown &&
16902 !SemaRef.CurContext->isDependentContext()) {
16903 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16904 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16905 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16906 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
16907 }
16908 }
16909 return true;
16910}
16911
16912static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First,
16913 unsigned Last,
16914 ArrayRef<unsigned> Exclude = {}) {
16915 SmallString<256> Buffer;
16916 llvm::raw_svector_ostream Out(Buffer);
16917 unsigned Skipped = Exclude.size();
16918 for (unsigned I = First; I < Last; ++I) {
16919 if (llvm::is_contained(Exclude, I)) {
16920 --Skipped;
16921 continue;
16922 }
16923 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
16924 if (I + Skipped + 2 == Last)
16925 Out << " or ";
16926 else if (I + Skipped + 1 != Last)
16927 Out << ", ";
16928 }
16929 return std::string(Out.str());
16930}
16931
16933 OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads,
16934 SourceLocation StartLoc, SourceLocation LParenLoc,
16935 SourceLocation ModifierLoc, SourceLocation EndLoc) {
16936 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 60) &&
16937 "Unexpected num_threads modifier in OpenMP < 60.");
16938
16939 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTHREADS_unknown) {
16940 std::string Values = getListOfPossibleValues(OMPC_num_threads, /*First=*/0,
16942 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
16943 << Values << getOpenMPClauseNameForDiag(OMPC_num_threads);
16944 return nullptr;
16945 }
16946
16947 Expr *ValExpr = NumThreads;
16948 Stmt *HelperValStmt = nullptr;
16949
16950 // OpenMP [2.5, Restrictions]
16951 // The num_threads expression must evaluate to a positive integer value.
16952 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads,
16953 /*StrictlyPositive=*/true))
16954 return nullptr;
16955
16956 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16958 DKind, OMPC_num_threads, getLangOpts().OpenMP);
16959 if (CaptureRegion != OMPD_unknown &&
16960 !SemaRef.CurContext->isDependentContext()) {
16961 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16962 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16963 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16964 HelperValStmt = buildPreInits(getASTContext(), Captures);
16965 }
16966
16967 return new (getASTContext())
16968 OMPNumThreadsClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
16969 StartLoc, LParenLoc, ModifierLoc, EndLoc);
16970}
16971
16973 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
16974 bool SuppressExprDiags) {
16975 if (!E)
16976 return ExprError();
16977 if (E->isValueDependent() || E->isTypeDependent() ||
16979 return E;
16980
16981 llvm::APSInt Result;
16982 ExprResult ICE;
16983 if (SuppressExprDiags) {
16984 // Use a custom diagnoser that suppresses 'note' diagnostics about the
16985 // expression.
16986 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
16987 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
16989 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
16990 llvm_unreachable("Diagnostic suppressed");
16991 }
16992 } Diagnoser;
16993 ICE = SemaRef.VerifyIntegerConstantExpression(E, &Result, Diagnoser,
16995 } else {
16996 ICE =
16997 SemaRef.VerifyIntegerConstantExpression(E, &Result,
16998 /*FIXME*/ AllowFoldKind::Allow);
16999 }
17000 if (ICE.isInvalid())
17001 return ExprError();
17002
17003 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
17004 (!StrictlyPositive && !Result.isNonNegative())) {
17005 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
17006 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
17007 << E->getSourceRange();
17008 return ExprError();
17009 }
17010 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
17011 CKind == OMPC_allocate) &&
17012 !Result.isPowerOf2()) {
17013 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
17014 << E->getSourceRange();
17015 return ExprError();
17016 }
17017
17018 if (!Result.isRepresentableByInt64()) {
17019 Diag(E->getExprLoc(), diag::err_omp_large_expression_in_clause)
17021 return ExprError();
17022 }
17023
17024 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
17025 DSAStack->setAssociatedLoops(Result.getExtValue());
17026 else if (CKind == OMPC_ordered)
17027 DSAStack->setAssociatedLoops(Result.getExtValue());
17028 return ICE;
17029}
17030
17031void SemaOpenMP::setOpenMPDeviceNum(int Num) { DeviceNum = Num; }
17032
17033void SemaOpenMP::setOpenMPDeviceNumID(StringRef ID) { DeviceNumID = ID; }
17034
17035int SemaOpenMP::getOpenMPDeviceNum() const { return DeviceNum; }
17036
17038 llvm::APSInt Result;
17039 Expr::EvalResult EvalResult;
17040 // Evaluate the expression to an integer value
17041 if (!DeviceNumExpr->isValueDependent() &&
17042 DeviceNumExpr->EvaluateAsInt(EvalResult, SemaRef.Context)) {
17043 // The device expression must evaluate to a non-negative integer value.
17044 Result = EvalResult.Val.getInt();
17045 if (Result.isNonNegative()) {
17046 setOpenMPDeviceNum(Result.getZExtValue());
17047 } else {
17048 Diag(DeviceNumExpr->getExprLoc(),
17049 diag::err_omp_negative_expression_in_clause)
17050 << "device_num" << 0 << DeviceNumExpr->getSourceRange();
17051 }
17052 } else if (auto *DeclRef = dyn_cast<DeclRefExpr>(DeviceNumExpr)) {
17053 // Check if the expression is an identifier
17054 IdentifierInfo *IdInfo = DeclRef->getDecl()->getIdentifier();
17055 if (IdInfo) {
17056 setOpenMPDeviceNumID(IdInfo->getName());
17057 }
17058 } else {
17059 Diag(DeviceNumExpr->getExprLoc(), diag::err_expected_expression);
17060 }
17061}
17062
17064 SourceLocation StartLoc,
17065 SourceLocation LParenLoc,
17066 SourceLocation EndLoc) {
17067 // OpenMP [2.8.1, simd construct, Description]
17068 // The parameter of the safelen clause must be a constant
17069 // positive integer expression.
17070 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
17071 if (Safelen.isInvalid())
17072 return nullptr;
17073 return new (getASTContext())
17074 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
17075}
17076
17078 SourceLocation StartLoc,
17079 SourceLocation LParenLoc,
17080 SourceLocation EndLoc) {
17081 // OpenMP [2.8.1, simd construct, Description]
17082 // The parameter of the simdlen clause must be a constant
17083 // positive integer expression.
17084 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
17085 if (Simdlen.isInvalid())
17086 return nullptr;
17087 return new (getASTContext())
17088 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
17089}
17090
17091/// Tries to find omp_allocator_handle_t type.
17093 DSAStackTy *Stack) {
17094 if (!Stack->getOMPAllocatorHandleT().isNull())
17095 return true;
17096
17097 // Set the allocator handle type.
17098 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
17099 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
17100 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
17101 S.Diag(Loc, diag::err_omp_implied_type_not_found)
17102 << "omp_allocator_handle_t";
17103 return false;
17104 }
17105 QualType AllocatorHandleEnumTy = PT.get();
17106 AllocatorHandleEnumTy.addConst();
17107 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
17108
17109 // Fill the predefined allocator map.
17110 bool ErrorFound = false;
17111 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
17112 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
17113 StringRef Allocator =
17114 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
17115 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
17116 auto *VD = dyn_cast_or_null<ValueDecl>(
17117 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
17118 if (!VD) {
17119 ErrorFound = true;
17120 break;
17121 }
17122 QualType AllocatorType =
17124 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
17125 if (!Res.isUsable()) {
17126 ErrorFound = true;
17127 break;
17128 }
17129 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
17131 /*AllowExplicit=*/true);
17132 if (!Res.isUsable()) {
17133 ErrorFound = true;
17134 break;
17135 }
17136 Stack->setAllocator(AllocatorKind, Res.get());
17137 }
17138 if (ErrorFound) {
17139 S.Diag(Loc, diag::err_omp_implied_type_not_found)
17140 << "omp_allocator_handle_t";
17141 return false;
17142 }
17143
17144 return true;
17145}
17146
17148 SourceLocation StartLoc,
17149 SourceLocation LParenLoc,
17150 SourceLocation EndLoc) {
17151 // OpenMP [2.11.3, allocate Directive, Description]
17152 // allocator is an expression of omp_allocator_handle_t type.
17154 return nullptr;
17155
17156 ExprResult Allocator = SemaRef.DefaultLvalueConversion(A);
17157 if (Allocator.isInvalid())
17158 return nullptr;
17159 Allocator = SemaRef.PerformImplicitConversion(
17160 Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
17162 /*AllowExplicit=*/true);
17163 if (Allocator.isInvalid())
17164 return nullptr;
17165 return new (getASTContext())
17166 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
17167}
17168
17170 SourceLocation StartLoc,
17171 SourceLocation LParenLoc,
17172 SourceLocation EndLoc) {
17173 // OpenMP [2.7.1, loop construct, Description]
17174 // OpenMP [2.8.1, simd construct, Description]
17175 // OpenMP [2.9.6, distribute construct, Description]
17176 // The parameter of the collapse clause must be a constant
17177 // positive integer expression.
17178 ExprResult NumForLoopsResult =
17179 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
17180 if (NumForLoopsResult.isInvalid())
17181 return nullptr;
17182 return new (getASTContext())
17183 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
17184}
17185
17187 SourceLocation EndLoc,
17188 SourceLocation LParenLoc,
17189 Expr *NumForLoops) {
17190 // OpenMP [2.7.1, loop construct, Description]
17191 // OpenMP [2.8.1, simd construct, Description]
17192 // OpenMP [2.9.6, distribute construct, Description]
17193 // The parameter of the ordered clause must be a constant
17194 // positive integer expression if any.
17195 if (NumForLoops && LParenLoc.isValid()) {
17196 ExprResult NumForLoopsResult =
17197 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
17198 if (NumForLoopsResult.isInvalid())
17199 return nullptr;
17200 NumForLoops = NumForLoopsResult.get();
17201 } else {
17202 NumForLoops = nullptr;
17203 }
17204 auto *Clause =
17205 OMPOrderedClause::Create(getASTContext(), NumForLoops,
17206 NumForLoops ? DSAStack->getAssociatedLoops() : 0,
17207 StartLoc, LParenLoc, EndLoc);
17208 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
17209 return Clause;
17210}
17211
17213 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
17214 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17215 OMPClause *Res = nullptr;
17216 switch (Kind) {
17217 case OMPC_proc_bind:
17218 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
17219 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17220 break;
17221 case OMPC_atomic_default_mem_order:
17223 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
17224 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17225 break;
17226 case OMPC_fail:
17227 Res = ActOnOpenMPFailClause(static_cast<OpenMPClauseKind>(Argument),
17228 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17229 break;
17230 case OMPC_update:
17231 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
17232 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17233 break;
17234 case OMPC_bind:
17235 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
17236 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17237 break;
17238 case OMPC_at:
17239 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
17240 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17241 break;
17242 case OMPC_severity:
17244 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
17245 LParenLoc, EndLoc);
17246 break;
17247 case OMPC_threadset:
17248 Res = ActOnOpenMPThreadsetClause(static_cast<OpenMPThreadsetKind>(Argument),
17249 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17250 break;
17251 case OMPC_if:
17252 case OMPC_final:
17253 case OMPC_num_threads:
17254 case OMPC_safelen:
17255 case OMPC_simdlen:
17256 case OMPC_sizes:
17257 case OMPC_allocator:
17258 case OMPC_collapse:
17259 case OMPC_schedule:
17260 case OMPC_private:
17261 case OMPC_firstprivate:
17262 case OMPC_lastprivate:
17263 case OMPC_shared:
17264 case OMPC_reduction:
17265 case OMPC_task_reduction:
17266 case OMPC_in_reduction:
17267 case OMPC_linear:
17268 case OMPC_aligned:
17269 case OMPC_copyin:
17270 case OMPC_copyprivate:
17271 case OMPC_ordered:
17272 case OMPC_nowait:
17273 case OMPC_untied:
17274 case OMPC_mergeable:
17275 case OMPC_threadprivate:
17276 case OMPC_groupprivate:
17277 case OMPC_allocate:
17278 case OMPC_flush:
17279 case OMPC_depobj:
17280 case OMPC_read:
17281 case OMPC_write:
17282 case OMPC_capture:
17283 case OMPC_compare:
17284 case OMPC_seq_cst:
17285 case OMPC_acq_rel:
17286 case OMPC_acquire:
17287 case OMPC_release:
17288 case OMPC_relaxed:
17289 case OMPC_depend:
17290 case OMPC_device:
17291 case OMPC_threads:
17292 case OMPC_simd:
17293 case OMPC_map:
17294 case OMPC_num_teams:
17295 case OMPC_thread_limit:
17296 case OMPC_priority:
17297 case OMPC_grainsize:
17298 case OMPC_nogroup:
17299 case OMPC_num_tasks:
17300 case OMPC_hint:
17301 case OMPC_dist_schedule:
17302 case OMPC_default:
17303 case OMPC_defaultmap:
17304 case OMPC_unknown:
17305 case OMPC_uniform:
17306 case OMPC_to:
17307 case OMPC_from:
17308 case OMPC_use_device_ptr:
17309 case OMPC_use_device_addr:
17310 case OMPC_is_device_ptr:
17311 case OMPC_has_device_addr:
17312 case OMPC_unified_address:
17313 case OMPC_unified_shared_memory:
17314 case OMPC_reverse_offload:
17315 case OMPC_dynamic_allocators:
17316 case OMPC_self_maps:
17317 case OMPC_device_type:
17318 case OMPC_match:
17319 case OMPC_nontemporal:
17320 case OMPC_destroy:
17321 case OMPC_novariants:
17322 case OMPC_nocontext:
17323 case OMPC_detach:
17324 case OMPC_inclusive:
17325 case OMPC_exclusive:
17326 case OMPC_uses_allocators:
17327 case OMPC_affinity:
17328 case OMPC_when:
17329 case OMPC_message:
17330 default:
17331 llvm_unreachable("Clause is not allowed.");
17332 }
17333 return Res;
17334}
17335
17337 llvm::omp::DefaultKind M, SourceLocation MLoc,
17339 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17340 if (M == OMP_DEFAULT_unknown) {
17341 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17342 << getListOfPossibleValues(OMPC_default, /*First=*/0,
17343 /*Last=*/unsigned(OMP_DEFAULT_unknown))
17344 << getOpenMPClauseNameForDiag(OMPC_default);
17345 return nullptr;
17346 }
17347 if (VCKind == OMPC_DEFAULT_VC_unknown) {
17348 Diag(VCKindLoc, diag::err_omp_default_vc)
17349 << getOpenMPSimpleClauseTypeName(OMPC_default, unsigned(M));
17350 return nullptr;
17351 }
17352
17353 bool IsTargetDefault =
17354 getLangOpts().OpenMP >= 60 &&
17355 isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective());
17356
17357 // OpenMP 6.0, page 224, lines 3-4 default Clause, Semantics
17358 // If data-sharing-attribute is shared then the clause has no effect
17359 // on a target construct;
17360 if (IsTargetDefault && M == OMP_DEFAULT_shared)
17361 return nullptr;
17362
17363 auto SetDefaultClauseAttrs = [&](llvm::omp::DefaultKind M,
17366 OpenMPDefaultmapClauseKind DefMapKind;
17367 // default data-sharing-attribute
17368 switch (M) {
17369 case OMP_DEFAULT_none:
17370 if (IsTargetDefault)
17371 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_none;
17372 else
17373 DSAStack->setDefaultDSANone(MLoc);
17374 break;
17375 case OMP_DEFAULT_firstprivate:
17376 if (IsTargetDefault)
17377 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_firstprivate;
17378 else
17379 DSAStack->setDefaultDSAFirstPrivate(MLoc);
17380 break;
17381 case OMP_DEFAULT_private:
17382 if (IsTargetDefault)
17383 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_private;
17384 else
17385 DSAStack->setDefaultDSAPrivate(MLoc);
17386 break;
17387 case OMP_DEFAULT_shared:
17388 assert(!IsTargetDefault && "DSA shared invalid with target directive");
17389 DSAStack->setDefaultDSAShared(MLoc);
17390 break;
17391 default:
17392 llvm_unreachable("unexpected DSA in OpenMP default clause");
17393 }
17394 // default variable-category
17395 switch (VCKind) {
17396 case OMPC_DEFAULT_VC_aggregate:
17397 if (IsTargetDefault)
17398 DefMapKind = OMPC_DEFAULTMAP_aggregate;
17399 else
17400 DSAStack->setDefaultDSAVCAggregate(VCKindLoc);
17401 break;
17402 case OMPC_DEFAULT_VC_pointer:
17403 if (IsTargetDefault)
17404 DefMapKind = OMPC_DEFAULTMAP_pointer;
17405 else
17406 DSAStack->setDefaultDSAVCPointer(VCKindLoc);
17407 break;
17408 case OMPC_DEFAULT_VC_scalar:
17409 if (IsTargetDefault)
17410 DefMapKind = OMPC_DEFAULTMAP_scalar;
17411 else
17412 DSAStack->setDefaultDSAVCScalar(VCKindLoc);
17413 break;
17414 case OMPC_DEFAULT_VC_all:
17415 if (IsTargetDefault)
17416 DefMapKind = OMPC_DEFAULTMAP_all;
17417 else
17418 DSAStack->setDefaultDSAVCAll(VCKindLoc);
17419 break;
17420 default:
17421 llvm_unreachable("unexpected variable category in OpenMP default clause");
17422 }
17423 // OpenMP 6.0, page 224, lines 4-5 default Clause, Semantics
17424 // otherwise, its effect on a target construct is equivalent to
17425 // specifying the defaultmap clause with the same data-sharing-attribute
17426 // and variable-category.
17427 //
17428 // If earlier than OpenMP 6.0, or not a target directive, the default DSA
17429 // is/was set as before.
17430 if (IsTargetDefault) {
17431 if (DefMapKind == OMPC_DEFAULTMAP_all) {
17432 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_aggregate, MLoc);
17433 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_scalar, MLoc);
17434 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_pointer, MLoc);
17435 } else {
17436 DSAStack->setDefaultDMAAttr(DefMapMod, DefMapKind, MLoc);
17437 }
17438 }
17439 };
17440
17441 SetDefaultClauseAttrs(M, VCKind);
17442 return new (getASTContext())
17443 OMPDefaultClause(M, MLoc, VCKind, VCKindLoc, StartLoc, LParenLoc, EndLoc);
17444}
17445
17447 SourceLocation KindLoc,
17448 SourceLocation StartLoc,
17449 SourceLocation LParenLoc,
17450 SourceLocation EndLoc) {
17451 if (Kind == OMPC_THREADSET_unknown) {
17452 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17453 << getListOfPossibleValues(OMPC_threadset, /*First=*/0,
17454 /*Last=*/unsigned(OMPC_THREADSET_unknown))
17455 << getOpenMPClauseName(OMPC_threadset);
17456 return nullptr;
17457 }
17458
17459 return new (getASTContext())
17460 OMPThreadsetClause(Kind, KindLoc, StartLoc, LParenLoc, EndLoc);
17461}
17462
17464 Expr *ImpexTypeArg,
17465 SourceLocation StartLoc,
17466 SourceLocation LParenLoc,
17467 SourceLocation EndLoc) {
17468 ExprResult ER = SemaRef.DefaultLvalueConversion(ImpexTypeArg);
17469 if (ER.isInvalid())
17470 return nullptr;
17471
17472 return new (Ctx) OMPTransparentClause(ER.get(), StartLoc, LParenLoc, EndLoc);
17473}
17474
17476 SourceLocation StartLoc,
17477 SourceLocation LParenLoc,
17478 SourceLocation EndLoc) {
17479 QualType Ty = ImpexTypeArg->getType();
17480
17481 if (const auto *TT = Ty->getAs<TypedefType>()) {
17482 const TypedefNameDecl *TypedefDecl = TT->getDecl();
17483 llvm::StringRef TypedefName = TypedefDecl->getName();
17484 IdentifierInfo &II = SemaRef.PP.getIdentifierTable().get(TypedefName);
17485 ParsedType ImpexTy =
17486 SemaRef.getTypeName(II, StartLoc, SemaRef.getCurScope());
17487 if (!ImpexTy.getAsOpaquePtr() || ImpexTy.get().isNull()) {
17488 SemaRef.Diag(StartLoc, diag::err_omp_implied_type_not_found)
17489 << TypedefName;
17490 return nullptr;
17491 }
17492 return createTransparentClause(SemaRef, getASTContext(), ImpexTypeArg,
17493 StartLoc, LParenLoc, EndLoc);
17494 }
17495
17496 if (Ty->isEnumeralType())
17497 return createTransparentClause(SemaRef, getASTContext(), ImpexTypeArg,
17498 StartLoc, LParenLoc, EndLoc);
17499
17500 if (Ty->isIntegerType()) {
17501 if (isNonNegativeIntegerValue(ImpexTypeArg, SemaRef, OMPC_transparent,
17502 /*StrictlyPositive=*/false)) {
17504 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(StartLoc,
17505 ImpexTypeArg);
17506 if (std::optional<llvm::APSInt> Result =
17507 Value.get()->getIntegerConstantExpr(SemaRef.Context)) {
17508 if (Result->isNegative() ||
17509 Result >
17510 static_cast<int64_t>(SemaOpenMP::OpenMPImpexType::OMP_Export))
17511 SemaRef.Diag(StartLoc, diag::err_omp_transparent_invalid_value);
17512 }
17513 return createTransparentClause(SemaRef, getASTContext(), ImpexTypeArg,
17514 StartLoc, LParenLoc, EndLoc);
17515 }
17516 }
17517 SemaRef.Diag(StartLoc, diag::err_omp_transparent_invalid_type) << Ty;
17518 return nullptr;
17519}
17520
17522 SourceLocation KindKwLoc,
17523 SourceLocation StartLoc,
17524 SourceLocation LParenLoc,
17525 SourceLocation EndLoc) {
17526 if (Kind == OMP_PROC_BIND_unknown) {
17527 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17528 << getListOfPossibleValues(OMPC_proc_bind,
17529 /*First=*/unsigned(OMP_PROC_BIND_master),
17530 /*Last=*/
17531 unsigned(getLangOpts().OpenMP > 50
17532 ? OMP_PROC_BIND_primary
17533 : OMP_PROC_BIND_spread) +
17534 1)
17535 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
17536 return nullptr;
17537 }
17538 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
17539 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17540 << getListOfPossibleValues(OMPC_proc_bind,
17541 /*First=*/unsigned(OMP_PROC_BIND_master),
17542 /*Last=*/
17543 unsigned(OMP_PROC_BIND_spread) + 1)
17544 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
17545 return new (getASTContext())
17546 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17547}
17548
17551 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17553 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17555 OMPC_atomic_default_mem_order, /*First=*/0,
17557 << getOpenMPClauseNameForDiag(OMPC_atomic_default_mem_order);
17558 return nullptr;
17559 }
17560 return new (getASTContext()) OMPAtomicDefaultMemOrderClause(
17561 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17562}
17563
17565 SourceLocation KindKwLoc,
17566 SourceLocation StartLoc,
17567 SourceLocation LParenLoc,
17568 SourceLocation EndLoc) {
17569 if (Kind == OMPC_AT_unknown) {
17570 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17571 << getListOfPossibleValues(OMPC_at, /*First=*/0,
17572 /*Last=*/OMPC_AT_unknown)
17573 << getOpenMPClauseNameForDiag(OMPC_at);
17574 return nullptr;
17575 }
17576 return new (getASTContext())
17577 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17578}
17579
17581 SourceLocation KindKwLoc,
17582 SourceLocation StartLoc,
17583 SourceLocation LParenLoc,
17584 SourceLocation EndLoc) {
17585 if (Kind == OMPC_SEVERITY_unknown) {
17586 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17587 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
17588 /*Last=*/OMPC_SEVERITY_unknown)
17589 << getOpenMPClauseNameForDiag(OMPC_severity);
17590 return nullptr;
17591 }
17592 return new (getASTContext())
17593 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17594}
17595
17597 SourceLocation StartLoc,
17598 SourceLocation LParenLoc,
17599 SourceLocation EndLoc) {
17600 assert(ME && "NULL expr in Message clause");
17601 QualType Type = ME->getType();
17602 if ((!Type->isPointerType() && !Type->isArrayType()) ||
17604 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
17605 << getOpenMPClauseNameForDiag(OMPC_message) << 0;
17606 return nullptr;
17607 }
17608
17609 Stmt *HelperValStmt = nullptr;
17610
17611 // Depending on whether this clause appears in an executable context or not,
17612 // we may or may not build a capture.
17613 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17614 OpenMPDirectiveKind CaptureRegion =
17615 DKind == OMPD_unknown ? OMPD_unknown
17617 DKind, OMPC_message, getLangOpts().OpenMP);
17618 if (CaptureRegion != OMPD_unknown &&
17619 !SemaRef.CurContext->isDependentContext()) {
17620 ME = SemaRef.MakeFullExpr(ME).get();
17621 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17622 ME = tryBuildCapture(SemaRef, ME, Captures).get();
17623 HelperValStmt = buildPreInits(getASTContext(), Captures);
17624 }
17625
17626 // Convert array type to pointer type if needed.
17627 ME = SemaRef.DefaultFunctionArrayLvalueConversion(ME).get();
17628
17629 return new (getASTContext()) OMPMessageClause(
17630 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17631}
17632
17635 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
17636 SourceLocation KindLoc, SourceLocation EndLoc) {
17637 if (Kind != OMPC_ORDER_concurrent ||
17638 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
17639 // Kind should be concurrent,
17640 // Modifiers introduced in OpenMP 5.1
17641 static_assert(OMPC_ORDER_unknown > 0,
17642 "OMPC_ORDER_unknown not greater than 0");
17643
17644 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17645 << getListOfPossibleValues(OMPC_order,
17646 /*First=*/0,
17647 /*Last=*/OMPC_ORDER_unknown)
17648 << getOpenMPClauseNameForDiag(OMPC_order);
17649 return nullptr;
17650 }
17651 if (getLangOpts().OpenMP >= 51 && Modifier == OMPC_ORDER_MODIFIER_unknown &&
17652 MLoc.isValid()) {
17653 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17654 << getListOfPossibleValues(OMPC_order,
17655 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
17656 /*Last=*/OMPC_ORDER_MODIFIER_last)
17657 << getOpenMPClauseNameForDiag(OMPC_order);
17658 } else if (getLangOpts().OpenMP >= 50) {
17659 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
17660 if (DSAStack->getCurScope()) {
17661 // mark the current scope with 'order' flag
17662 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
17663 DSAStack->getCurScope()->setFlags(existingFlags |
17665 }
17666 }
17667 return new (getASTContext()) OMPOrderClause(
17668 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
17669}
17670
17672 SourceLocation KindKwLoc,
17673 SourceLocation StartLoc,
17674 SourceLocation LParenLoc,
17675 SourceLocation EndLoc) {
17676 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
17677 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
17678 SmallVector<unsigned> Except = {
17679 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
17680 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
17681 if (getLangOpts().OpenMP < 51)
17682 Except.push_back(OMPC_DEPEND_inoutset);
17683 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17684 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
17685 /*Last=*/OMPC_DEPEND_unknown, Except)
17686 << getOpenMPClauseNameForDiag(OMPC_update);
17687 return nullptr;
17688 }
17689 return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc,
17690 KindKwLoc, Kind, EndLoc);
17691}
17692
17694 SourceLocation StartLoc,
17695 SourceLocation LParenLoc,
17696 SourceLocation EndLoc) {
17697 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
17698
17699 for (Expr *&SizeExpr : SanitizedSizeExprs) {
17700 // Skip if already sanitized, e.g. during a partial template instantiation.
17701 if (!SizeExpr)
17702 continue;
17703
17704 bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes,
17705 /*StrictlyPositive=*/true);
17706
17707 // isNonNegativeIntegerValue returns true for non-integral types (but still
17708 // emits error diagnostic), so check for the expected type explicitly.
17709 QualType SizeTy = SizeExpr->getType();
17710 if (!SizeTy->isIntegerType())
17711 IsValid = false;
17712
17713 // Handling in templates is tricky. There are four possibilities to
17714 // consider:
17715 //
17716 // 1a. The expression is valid and we are in a instantiated template or not
17717 // in a template:
17718 // Pass valid expression to be further analysed later in Sema.
17719 // 1b. The expression is valid and we are in a template (including partial
17720 // instantiation):
17721 // isNonNegativeIntegerValue skipped any checks so there is no
17722 // guarantee it will be correct after instantiation.
17723 // ActOnOpenMPSizesClause will be called again at instantiation when
17724 // it is not in a dependent context anymore. This may cause warnings
17725 // to be emitted multiple times.
17726 // 2a. The expression is invalid and we are in an instantiated template or
17727 // not in a template:
17728 // Invalidate the expression with a clearly wrong value (nullptr) so
17729 // later in Sema we do not have to do the same validity analysis again
17730 // or crash from unexpected data. Error diagnostics have already been
17731 // emitted.
17732 // 2b. The expression is invalid and we are in a template (including partial
17733 // instantiation):
17734 // Pass the invalid expression as-is, template instantiation may
17735 // replace unexpected types/values with valid ones. The directives
17736 // with this clause must not try to use these expressions in dependent
17737 // contexts, but delay analysis until full instantiation.
17738 if (!SizeExpr->isInstantiationDependent() && !IsValid)
17739 SizeExpr = nullptr;
17740 }
17741
17742 return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17743 SanitizedSizeExprs);
17744}
17745
17747 SourceLocation StartLoc,
17748 SourceLocation LParenLoc,
17749 SourceLocation EndLoc) {
17750 size_t NumLoops = PermExprs.size();
17751 SmallVector<Expr *> SanitizedPermExprs;
17752 llvm::append_range(SanitizedPermExprs, PermExprs);
17753
17754 for (Expr *&PermExpr : SanitizedPermExprs) {
17755 // Skip if template-dependent or already sanitized, e.g. during a partial
17756 // template instantiation.
17757 if (!PermExpr || PermExpr->isInstantiationDependent())
17758 continue;
17759
17760 llvm::APSInt PermVal;
17761 ExprResult PermEvalExpr = SemaRef.VerifyIntegerConstantExpression(
17762 PermExpr, &PermVal, AllowFoldKind::Allow);
17763 bool IsValid = PermEvalExpr.isUsable();
17764 if (IsValid)
17765 PermExpr = PermEvalExpr.get();
17766
17767 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
17768 SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
17769 PermEvalExpr.get()->getEndLoc());
17770 Diag(PermEvalExpr.get()->getExprLoc(),
17771 diag::err_omp_interchange_permutation_value_range)
17772 << NumLoops << ExprRange;
17773 IsValid = false;
17774 }
17775
17776 if (!PermExpr->isInstantiationDependent() && !IsValid)
17777 PermExpr = nullptr;
17778 }
17779
17780 return OMPPermutationClause::Create(getASTContext(), StartLoc, LParenLoc,
17781 EndLoc, SanitizedPermExprs);
17782}
17783
17785 SourceLocation EndLoc) {
17786 return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc);
17787}
17788
17790 SourceLocation StartLoc,
17791 SourceLocation LParenLoc,
17792 SourceLocation EndLoc) {
17793 if (FactorExpr) {
17794 // If an argument is specified, it must be a constant (or an unevaluated
17795 // template expression).
17797 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
17798 if (FactorResult.isInvalid())
17799 return nullptr;
17800 FactorExpr = FactorResult.get();
17801 }
17802
17803 return OMPPartialClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17804 FactorExpr);
17805}
17806
17808 Expr *First, Expr *Count, SourceLocation StartLoc, SourceLocation LParenLoc,
17809 SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc) {
17810
17811 // OpenMP [6.0, Restrictions]
17812 // First and Count must be integer expressions with positive value
17813 ExprResult FirstVal =
17815 if (FirstVal.isInvalid())
17816 First = nullptr;
17817
17818 ExprResult CountVal =
17819 VerifyPositiveIntegerConstantInClause(Count, OMPC_looprange);
17820 if (CountVal.isInvalid())
17821 Count = nullptr;
17822
17823 // OpenMP [6.0, Restrictions]
17824 // first + count - 1 must not evaluate to a value greater than the
17825 // loop sequence length of the associated canonical loop sequence.
17826 // This check must be performed afterwards due to the delayed
17827 // parsing and computation of the associated loop sequence
17828 return OMPLoopRangeClause::Create(getASTContext(), StartLoc, LParenLoc,
17829 FirstLoc, CountLoc, EndLoc, First, Count);
17830}
17831
17833 SourceLocation LParenLoc,
17834 SourceLocation EndLoc) {
17835 ExprResult AlignVal;
17836 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
17837 if (AlignVal.isInvalid())
17838 return nullptr;
17839 return OMPAlignClause::Create(getASTContext(), AlignVal.get(), StartLoc,
17840 LParenLoc, EndLoc);
17841}
17842
17845 SourceLocation StartLoc, SourceLocation LParenLoc,
17846 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
17847 SourceLocation EndLoc) {
17848 OMPClause *Res = nullptr;
17849 switch (Kind) {
17850 case OMPC_schedule: {
17851 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
17852 assert(Argument.size() == NumberOfElements &&
17853 ArgumentLoc.size() == NumberOfElements);
17855 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
17856 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
17857 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
17858 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
17859 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
17860 break;
17861 }
17862 case OMPC_if:
17863 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17864 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
17865 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
17866 DelimLoc, EndLoc);
17867 break;
17868 case OMPC_dist_schedule:
17870 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
17871 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
17872 break;
17873 case OMPC_default:
17874 enum { DefaultModifier, DefaultVarCategory };
17876 static_cast<llvm::omp::DefaultKind>(Argument[DefaultModifier]),
17877 ArgumentLoc[DefaultModifier],
17879 Argument[DefaultVarCategory]),
17880 ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc);
17881 break;
17882 case OMPC_defaultmap:
17883 enum { Modifier, DefaultmapKind };
17885 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
17886 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
17887 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
17888 EndLoc);
17889 break;
17890 case OMPC_order:
17891 enum { OrderModifier, OrderKind };
17893 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
17894 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
17895 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
17896 break;
17897 case OMPC_device:
17898 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17900 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
17901 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17902 break;
17903 case OMPC_grainsize:
17904 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17905 "Modifier for grainsize clause and its location are expected.");
17907 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
17908 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17909 break;
17910 case OMPC_num_tasks:
17911 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17912 "Modifier for num_tasks clause and its location are expected.");
17914 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
17915 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17916 break;
17917 case OMPC_dyn_groupprivate: {
17918 enum { Modifier1, Modifier2, NumberOfElements };
17919 assert(Argument.size() == NumberOfElements &&
17920 ArgumentLoc.size() == NumberOfElements &&
17921 "Modifiers for dyn_groupprivate clause and their locations are "
17922 "expected.");
17924 static_cast<OpenMPDynGroupprivateClauseModifier>(Argument[Modifier1]),
17926 Argument[Modifier2]),
17927 Expr, StartLoc, LParenLoc, ArgumentLoc[Modifier1],
17928 ArgumentLoc[Modifier2], EndLoc);
17929 break;
17930 }
17931 case OMPC_num_threads:
17932 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17933 "Modifier for num_threads clause and its location are expected.");
17935 static_cast<OpenMPNumThreadsClauseModifier>(Argument.back()), Expr,
17936 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17937 break;
17938 case OMPC_final:
17939 case OMPC_safelen:
17940 case OMPC_simdlen:
17941 case OMPC_sizes:
17942 case OMPC_allocator:
17943 case OMPC_collapse:
17944 case OMPC_proc_bind:
17945 case OMPC_private:
17946 case OMPC_firstprivate:
17947 case OMPC_lastprivate:
17948 case OMPC_shared:
17949 case OMPC_reduction:
17950 case OMPC_task_reduction:
17951 case OMPC_in_reduction:
17952 case OMPC_linear:
17953 case OMPC_aligned:
17954 case OMPC_copyin:
17955 case OMPC_copyprivate:
17956 case OMPC_ordered:
17957 case OMPC_nowait:
17958 case OMPC_untied:
17959 case OMPC_mergeable:
17960 case OMPC_threadprivate:
17961 case OMPC_groupprivate:
17962 case OMPC_allocate:
17963 case OMPC_flush:
17964 case OMPC_depobj:
17965 case OMPC_read:
17966 case OMPC_write:
17967 case OMPC_update:
17968 case OMPC_capture:
17969 case OMPC_compare:
17970 case OMPC_seq_cst:
17971 case OMPC_acq_rel:
17972 case OMPC_acquire:
17973 case OMPC_release:
17974 case OMPC_relaxed:
17975 case OMPC_depend:
17976 case OMPC_threads:
17977 case OMPC_simd:
17978 case OMPC_map:
17979 case OMPC_num_teams:
17980 case OMPC_thread_limit:
17981 case OMPC_priority:
17982 case OMPC_nogroup:
17983 case OMPC_hint:
17984 case OMPC_unknown:
17985 case OMPC_uniform:
17986 case OMPC_to:
17987 case OMPC_from:
17988 case OMPC_use_device_ptr:
17989 case OMPC_use_device_addr:
17990 case OMPC_is_device_ptr:
17991 case OMPC_has_device_addr:
17992 case OMPC_unified_address:
17993 case OMPC_unified_shared_memory:
17994 case OMPC_reverse_offload:
17995 case OMPC_dynamic_allocators:
17996 case OMPC_atomic_default_mem_order:
17997 case OMPC_self_maps:
17998 case OMPC_device_type:
17999 case OMPC_match:
18000 case OMPC_nontemporal:
18001 case OMPC_at:
18002 case OMPC_severity:
18003 case OMPC_message:
18004 case OMPC_destroy:
18005 case OMPC_novariants:
18006 case OMPC_nocontext:
18007 case OMPC_detach:
18008 case OMPC_inclusive:
18009 case OMPC_exclusive:
18010 case OMPC_uses_allocators:
18011 case OMPC_affinity:
18012 case OMPC_when:
18013 case OMPC_bind:
18014 default:
18015 llvm_unreachable("Clause is not allowed.");
18016 }
18017 return Res;
18018}
18019
18022 SourceLocation M1Loc, SourceLocation M2Loc) {
18023 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
18024 SmallVector<unsigned, 2> Excluded;
18026 Excluded.push_back(M2);
18027 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
18028 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
18029 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
18030 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
18031 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
18032 << getListOfPossibleValues(OMPC_schedule,
18033 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
18035 Excluded)
18036 << getOpenMPClauseNameForDiag(OMPC_schedule);
18037 return true;
18038 }
18039 return false;
18040}
18041
18044 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
18045 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
18046 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
18047 if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) ||
18048 checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc))
18049 return nullptr;
18050 // OpenMP, 2.7.1, Loop Construct, Restrictions
18051 // Either the monotonic modifier or the nonmonotonic modifier can be specified
18052 // but not both.
18053 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
18054 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
18055 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
18056 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
18057 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
18058 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
18059 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
18060 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
18061 return nullptr;
18062 }
18063 if (Kind == OMPC_SCHEDULE_unknown) {
18064 std::string Values;
18065 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
18066 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
18067 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
18069 Exclude);
18070 } else {
18071 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
18072 /*Last=*/OMPC_SCHEDULE_unknown);
18073 }
18074 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
18075 << Values << getOpenMPClauseNameForDiag(OMPC_schedule);
18076 return nullptr;
18077 }
18078 // OpenMP, 2.7.1, Loop Construct, Restrictions
18079 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
18080 // schedule(guided).
18081 // OpenMP 5.0 does not have this restriction.
18082 if (getLangOpts().OpenMP < 50 &&
18083 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
18084 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
18085 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
18086 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
18087 diag::err_omp_schedule_nonmonotonic_static);
18088 return nullptr;
18089 }
18090 Expr *ValExpr = ChunkSize;
18091 Stmt *HelperValStmt = nullptr;
18092 if (ChunkSize) {
18093 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
18094 !ChunkSize->isInstantiationDependent() &&
18095 !ChunkSize->containsUnexpandedParameterPack()) {
18096 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
18097 ExprResult Val =
18098 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
18099 if (Val.isInvalid())
18100 return nullptr;
18101
18102 ValExpr = Val.get();
18103
18104 // OpenMP [2.7.1, Restrictions]
18105 // chunk_size must be a loop invariant integer expression with a positive
18106 // value.
18107 if (std::optional<llvm::APSInt> Result =
18109 if (Result->isSigned() && !Result->isStrictlyPositive()) {
18110 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
18111 << "schedule" << 1 << ChunkSize->getSourceRange();
18112 return nullptr;
18113 }
18115 DSAStack->getCurrentDirective(), OMPC_schedule,
18116 getLangOpts().OpenMP) != OMPD_unknown &&
18117 !SemaRef.CurContext->isDependentContext()) {
18118 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18119 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18120 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18121 HelperValStmt = buildPreInits(getASTContext(), Captures);
18122 }
18123 }
18124 }
18125
18126 return new (getASTContext())
18127 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
18128 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
18129}
18130
18132 SourceLocation StartLoc,
18133 SourceLocation EndLoc) {
18134 OMPClause *Res = nullptr;
18135 switch (Kind) {
18136 case OMPC_ordered:
18137 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
18138 break;
18139 case OMPC_nowait:
18140 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc,
18141 /*LParenLoc=*/SourceLocation(),
18142 /*Condition=*/nullptr);
18143 break;
18144 case OMPC_untied:
18145 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
18146 break;
18147 case OMPC_mergeable:
18148 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
18149 break;
18150 case OMPC_read:
18151 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
18152 break;
18153 case OMPC_write:
18154 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
18155 break;
18156 case OMPC_update:
18157 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
18158 break;
18159 case OMPC_capture:
18160 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
18161 break;
18162 case OMPC_compare:
18163 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
18164 break;
18165 case OMPC_fail:
18166 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
18167 break;
18168 case OMPC_seq_cst:
18169 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
18170 break;
18171 case OMPC_acq_rel:
18172 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
18173 break;
18174 case OMPC_acquire:
18175 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
18176 break;
18177 case OMPC_release:
18178 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
18179 break;
18180 case OMPC_relaxed:
18181 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
18182 break;
18183 case OMPC_weak:
18184 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
18185 break;
18186 case OMPC_threads:
18187 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
18188 break;
18189 case OMPC_simd:
18190 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
18191 break;
18192 case OMPC_nogroup:
18193 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
18194 break;
18195 case OMPC_unified_address:
18196 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
18197 break;
18198 case OMPC_unified_shared_memory:
18199 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
18200 break;
18201 case OMPC_reverse_offload:
18202 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
18203 break;
18204 case OMPC_dynamic_allocators:
18205 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
18206 break;
18207 case OMPC_self_maps:
18208 Res = ActOnOpenMPSelfMapsClause(StartLoc, EndLoc);
18209 break;
18210 case OMPC_destroy:
18211 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
18212 /*LParenLoc=*/SourceLocation(),
18213 /*VarLoc=*/SourceLocation(), EndLoc);
18214 break;
18215 case OMPC_full:
18216 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
18217 break;
18218 case OMPC_partial:
18219 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
18220 break;
18221 case OMPC_ompx_bare:
18222 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
18223 break;
18224 case OMPC_if:
18225 case OMPC_final:
18226 case OMPC_num_threads:
18227 case OMPC_safelen:
18228 case OMPC_simdlen:
18229 case OMPC_sizes:
18230 case OMPC_allocator:
18231 case OMPC_collapse:
18232 case OMPC_schedule:
18233 case OMPC_private:
18234 case OMPC_firstprivate:
18235 case OMPC_lastprivate:
18236 case OMPC_shared:
18237 case OMPC_reduction:
18238 case OMPC_task_reduction:
18239 case OMPC_in_reduction:
18240 case OMPC_linear:
18241 case OMPC_aligned:
18242 case OMPC_copyin:
18243 case OMPC_copyprivate:
18244 case OMPC_default:
18245 case OMPC_proc_bind:
18246 case OMPC_threadprivate:
18247 case OMPC_groupprivate:
18248 case OMPC_allocate:
18249 case OMPC_flush:
18250 case OMPC_depobj:
18251 case OMPC_depend:
18252 case OMPC_device:
18253 case OMPC_map:
18254 case OMPC_num_teams:
18255 case OMPC_thread_limit:
18256 case OMPC_priority:
18257 case OMPC_grainsize:
18258 case OMPC_num_tasks:
18259 case OMPC_hint:
18260 case OMPC_dist_schedule:
18261 case OMPC_defaultmap:
18262 case OMPC_unknown:
18263 case OMPC_uniform:
18264 case OMPC_to:
18265 case OMPC_from:
18266 case OMPC_use_device_ptr:
18267 case OMPC_use_device_addr:
18268 case OMPC_is_device_ptr:
18269 case OMPC_has_device_addr:
18270 case OMPC_atomic_default_mem_order:
18271 case OMPC_device_type:
18272 case OMPC_match:
18273 case OMPC_nontemporal:
18274 case OMPC_order:
18275 case OMPC_at:
18276 case OMPC_severity:
18277 case OMPC_message:
18278 case OMPC_novariants:
18279 case OMPC_nocontext:
18280 case OMPC_detach:
18281 case OMPC_inclusive:
18282 case OMPC_exclusive:
18283 case OMPC_uses_allocators:
18284 case OMPC_affinity:
18285 case OMPC_when:
18286 case OMPC_ompx_dyn_cgroup_mem:
18287 case OMPC_dyn_groupprivate:
18288 default:
18289 llvm_unreachable("Clause is not allowed.");
18290 }
18291 return Res;
18292}
18293
18295 SourceLocation EndLoc,
18296 SourceLocation LParenLoc,
18297 Expr *Condition) {
18298 Expr *ValExpr = Condition;
18299 if (Condition && LParenLoc.isValid()) {
18300 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18301 !Condition->isInstantiationDependent() &&
18302 !Condition->containsUnexpandedParameterPack()) {
18303 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
18304 if (Val.isInvalid())
18305 return nullptr;
18306
18307 ValExpr = Val.get();
18308 }
18309 }
18310 DSAStack->setNowaitRegion();
18311 return new (getASTContext())
18312 OMPNowaitClause(ValExpr, StartLoc, LParenLoc, EndLoc);
18313}
18314
18316 SourceLocation EndLoc) {
18317 DSAStack->setUntiedRegion();
18318 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
18319}
18320
18322 SourceLocation EndLoc) {
18323 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
18324}
18325
18327 SourceLocation EndLoc) {
18328 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
18329}
18330
18332 SourceLocation EndLoc) {
18333 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
18334}
18335
18337 SourceLocation EndLoc) {
18338 return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc);
18339}
18340
18342 SourceLocation EndLoc) {
18343 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
18344}
18345
18347 SourceLocation EndLoc) {
18348 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
18349}
18350
18352 SourceLocation EndLoc) {
18353 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
18354}
18355
18357 SourceLocation KindLoc,
18358 SourceLocation StartLoc,
18359 SourceLocation LParenLoc,
18360 SourceLocation EndLoc) {
18361
18363 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
18364 return nullptr;
18365 }
18366 return new (getASTContext())
18367 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
18368}
18369
18371 SourceLocation EndLoc) {
18372 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
18373}
18374
18376 SourceLocation EndLoc) {
18377 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
18378}
18379
18381 SourceLocation EndLoc) {
18382 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
18383}
18384
18386 SourceLocation EndLoc) {
18387 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
18388}
18389
18391 SourceLocation EndLoc) {
18392 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
18393}
18394
18396 SourceLocation EndLoc) {
18397 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
18398}
18399
18401 SourceLocation EndLoc) {
18402 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
18403}
18404
18406 SourceLocation EndLoc) {
18407 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
18408}
18409
18411 SourceLocation EndLoc) {
18412 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
18413}
18414
18416 SourceLocation EndLoc) {
18417 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
18418}
18419
18420OMPClause *
18422 SourceLocation EndLoc) {
18423 return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
18424}
18425
18427 SourceLocation EndLoc) {
18428 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
18429}
18430
18431OMPClause *
18433 SourceLocation EndLoc) {
18434 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
18435}
18436
18438 SourceLocation EndLoc) {
18439 return new (getASTContext()) OMPSelfMapsClause(StartLoc, EndLoc);
18440}
18441
18444 SourceLocation StartLoc,
18445 SourceLocation EndLoc) {
18446
18447 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18448 // At least one action-clause must appear on a directive.
18449 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
18450 unsigned OMPVersion = getLangOpts().OpenMP;
18451 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
18452 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
18453 << Expected << getOpenMPDirectiveName(OMPD_interop, OMPVersion);
18454 return StmtError();
18455 }
18456
18457 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18458 // A depend clause can only appear on the directive if a targetsync
18459 // interop-type is present or the interop-var was initialized with
18460 // the targetsync interop-type.
18461
18462 // If there is any 'init' clause diagnose if there is no 'init' clause with
18463 // interop-type of 'targetsync'. Cases involving other directives cannot be
18464 // diagnosed.
18465 const OMPDependClause *DependClause = nullptr;
18466 bool HasInitClause = false;
18467 bool IsTargetSync = false;
18468 for (const OMPClause *C : Clauses) {
18469 if (IsTargetSync)
18470 break;
18471 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
18472 HasInitClause = true;
18473 if (InitClause->getIsTargetSync())
18474 IsTargetSync = true;
18475 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
18476 DependClause = DC;
18477 }
18478 }
18479 if (DependClause && HasInitClause && !IsTargetSync) {
18480 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
18481 return StmtError();
18482 }
18483
18484 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18485 // Each interop-var may be specified for at most one action-clause of each
18486 // interop construct.
18488 for (OMPClause *C : Clauses) {
18489 OpenMPClauseKind ClauseKind = C->getClauseKind();
18490 std::pair<ValueDecl *, bool> DeclResult;
18491 SourceLocation ELoc;
18492 SourceRange ERange;
18493
18494 if (ClauseKind == OMPC_init) {
18495 auto *E = cast<OMPInitClause>(C)->getInteropVar();
18496 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18497 } else if (ClauseKind == OMPC_use) {
18498 auto *E = cast<OMPUseClause>(C)->getInteropVar();
18499 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18500 } else if (ClauseKind == OMPC_destroy) {
18501 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
18502 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18503 }
18504
18505 if (DeclResult.first) {
18506 if (!InteropVars.insert(DeclResult.first).second) {
18507 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
18508 << DeclResult.first;
18509 return StmtError();
18510 }
18511 }
18512 }
18513
18514 return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc,
18515 Clauses);
18516}
18517
18518static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
18519 SourceLocation VarLoc,
18520 OpenMPClauseKind Kind) {
18521 SourceLocation ELoc;
18522 SourceRange ERange;
18523 Expr *RefExpr = InteropVarExpr;
18524 auto Res = getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
18525 /*AllowArraySection=*/false,
18526 /*AllowAssumedSizeArray=*/false,
18527 /*DiagType=*/"omp_interop_t");
18528
18529 if (Res.second) {
18530 // It will be analyzed later.
18531 return true;
18532 }
18533
18534 if (!Res.first)
18535 return false;
18536
18537 // Interop variable should be of type omp_interop_t.
18538 bool HasError = false;
18539 QualType InteropType;
18540 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
18541 VarLoc, Sema::LookupOrdinaryName);
18542 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
18543 NamedDecl *ND = Result.getFoundDecl();
18544 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
18545 InteropType = QualType(TD->getTypeForDecl(), 0);
18546 } else {
18547 HasError = true;
18548 }
18549 } else {
18550 HasError = true;
18551 }
18552
18553 if (HasError) {
18554 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
18555 << "omp_interop_t";
18556 return false;
18557 }
18558
18559 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
18560 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
18561 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
18562 return false;
18563 }
18564
18565 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18566 // The interop-var passed to init or destroy must be non-const.
18567 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
18568 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
18569 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
18570 << /*non-const*/ 1;
18571 return false;
18572 }
18573 return true;
18574}
18575
18577 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
18578 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
18579
18580 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init))
18581 return nullptr;
18582
18583 // Check prefer_type values. These foreign-runtime-id values are either
18584 // string literals or constant integral expressions.
18585 for (const Expr *E : InteropInfo.PreferTypes) {
18586 if (E->isValueDependent() || E->isTypeDependent() ||
18588 continue;
18590 continue;
18591 if (isa<StringLiteral>(E))
18592 continue;
18593 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
18594 return nullptr;
18595 }
18596
18597 return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo,
18598 StartLoc, LParenLoc, VarLoc, EndLoc);
18599}
18600
18602 SourceLocation StartLoc,
18603 SourceLocation LParenLoc,
18604 SourceLocation VarLoc,
18605 SourceLocation EndLoc) {
18606
18607 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use))
18608 return nullptr;
18609
18610 return new (getASTContext())
18611 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18612}
18613
18615 SourceLocation StartLoc,
18616 SourceLocation LParenLoc,
18617 SourceLocation VarLoc,
18618 SourceLocation EndLoc) {
18619 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
18620 DSAStack->getCurrentDirective() == OMPD_depobj) {
18621 unsigned OMPVersion = getLangOpts().OpenMP;
18622 Diag(StartLoc, diag::err_omp_expected_clause_argument)
18623 << getOpenMPClauseNameForDiag(OMPC_destroy)
18624 << getOpenMPDirectiveName(OMPD_depobj, OMPVersion);
18625 return nullptr;
18626 }
18627 if (InteropVar &&
18628 !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy))
18629 return nullptr;
18630
18631 return new (getASTContext())
18632 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18633}
18634
18636 SourceLocation StartLoc,
18637 SourceLocation LParenLoc,
18638 SourceLocation EndLoc) {
18639 Expr *ValExpr = Condition;
18640 Stmt *HelperValStmt = nullptr;
18641 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18642 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18643 !Condition->isInstantiationDependent() &&
18644 !Condition->containsUnexpandedParameterPack()) {
18645 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
18646 if (Val.isInvalid())
18647 return nullptr;
18648
18649 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
18650
18651 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18652 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
18653 getLangOpts().OpenMP);
18654 if (CaptureRegion != OMPD_unknown &&
18655 !SemaRef.CurContext->isDependentContext()) {
18656 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18657 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18658 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18659 HelperValStmt = buildPreInits(getASTContext(), Captures);
18660 }
18661 }
18662
18663 return new (getASTContext()) OMPNovariantsClause(
18664 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18665}
18666
18668 SourceLocation StartLoc,
18669 SourceLocation LParenLoc,
18670 SourceLocation EndLoc) {
18671 Expr *ValExpr = Condition;
18672 Stmt *HelperValStmt = nullptr;
18673 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18674 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18675 !Condition->isInstantiationDependent() &&
18676 !Condition->containsUnexpandedParameterPack()) {
18677 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
18678 if (Val.isInvalid())
18679 return nullptr;
18680
18681 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
18682
18683 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18684 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext,
18685 getLangOpts().OpenMP);
18686 if (CaptureRegion != OMPD_unknown &&
18687 !SemaRef.CurContext->isDependentContext()) {
18688 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18689 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18690 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18691 HelperValStmt = buildPreInits(getASTContext(), Captures);
18692 }
18693 }
18694
18695 return new (getASTContext()) OMPNocontextClause(
18696 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18697}
18698
18700 SourceLocation StartLoc,
18701 SourceLocation LParenLoc,
18702 SourceLocation EndLoc) {
18703 Expr *ValExpr = ThreadID;
18704 Stmt *HelperValStmt = nullptr;
18705
18706 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18707 OpenMPDirectiveKind CaptureRegion =
18708 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP);
18709 if (CaptureRegion != OMPD_unknown &&
18710 !SemaRef.CurContext->isDependentContext()) {
18711 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18712 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18713 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18714 HelperValStmt = buildPreInits(getASTContext(), Captures);
18715 }
18716
18717 return new (getASTContext()) OMPFilterClause(
18718 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18719}
18720
18722 ArrayRef<Expr *> VarList,
18723 const OMPVarListLocTy &Locs,
18725 SourceLocation StartLoc = Locs.StartLoc;
18726 SourceLocation LParenLoc = Locs.LParenLoc;
18727 SourceLocation EndLoc = Locs.EndLoc;
18728 OMPClause *Res = nullptr;
18729 int ExtraModifier = Data.ExtraModifier;
18730 int OriginalSharingModifier = Data.OriginalSharingModifier;
18731 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
18732 SourceLocation ColonLoc = Data.ColonLoc;
18733 switch (Kind) {
18734 case OMPC_private:
18735 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18736 break;
18737 case OMPC_firstprivate:
18738 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18739 break;
18740 case OMPC_lastprivate:
18741 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
18742 "Unexpected lastprivate modifier.");
18744 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
18745 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
18746 break;
18747 case OMPC_shared:
18748 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
18749 break;
18750 case OMPC_reduction:
18751 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
18752 "Unexpected lastprivate modifier.");
18754 VarList,
18756 ExtraModifier, OriginalSharingModifier),
18757 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
18758 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18759 break;
18760 case OMPC_task_reduction:
18762 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18763 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18764 break;
18765 case OMPC_in_reduction:
18767 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18768 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18769 break;
18770 case OMPC_linear:
18771 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
18772 "Unexpected linear modifier.");
18774 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
18775 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
18776 ColonLoc, Data.StepModifierLoc, EndLoc);
18777 break;
18778 case OMPC_aligned:
18779 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
18780 LParenLoc, ColonLoc, EndLoc);
18781 break;
18782 case OMPC_copyin:
18783 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
18784 break;
18785 case OMPC_copyprivate:
18786 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18787 break;
18788 case OMPC_flush:
18789 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
18790 break;
18791 case OMPC_depend:
18792 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
18793 "Unexpected depend modifier.");
18795 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
18796 ColonLoc, Data.OmpAllMemoryLoc},
18797 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
18798 break;
18799 case OMPC_map:
18800 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
18801 "Unexpected map modifier.");
18803 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
18804 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
18805 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
18806 ExtraModifierLoc, ColonLoc, VarList, Locs);
18807 break;
18808 case OMPC_to:
18809 Res = ActOnOpenMPToClause(
18810 Data.MotionModifiers, Data.MotionModifiersLoc, Data.IteratorExpr,
18811 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, ColonLoc,
18812 VarList, Locs);
18813 break;
18814 case OMPC_from:
18816 Data.MotionModifiers, Data.MotionModifiersLoc, Data.IteratorExpr,
18817 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, ColonLoc,
18818 VarList, Locs);
18819 break;
18820 case OMPC_use_device_ptr:
18821 assert(0 <= Data.ExtraModifier &&
18822 Data.ExtraModifier <= OMPC_USE_DEVICE_PTR_FALLBACK_unknown &&
18823 "Unexpected use_device_ptr fallback modifier.");
18825 VarList, Locs,
18826 static_cast<OpenMPUseDevicePtrFallbackModifier>(Data.ExtraModifier),
18827 Data.ExtraModifierLoc);
18828 break;
18829 case OMPC_use_device_addr:
18830 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
18831 break;
18832 case OMPC_is_device_ptr:
18833 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
18834 break;
18835 case OMPC_has_device_addr:
18836 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
18837 break;
18838 case OMPC_allocate: {
18841 SourceLocation Modifier1Loc, Modifier2Loc;
18842 if (!Data.AllocClauseModifiers.empty()) {
18843 assert(Data.AllocClauseModifiers.size() <= 2 &&
18844 "More allocate modifiers than expected");
18845 Modifier1 = Data.AllocClauseModifiers[0];
18846 Modifier1Loc = Data.AllocClauseModifiersLoc[0];
18847 if (Data.AllocClauseModifiers.size() == 2) {
18848 Modifier2 = Data.AllocClauseModifiers[1];
18849 Modifier2Loc = Data.AllocClauseModifiersLoc[1];
18850 }
18851 }
18853 Data.DepModOrTailExpr, Data.AllocateAlignment, Modifier1, Modifier1Loc,
18854 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
18855 EndLoc);
18856 break;
18857 }
18858 case OMPC_nontemporal:
18859 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
18860 break;
18861 case OMPC_inclusive:
18862 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18863 break;
18864 case OMPC_exclusive:
18865 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18866 break;
18867 case OMPC_affinity:
18868 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
18869 Data.DepModOrTailExpr, VarList);
18870 break;
18871 case OMPC_doacross:
18873 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
18874 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
18875 break;
18876 case OMPC_num_teams:
18877 Res = ActOnOpenMPNumTeamsClause(VarList, StartLoc, LParenLoc, EndLoc);
18878 break;
18879 case OMPC_thread_limit:
18880 Res = ActOnOpenMPThreadLimitClause(VarList, StartLoc, LParenLoc, EndLoc);
18881 break;
18882 case OMPC_if:
18883 case OMPC_depobj:
18884 case OMPC_final:
18885 case OMPC_num_threads:
18886 case OMPC_safelen:
18887 case OMPC_simdlen:
18888 case OMPC_sizes:
18889 case OMPC_allocator:
18890 case OMPC_collapse:
18891 case OMPC_default:
18892 case OMPC_proc_bind:
18893 case OMPC_schedule:
18894 case OMPC_ordered:
18895 case OMPC_nowait:
18896 case OMPC_untied:
18897 case OMPC_mergeable:
18898 case OMPC_threadprivate:
18899 case OMPC_groupprivate:
18900 case OMPC_read:
18901 case OMPC_write:
18902 case OMPC_update:
18903 case OMPC_capture:
18904 case OMPC_compare:
18905 case OMPC_seq_cst:
18906 case OMPC_acq_rel:
18907 case OMPC_acquire:
18908 case OMPC_release:
18909 case OMPC_relaxed:
18910 case OMPC_device:
18911 case OMPC_threads:
18912 case OMPC_simd:
18913 case OMPC_priority:
18914 case OMPC_grainsize:
18915 case OMPC_nogroup:
18916 case OMPC_num_tasks:
18917 case OMPC_hint:
18918 case OMPC_dist_schedule:
18919 case OMPC_defaultmap:
18920 case OMPC_unknown:
18921 case OMPC_uniform:
18922 case OMPC_unified_address:
18923 case OMPC_unified_shared_memory:
18924 case OMPC_reverse_offload:
18925 case OMPC_dynamic_allocators:
18926 case OMPC_atomic_default_mem_order:
18927 case OMPC_self_maps:
18928 case OMPC_device_type:
18929 case OMPC_match:
18930 case OMPC_order:
18931 case OMPC_at:
18932 case OMPC_severity:
18933 case OMPC_message:
18934 case OMPC_destroy:
18935 case OMPC_novariants:
18936 case OMPC_nocontext:
18937 case OMPC_detach:
18938 case OMPC_uses_allocators:
18939 case OMPC_when:
18940 case OMPC_bind:
18941 default:
18942 llvm_unreachable("Clause is not allowed.");
18943 }
18944 return Res;
18945}
18946
18948 ExprObjectKind OK,
18949 SourceLocation Loc) {
18950 ExprResult Res = SemaRef.BuildDeclRefExpr(
18951 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
18952 if (!Res.isUsable())
18953 return ExprError();
18954 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
18955 Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
18956 if (!Res.isUsable())
18957 return ExprError();
18958 }
18959 if (VK != VK_LValue && Res.get()->isGLValue()) {
18960 Res = SemaRef.DefaultLvalueConversion(Res.get());
18961 if (!Res.isUsable())
18962 return ExprError();
18963 }
18964 return Res;
18965}
18966
18968 SourceLocation StartLoc,
18969 SourceLocation LParenLoc,
18970 SourceLocation EndLoc) {
18972 SmallVector<Expr *, 8> PrivateCopies;
18973 unsigned OMPVersion = getLangOpts().OpenMP;
18974 bool IsImplicitClause =
18975 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18976 for (Expr *RefExpr : VarList) {
18977 assert(RefExpr && "NULL expr in OpenMP private clause.");
18978 SourceLocation ELoc;
18979 SourceRange ERange;
18980 Expr *SimpleRefExpr = RefExpr;
18981 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
18982 if (Res.second) {
18983 // It will be analyzed later.
18984 Vars.push_back(RefExpr);
18985 PrivateCopies.push_back(nullptr);
18986 }
18987 ValueDecl *D = Res.first;
18988 if (!D)
18989 continue;
18990
18991 QualType Type = D->getType();
18992 auto *VD = dyn_cast<VarDecl>(D);
18993
18994 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18995 // A variable that appears in a private clause must not have an incomplete
18996 // type or a reference type.
18997 if (SemaRef.RequireCompleteType(ELoc, Type,
18998 diag::err_omp_private_incomplete_type))
18999 continue;
19000 Type = Type.getNonReferenceType();
19001
19002 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19003 // A variable that is privatized must not have a const-qualified type
19004 // unless it is of class type with a mutable member. This restriction does
19005 // not apply to the firstprivate clause.
19006 //
19007 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
19008 // A variable that appears in a private clause must not have a
19009 // const-qualified type unless it is of class type with a mutable member.
19010 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc))
19011 continue;
19012
19013 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19014 // in a Construct]
19015 // Variables with the predetermined data-sharing attributes may not be
19016 // listed in data-sharing attributes clauses, except for the cases
19017 // listed below. For these exceptions only, listing a predetermined
19018 // variable in a data-sharing attribute clause is allowed and overrides
19019 // the variable's predetermined data-sharing attributes.
19020 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19021 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
19022 Diag(ELoc, diag::err_omp_wrong_dsa)
19023 << getOpenMPClauseNameForDiag(DVar.CKind)
19024 << getOpenMPClauseNameForDiag(OMPC_private);
19026 continue;
19027 }
19028
19029 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19030 // Variably modified types are not supported for tasks.
19032 isOpenMPTaskingDirective(CurrDir)) {
19033 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19034 << getOpenMPClauseNameForDiag(OMPC_private) << Type
19035 << getOpenMPDirectiveName(CurrDir, OMPVersion);
19036 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19038 Diag(D->getLocation(),
19039 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19040 << D;
19041 continue;
19042 }
19043
19044 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
19045 // A list item cannot appear in both a map clause and a data-sharing
19046 // attribute clause on the same construct
19047 //
19048 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
19049 // A list item cannot appear in both a map clause and a data-sharing
19050 // attribute clause on the same construct unless the construct is a
19051 // combined construct.
19052 if ((getLangOpts().OpenMP <= 45 &&
19054 CurrDir == OMPD_target) {
19055 OpenMPClauseKind ConflictKind;
19056 if (DSAStack->checkMappableExprComponentListsForDecl(
19057 VD, /*CurrentRegionOnly=*/true,
19059 OpenMPClauseKind WhereFoundClauseKind) -> bool {
19060 ConflictKind = WhereFoundClauseKind;
19061 return true;
19062 })) {
19063 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
19064 << getOpenMPClauseNameForDiag(OMPC_private)
19065 << getOpenMPClauseNameForDiag(ConflictKind)
19066 << getOpenMPDirectiveName(CurrDir, OMPVersion);
19068 continue;
19069 }
19070 }
19071
19072 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
19073 // A variable of class type (or array thereof) that appears in a private
19074 // clause requires an accessible, unambiguous default constructor for the
19075 // class type.
19076 // Generate helper private variable and initialize it with the default
19077 // value. The address of the original variable is replaced by the address of
19078 // the new private variable in CodeGen. This new variable is not added to
19079 // IdResolver, so the code in the OpenMP region uses original variable for
19080 // proper diagnostics.
19081 Type = Type.getUnqualifiedType();
19082 VarDecl *VDPrivate =
19083 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
19084 D->hasAttrs() ? &D->getAttrs() : nullptr,
19085 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19086 SemaRef.ActOnUninitializedDecl(VDPrivate);
19087 if (VDPrivate->isInvalidDecl())
19088 continue;
19089 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
19090 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
19091
19092 DeclRefExpr *Ref = nullptr;
19093 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19094 auto *FD = dyn_cast<FieldDecl>(D);
19095 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
19096 if (VD)
19098 RefExpr->getExprLoc());
19099 else
19100 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19101 }
19102 if (!IsImplicitClause)
19103 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
19104 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19105 ? RefExpr->IgnoreParens()
19106 : Ref);
19107 PrivateCopies.push_back(VDPrivateRefExpr);
19108 }
19109
19110 if (Vars.empty())
19111 return nullptr;
19112
19113 return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19114 Vars, PrivateCopies);
19115}
19116
19118 SourceLocation StartLoc,
19119 SourceLocation LParenLoc,
19120 SourceLocation EndLoc) {
19122 SmallVector<Expr *, 8> PrivateCopies;
19124 SmallVector<Decl *, 4> ExprCaptures;
19125 bool IsImplicitClause =
19126 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
19127 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
19128 unsigned OMPVersion = getLangOpts().OpenMP;
19129
19130 for (Expr *RefExpr : VarList) {
19131 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
19132 SourceLocation ELoc;
19133 SourceRange ERange;
19134 Expr *SimpleRefExpr = RefExpr;
19135 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19136 if (Res.second) {
19137 // It will be analyzed later.
19138 Vars.push_back(RefExpr);
19139 PrivateCopies.push_back(nullptr);
19140 Inits.push_back(nullptr);
19141 }
19142 ValueDecl *D = Res.first;
19143 if (!D)
19144 continue;
19145
19146 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
19147 QualType Type = D->getType();
19148 auto *VD = dyn_cast<VarDecl>(D);
19149
19150 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19151 // A variable that appears in a private clause must not have an incomplete
19152 // type or a reference type.
19153 if (SemaRef.RequireCompleteType(ELoc, Type,
19154 diag::err_omp_firstprivate_incomplete_type))
19155 continue;
19156 Type = Type.getNonReferenceType();
19157
19158 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
19159 // A variable of class type (or array thereof) that appears in a private
19160 // clause requires an accessible, unambiguous copy constructor for the
19161 // class type.
19162 QualType ElemType =
19164
19165 // If an implicit firstprivate variable found it was checked already.
19166 DSAStackTy::DSAVarData TopDVar;
19167 if (!IsImplicitClause) {
19168 DSAStackTy::DSAVarData DVar =
19169 DSAStack->getTopDSA(D, /*FromParent=*/false);
19170 TopDVar = DVar;
19171 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19172 bool IsConstant = ElemType.isConstant(getASTContext());
19173 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
19174 // A list item that specifies a given variable may not appear in more
19175 // than one clause on the same directive, except that a variable may be
19176 // specified in both firstprivate and lastprivate clauses.
19177 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
19178 // A list item may appear in a firstprivate or lastprivate clause but not
19179 // both.
19180 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
19181 (isOpenMPDistributeDirective(CurrDir) ||
19182 DVar.CKind != OMPC_lastprivate) &&
19183 DVar.RefExpr) {
19184 Diag(ELoc, diag::err_omp_wrong_dsa)
19185 << getOpenMPClauseNameForDiag(DVar.CKind)
19186 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
19188 continue;
19189 }
19190
19191 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19192 // in a Construct]
19193 // Variables with the predetermined data-sharing attributes may not be
19194 // listed in data-sharing attributes clauses, except for the cases
19195 // listed below. For these exceptions only, listing a predetermined
19196 // variable in a data-sharing attribute clause is allowed and overrides
19197 // the variable's predetermined data-sharing attributes.
19198 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19199 // in a Construct, C/C++, p.2]
19200 // Variables with const-qualified type having no mutable member may be
19201 // listed in a firstprivate clause, even if they are static data members.
19202 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
19203 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
19204 Diag(ELoc, diag::err_omp_wrong_dsa)
19205 << getOpenMPClauseNameForDiag(DVar.CKind)
19206 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
19208 continue;
19209 }
19210
19211 // OpenMP [2.9.3.4, Restrictions, p.2]
19212 // A list item that is private within a parallel region must not appear
19213 // in a firstprivate clause on a worksharing construct if any of the
19214 // worksharing regions arising from the worksharing construct ever bind
19215 // to any of the parallel regions arising from the parallel construct.
19216 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
19217 // A list item that is private within a teams region must not appear in a
19218 // firstprivate clause on a distribute construct if any of the distribute
19219 // regions arising from the distribute construct ever bind to any of the
19220 // teams regions arising from the teams construct.
19221 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
19222 // A list item that appears in a reduction clause of a teams construct
19223 // must not appear in a firstprivate clause on a distribute construct if
19224 // any of the distribute regions arising from the distribute construct
19225 // ever bind to any of the teams regions arising from the teams construct.
19226 if ((isOpenMPWorksharingDirective(CurrDir) ||
19227 isOpenMPDistributeDirective(CurrDir)) &&
19228 !isOpenMPParallelDirective(CurrDir) &&
19229 !isOpenMPTeamsDirective(CurrDir)) {
19230 DVar = DSAStack->getImplicitDSA(D, true);
19231 if (DVar.CKind != OMPC_shared &&
19232 (isOpenMPParallelDirective(DVar.DKind) ||
19233 isOpenMPTeamsDirective(DVar.DKind) ||
19234 DVar.DKind == OMPD_unknown)) {
19235 Diag(ELoc, diag::err_omp_required_access)
19236 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
19237 << getOpenMPClauseNameForDiag(OMPC_shared);
19239 continue;
19240 }
19241 }
19242 // OpenMP [2.9.3.4, Restrictions, p.3]
19243 // A list item that appears in a reduction clause of a parallel construct
19244 // must not appear in a firstprivate clause on a worksharing or task
19245 // construct if any of the worksharing or task regions arising from the
19246 // worksharing or task construct ever bind to any of the parallel regions
19247 // arising from the parallel construct.
19248 // OpenMP [2.9.3.4, Restrictions, p.4]
19249 // A list item that appears in a reduction clause in worksharing
19250 // construct must not appear in a firstprivate clause in a task construct
19251 // encountered during execution of any of the worksharing regions arising
19252 // from the worksharing construct.
19253 if (isOpenMPTaskingDirective(CurrDir)) {
19254 DVar = DSAStack->hasInnermostDSA(
19255 D,
19256 [](OpenMPClauseKind C, bool AppliedToPointee) {
19257 return C == OMPC_reduction && !AppliedToPointee;
19258 },
19259 [](OpenMPDirectiveKind K) {
19260 return isOpenMPParallelDirective(K) ||
19263 },
19264 /*FromParent=*/true);
19265 if (DVar.CKind == OMPC_reduction &&
19266 (isOpenMPParallelDirective(DVar.DKind) ||
19267 isOpenMPWorksharingDirective(DVar.DKind) ||
19268 isOpenMPTeamsDirective(DVar.DKind))) {
19269 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
19270 << getOpenMPDirectiveName(DVar.DKind, OMPVersion);
19272 continue;
19273 }
19274 }
19275
19276 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
19277 // A list item cannot appear in both a map clause and a data-sharing
19278 // attribute clause on the same construct
19279 //
19280 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
19281 // A list item cannot appear in both a map clause and a data-sharing
19282 // attribute clause on the same construct unless the construct is a
19283 // combined construct.
19284 if ((getLangOpts().OpenMP <= 45 &&
19286 CurrDir == OMPD_target) {
19287 OpenMPClauseKind ConflictKind;
19288 if (DSAStack->checkMappableExprComponentListsForDecl(
19289 VD, /*CurrentRegionOnly=*/true,
19290 [&ConflictKind](
19292 OpenMPClauseKind WhereFoundClauseKind) {
19293 ConflictKind = WhereFoundClauseKind;
19294 return true;
19295 })) {
19296 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
19297 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
19298 << getOpenMPClauseNameForDiag(ConflictKind)
19299 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
19300 OMPVersion);
19302 continue;
19303 }
19304 }
19305 }
19306
19307 // Variably modified types are not supported for tasks.
19309 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
19310 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19311 << getOpenMPClauseNameForDiag(OMPC_firstprivate) << Type
19312 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
19313 OMPVersion);
19314 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19316 Diag(D->getLocation(),
19317 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19318 << D;
19319 continue;
19320 }
19321
19322 Type = Type.getUnqualifiedType();
19323 VarDecl *VDPrivate =
19324 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
19325 D->hasAttrs() ? &D->getAttrs() : nullptr,
19326 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19327 // Generate helper private variable and initialize it with the value of the
19328 // original variable. The address of the original variable is replaced by
19329 // the address of the new private variable in the CodeGen. This new variable
19330 // is not added to IdResolver, so the code in the OpenMP region uses
19331 // original variable for proper diagnostics and variable capturing.
19332 Expr *VDInitRefExpr = nullptr;
19333 // For arrays generate initializer for single element and replace it by the
19334 // original array element in CodeGen.
19335 if (Type->isArrayType()) {
19336 VarDecl *VDInit =
19337 buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName());
19338 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc);
19339 Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get();
19340 ElemType = ElemType.getUnqualifiedType();
19341 VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(),
19342 ElemType, ".firstprivate.temp");
19343 InitializedEntity Entity =
19346
19347 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
19348 ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init);
19349 if (Result.isInvalid())
19350 VDPrivate->setInvalidDecl();
19351 else
19352 VDPrivate->setInit(Result.getAs<Expr>());
19353 // Remove temp variable declaration.
19354 getASTContext().Deallocate(VDInitTemp);
19355 } else {
19356 VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type,
19357 ".firstprivate.temp");
19358 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(),
19359 RefExpr->getExprLoc());
19360 SemaRef.AddInitializerToDecl(
19361 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
19362 /*DirectInit=*/false);
19363 }
19364 if (VDPrivate->isInvalidDecl()) {
19365 if (IsImplicitClause) {
19366 Diag(RefExpr->getExprLoc(),
19367 diag::note_omp_task_predetermined_firstprivate_here);
19368 }
19369 continue;
19370 }
19371 SemaRef.CurContext->addDecl(VDPrivate);
19372 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
19373 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(),
19374 RefExpr->getExprLoc());
19375 DeclRefExpr *Ref = nullptr;
19376 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19377 if (TopDVar.CKind == OMPC_lastprivate) {
19378 Ref = TopDVar.PrivateCopy;
19379 } else {
19380 auto *FD = dyn_cast<FieldDecl>(D);
19381 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
19382 if (VD)
19383 Ref =
19385 RefExpr->getExprLoc());
19386 else
19387 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19388 if (VD || !isOpenMPCapturedDecl(D))
19389 ExprCaptures.push_back(Ref->getDecl());
19390 }
19391 }
19392 if (!IsImplicitClause)
19393 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
19394 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19395 ? RefExpr->IgnoreParens()
19396 : Ref);
19397 PrivateCopies.push_back(VDPrivateRefExpr);
19398 Inits.push_back(VDInitRefExpr);
19399 }
19400
19401 if (Vars.empty())
19402 return nullptr;
19403
19404 return OMPFirstprivateClause::Create(
19405 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
19406 buildPreInits(getASTContext(), ExprCaptures));
19407}
19408
19411 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
19412 SourceLocation LParenLoc, SourceLocation EndLoc) {
19413 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
19414 assert(ColonLoc.isValid() && "Colon location must be valid.");
19415 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
19416 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
19417 /*Last=*/OMPC_LASTPRIVATE_unknown)
19418 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
19419 return nullptr;
19420 }
19421
19423 SmallVector<Expr *, 8> SrcExprs;
19424 SmallVector<Expr *, 8> DstExprs;
19425 SmallVector<Expr *, 8> AssignmentOps;
19426 SmallVector<Decl *, 4> ExprCaptures;
19427 SmallVector<Expr *, 4> ExprPostUpdates;
19428 for (Expr *RefExpr : VarList) {
19429 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
19430 SourceLocation ELoc;
19431 SourceRange ERange;
19432 Expr *SimpleRefExpr = RefExpr;
19433 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19434 if (Res.second) {
19435 // It will be analyzed later.
19436 Vars.push_back(RefExpr);
19437 SrcExprs.push_back(nullptr);
19438 DstExprs.push_back(nullptr);
19439 AssignmentOps.push_back(nullptr);
19440 }
19441 ValueDecl *D = Res.first;
19442 if (!D)
19443 continue;
19444
19445 QualType Type = D->getType();
19446 auto *VD = dyn_cast<VarDecl>(D);
19447
19448 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
19449 // A variable that appears in a lastprivate clause must not have an
19450 // incomplete type or a reference type.
19451 if (SemaRef.RequireCompleteType(ELoc, Type,
19452 diag::err_omp_lastprivate_incomplete_type))
19453 continue;
19454 Type = Type.getNonReferenceType();
19455
19456 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19457 // A variable that is privatized must not have a const-qualified type
19458 // unless it is of class type with a mutable member. This restriction does
19459 // not apply to the firstprivate clause.
19460 //
19461 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
19462 // A variable that appears in a lastprivate clause must not have a
19463 // const-qualified type unless it is of class type with a mutable member.
19464 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc))
19465 continue;
19466
19467 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
19468 // A list item that appears in a lastprivate clause with the conditional
19469 // modifier must be a scalar variable.
19470 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
19471 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
19472 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19474 Diag(D->getLocation(),
19475 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19476 << D;
19477 continue;
19478 }
19479
19480 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19481 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19482 // in a Construct]
19483 // Variables with the predetermined data-sharing attributes may not be
19484 // listed in data-sharing attributes clauses, except for the cases
19485 // listed below.
19486 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
19487 // A list item may appear in a firstprivate or lastprivate clause but not
19488 // both.
19489 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19490 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
19491 (isOpenMPDistributeDirective(CurrDir) ||
19492 DVar.CKind != OMPC_firstprivate) &&
19493 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
19494 Diag(ELoc, diag::err_omp_wrong_dsa)
19495 << getOpenMPClauseNameForDiag(DVar.CKind)
19496 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
19498 continue;
19499 }
19500
19501 // OpenMP [2.14.3.5, Restrictions, p.2]
19502 // A list item that is private within a parallel region, or that appears in
19503 // the reduction clause of a parallel construct, must not appear in a
19504 // lastprivate clause on a worksharing construct if any of the corresponding
19505 // worksharing regions ever binds to any of the corresponding parallel
19506 // regions.
19507 DSAStackTy::DSAVarData TopDVar = DVar;
19508 if (isOpenMPWorksharingDirective(CurrDir) &&
19509 !isOpenMPParallelDirective(CurrDir) &&
19510 !isOpenMPTeamsDirective(CurrDir)) {
19511 DVar = DSAStack->getImplicitDSA(D, true);
19512 if (DVar.CKind != OMPC_shared) {
19513 Diag(ELoc, diag::err_omp_required_access)
19514 << getOpenMPClauseNameForDiag(OMPC_lastprivate)
19515 << getOpenMPClauseNameForDiag(OMPC_shared);
19517 continue;
19518 }
19519 }
19520
19521 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
19522 // A variable of class type (or array thereof) that appears in a
19523 // lastprivate clause requires an accessible, unambiguous default
19524 // constructor for the class type, unless the list item is also specified
19525 // in a firstprivate clause.
19526 // A variable of class type (or array thereof) that appears in a
19527 // lastprivate clause requires an accessible, unambiguous copy assignment
19528 // operator for the class type.
19530 VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(),
19531 Type.getUnqualifiedType(), ".lastprivate.src",
19532 D->hasAttrs() ? &D->getAttrs() : nullptr);
19533 DeclRefExpr *PseudoSrcExpr =
19534 buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc);
19535 VarDecl *DstVD =
19536 buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst",
19537 D->hasAttrs() ? &D->getAttrs() : nullptr);
19538 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
19539 // For arrays generate assignment operation for single element and replace
19540 // it by the original array element in CodeGen.
19541 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
19542 PseudoDstExpr, PseudoSrcExpr);
19543 if (AssignmentOp.isInvalid())
19544 continue;
19545 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
19546 /*DiscardedValue=*/false);
19547 if (AssignmentOp.isInvalid())
19548 continue;
19549
19550 DeclRefExpr *Ref = nullptr;
19551 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19552 if (TopDVar.CKind == OMPC_firstprivate) {
19553 Ref = TopDVar.PrivateCopy;
19554 } else {
19555 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19556 if (!isOpenMPCapturedDecl(D))
19557 ExprCaptures.push_back(Ref->getDecl());
19558 }
19559 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
19560 (!isOpenMPCapturedDecl(D) &&
19561 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
19562 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
19563 if (!RefRes.isUsable())
19564 continue;
19565 ExprResult PostUpdateRes =
19566 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
19567 SimpleRefExpr, RefRes.get());
19568 if (!PostUpdateRes.isUsable())
19569 continue;
19570 ExprPostUpdates.push_back(
19571 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
19572 }
19573 }
19574 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
19575 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19576 ? RefExpr->IgnoreParens()
19577 : Ref);
19578 SrcExprs.push_back(PseudoSrcExpr);
19579 DstExprs.push_back(PseudoDstExpr);
19580 AssignmentOps.push_back(AssignmentOp.get());
19581 }
19582
19583 if (Vars.empty())
19584 return nullptr;
19585
19586 return OMPLastprivateClause::Create(
19587 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
19588 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
19589 buildPreInits(getASTContext(), ExprCaptures),
19590 buildPostUpdate(SemaRef, ExprPostUpdates));
19591}
19592
19594 SourceLocation StartLoc,
19595 SourceLocation LParenLoc,
19596 SourceLocation EndLoc) {
19598 for (Expr *RefExpr : VarList) {
19599 assert(RefExpr && "NULL expr in OpenMP shared clause.");
19600 SourceLocation ELoc;
19601 SourceRange ERange;
19602 Expr *SimpleRefExpr = RefExpr;
19603 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19604 if (Res.second) {
19605 // It will be analyzed later.
19606 Vars.push_back(RefExpr);
19607 }
19608 ValueDecl *D = Res.first;
19609 if (!D)
19610 continue;
19611
19612 auto *VD = dyn_cast<VarDecl>(D);
19613 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19614 // in a Construct]
19615 // Variables with the predetermined data-sharing attributes may not be
19616 // listed in data-sharing attributes clauses, except for the cases
19617 // listed below. For these exceptions only, listing a predetermined
19618 // variable in a data-sharing attribute clause is allowed and overrides
19619 // the variable's predetermined data-sharing attributes.
19620 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19621 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
19622 DVar.RefExpr) {
19623 Diag(ELoc, diag::err_omp_wrong_dsa)
19624 << getOpenMPClauseNameForDiag(DVar.CKind)
19625 << getOpenMPClauseNameForDiag(OMPC_shared);
19627 continue;
19628 }
19629
19630 DeclRefExpr *Ref = nullptr;
19631 if (!VD && isOpenMPCapturedDecl(D) &&
19632 !SemaRef.CurContext->isDependentContext())
19633 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19634 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
19635 Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext())
19636 ? RefExpr->IgnoreParens()
19637 : Ref);
19638 }
19639
19640 if (Vars.empty())
19641 return nullptr;
19642
19643 return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19644 Vars);
19645}
19646
19647namespace {
19648class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
19649 DSAStackTy *Stack;
19650
19651public:
19652 bool VisitDeclRefExpr(DeclRefExpr *E) {
19653 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
19654 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
19655 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
19656 return false;
19657 if (DVar.CKind != OMPC_unknown)
19658 return true;
19659 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
19660 VD,
19661 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
19662 return isOpenMPPrivate(C) && !AppliedToPointee;
19663 },
19664 [](OpenMPDirectiveKind) { return true; },
19665 /*FromParent=*/true);
19666 return DVarPrivate.CKind != OMPC_unknown;
19667 }
19668 return false;
19669 }
19670 bool VisitStmt(Stmt *S) {
19671 for (Stmt *Child : S->children()) {
19672 if (Child && Visit(Child))
19673 return true;
19674 }
19675 return false;
19676 }
19677 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
19678};
19679} // namespace
19680
19681namespace {
19682// Transform MemberExpression for specified FieldDecl of current class to
19683// DeclRefExpr to specified OMPCapturedExprDecl.
19684class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
19685 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
19686 ValueDecl *Field = nullptr;
19687 DeclRefExpr *CapturedExpr = nullptr;
19688
19689public:
19690 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
19691 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
19692
19693 ExprResult TransformMemberExpr(MemberExpr *E) {
19695 E->getMemberDecl() == Field) {
19696 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
19697 return CapturedExpr;
19698 }
19699 return BaseTransform::TransformMemberExpr(E);
19700 }
19701 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
19702};
19703} // namespace
19704
19705template <typename T, typename U>
19707 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
19708 for (U &Set : Lookups) {
19709 for (auto *D : Set) {
19710 if (T Res = Gen(cast<ValueDecl>(D)))
19711 return Res;
19712 }
19713 }
19714 return T();
19715}
19716
19718 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
19719
19720 for (auto *RD : D->redecls()) {
19721 // Don't bother with extra checks if we already know this one isn't visible.
19722 if (RD == D)
19723 continue;
19724
19725 auto ND = cast<NamedDecl>(RD);
19726 if (LookupResult::isVisible(SemaRef, ND))
19727 return ND;
19728 }
19729
19730 return nullptr;
19731}
19732
19733static void
19735 SourceLocation Loc, QualType Ty,
19737 // Find all of the associated namespaces and classes based on the
19738 // arguments we have.
19739 Sema::AssociatedNamespaceSet AssociatedNamespaces;
19740 Sema::AssociatedClassSet AssociatedClasses;
19741 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
19742 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
19743 AssociatedClasses);
19744
19745 // C++ [basic.lookup.argdep]p3:
19746 // Let X be the lookup set produced by unqualified lookup (3.4.1)
19747 // and let Y be the lookup set produced by argument dependent
19748 // lookup (defined as follows). If X contains [...] then Y is
19749 // empty. Otherwise Y is the set of declarations found in the
19750 // namespaces associated with the argument types as described
19751 // below. The set of declarations found by the lookup of the name
19752 // is the union of X and Y.
19753 //
19754 // Here, we compute Y and add its members to the overloaded
19755 // candidate set.
19756 for (auto *NS : AssociatedNamespaces) {
19757 // When considering an associated namespace, the lookup is the
19758 // same as the lookup performed when the associated namespace is
19759 // used as a qualifier (3.4.3.2) except that:
19760 //
19761 // -- Any using-directives in the associated namespace are
19762 // ignored.
19763 //
19764 // -- Any namespace-scope friend functions declared in
19765 // associated classes are visible within their respective
19766 // namespaces even if they are not visible during an ordinary
19767 // lookup (11.4).
19768 DeclContext::lookup_result R = NS->lookup(Id.getName());
19769 for (auto *D : R) {
19770 auto *Underlying = D;
19771 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19772 Underlying = USD->getTargetDecl();
19773
19774 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
19775 !isa<OMPDeclareMapperDecl>(Underlying))
19776 continue;
19777
19778 if (!SemaRef.isVisible(D)) {
19779 D = findAcceptableDecl(SemaRef, D);
19780 if (!D)
19781 continue;
19782 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19783 Underlying = USD->getTargetDecl();
19784 }
19785 Lookups.emplace_back();
19786 Lookups.back().addDecl(Underlying);
19787 }
19788 }
19789}
19790
19791static ExprResult
19793 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
19794 const DeclarationNameInfo &ReductionId, QualType Ty,
19795 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
19796 if (ReductionIdScopeSpec.isInvalid())
19797 return ExprError();
19798 SmallVector<UnresolvedSet<8>, 4> Lookups;
19799 if (S) {
19800 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19801 Lookup.suppressDiagnostics();
19802 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec,
19803 /*ObjectType=*/QualType())) {
19804 NamedDecl *D = Lookup.getRepresentativeDecl();
19805 do {
19806 S = S->getParent();
19807 } while (S && !S->isDeclScope(D));
19808 if (S)
19809 S = S->getParent();
19810 Lookups.emplace_back();
19811 Lookups.back().append(Lookup.begin(), Lookup.end());
19812 Lookup.clear();
19813 }
19814 } else if (auto *ULE =
19815 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
19816 Lookups.push_back(UnresolvedSet<8>());
19817 Decl *PrevD = nullptr;
19818 for (NamedDecl *D : ULE->decls()) {
19819 if (D == PrevD)
19820 Lookups.push_back(UnresolvedSet<8>());
19821 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
19822 Lookups.back().addDecl(DRD);
19823 PrevD = D;
19824 }
19825 }
19826 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
19830 return !D->isInvalidDecl() &&
19831 (D->getType()->isDependentType() ||
19832 D->getType()->isInstantiationDependentType() ||
19833 D->getType()->containsUnexpandedParameterPack());
19834 })) {
19835 UnresolvedSet<8> ResSet;
19836 for (const UnresolvedSet<8> &Set : Lookups) {
19837 if (Set.empty())
19838 continue;
19839 ResSet.append(Set.begin(), Set.end());
19840 // The last item marks the end of all declarations at the specified scope.
19841 ResSet.addDecl(Set[Set.size() - 1]);
19842 }
19844 SemaRef.Context, /*NamingClass=*/nullptr,
19845 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
19846 /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false,
19847 /*KnownInstantiationDependent=*/false);
19848 }
19849 // Lookup inside the classes.
19850 // C++ [over.match.oper]p3:
19851 // For a unary operator @ with an operand of a type whose
19852 // cv-unqualified version is T1, and for a binary operator @ with
19853 // a left operand of a type whose cv-unqualified version is T1 and
19854 // a right operand of a type whose cv-unqualified version is T2,
19855 // three sets of candidate functions, designated member
19856 // candidates, non-member candidates and built-in candidates, are
19857 // constructed as follows:
19858 // -- If T1 is a complete class type or a class currently being
19859 // defined, the set of member candidates is the result of the
19860 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
19861 // the set of member candidates is empty.
19862 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19863 Lookup.suppressDiagnostics();
19864 if (Ty->isRecordType()) {
19865 // Complete the type if it can be completed.
19866 // If the type is neither complete nor being defined, bail out now.
19867 bool IsComplete = SemaRef.isCompleteType(Loc, Ty);
19868 auto *RD = Ty->castAsRecordDecl();
19869 if (IsComplete || RD->isBeingDefined()) {
19870 Lookup.clear();
19871 SemaRef.LookupQualifiedName(Lookup, RD);
19872 if (Lookup.empty()) {
19873 Lookups.emplace_back();
19874 Lookups.back().append(Lookup.begin(), Lookup.end());
19875 }
19876 }
19877 }
19878 // Perform ADL.
19879 if (SemaRef.getLangOpts().CPlusPlus)
19880 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
19882 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
19883 if (!D->isInvalidDecl() &&
19884 SemaRef.Context.hasSameType(D->getType(), Ty))
19885 return D;
19886 return nullptr;
19887 }))
19888 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
19889 VK_LValue, Loc);
19890 if (SemaRef.getLangOpts().CPlusPlus) {
19892 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
19893 if (!D->isInvalidDecl() &&
19894 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
19896 SemaRef.getASTContext()))
19897 return D;
19898 return nullptr;
19899 })) {
19900 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
19901 /*DetectVirtual=*/false);
19902 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
19903 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
19904 VD->getType().getUnqualifiedType()))) {
19905 if (SemaRef.CheckBaseClassAccess(
19906 Loc, VD->getType(), Ty, Paths.front(),
19907 /*DiagID=*/0) != Sema::AR_inaccessible) {
19908 SemaRef.BuildBasePathArray(Paths, BasePath);
19909 return SemaRef.BuildDeclRefExpr(
19910 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc);
19911 }
19912 }
19913 }
19914 }
19915 }
19916 if (ReductionIdScopeSpec.isSet()) {
19917 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
19918 << Ty << Range;
19919 return ExprError();
19920 }
19921 return ExprEmpty();
19922}
19923
19924namespace {
19925/// Data for the reduction-based clauses.
19926struct ReductionData {
19927 /// List of original reduction items.
19928 SmallVector<Expr *, 8> Vars;
19929 /// List of private copies of the reduction items.
19930 SmallVector<Expr *, 8> Privates;
19931 /// LHS expressions for the reduction_op expressions.
19932 SmallVector<Expr *, 8> LHSs;
19933 /// RHS expressions for the reduction_op expressions.
19934 SmallVector<Expr *, 8> RHSs;
19935 /// Reduction operation expression.
19936 SmallVector<Expr *, 8> ReductionOps;
19937 /// inscan copy operation expressions.
19938 SmallVector<Expr *, 8> InscanCopyOps;
19939 /// inscan copy temp array expressions for prefix sums.
19940 SmallVector<Expr *, 8> InscanCopyArrayTemps;
19941 /// inscan copy temp array element expressions for prefix sums.
19942 SmallVector<Expr *, 8> InscanCopyArrayElems;
19943 /// Taskgroup descriptors for the corresponding reduction items in
19944 /// in_reduction clauses.
19945 SmallVector<Expr *, 8> TaskgroupDescriptors;
19946 /// List of captures for clause.
19947 SmallVector<Decl *, 4> ExprCaptures;
19948 /// List of postupdate expressions.
19949 SmallVector<Expr *, 4> ExprPostUpdates;
19950 /// Reduction modifier.
19951 unsigned RedModifier = 0;
19952 /// Original modifier.
19953 unsigned OrigSharingModifier = 0;
19954 /// Private Variable Reduction
19955 SmallVector<bool, 8> IsPrivateVarReduction;
19956 ReductionData() = delete;
19957 /// Reserves required memory for the reduction data.
19958 ReductionData(unsigned Size, unsigned Modifier = 0, unsigned OrgModifier = 0)
19959 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
19960 Vars.reserve(Size);
19961 Privates.reserve(Size);
19962 LHSs.reserve(Size);
19963 RHSs.reserve(Size);
19964 ReductionOps.reserve(Size);
19965 IsPrivateVarReduction.reserve(Size);
19966 if (RedModifier == OMPC_REDUCTION_inscan) {
19967 InscanCopyOps.reserve(Size);
19968 InscanCopyArrayTemps.reserve(Size);
19969 InscanCopyArrayElems.reserve(Size);
19970 }
19971 TaskgroupDescriptors.reserve(Size);
19972 ExprCaptures.reserve(Size);
19973 ExprPostUpdates.reserve(Size);
19974 }
19975 /// Stores reduction item and reduction operation only (required for dependent
19976 /// reduction item).
19977 void push(Expr *Item, Expr *ReductionOp) {
19978 Vars.emplace_back(Item);
19979 Privates.emplace_back(nullptr);
19980 LHSs.emplace_back(nullptr);
19981 RHSs.emplace_back(nullptr);
19982 ReductionOps.emplace_back(ReductionOp);
19983 IsPrivateVarReduction.emplace_back(false);
19984 TaskgroupDescriptors.emplace_back(nullptr);
19985 if (RedModifier == OMPC_REDUCTION_inscan) {
19986 InscanCopyOps.push_back(nullptr);
19987 InscanCopyArrayTemps.push_back(nullptr);
19988 InscanCopyArrayElems.push_back(nullptr);
19989 }
19990 }
19991 /// Stores reduction data.
19992 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
19993 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
19994 Expr *CopyArrayElem, bool IsPrivate) {
19995 Vars.emplace_back(Item);
19996 Privates.emplace_back(Private);
19997 LHSs.emplace_back(LHS);
19998 RHSs.emplace_back(RHS);
19999 ReductionOps.emplace_back(ReductionOp);
20000 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
20001 if (RedModifier == OMPC_REDUCTION_inscan) {
20002 InscanCopyOps.push_back(CopyOp);
20003 InscanCopyArrayTemps.push_back(CopyArrayTemp);
20004 InscanCopyArrayElems.push_back(CopyArrayElem);
20005 } else {
20006 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
20007 CopyArrayElem == nullptr &&
20008 "Copy operation must be used for inscan reductions only.");
20009 }
20010 IsPrivateVarReduction.emplace_back(IsPrivate);
20011 }
20012};
20013} // namespace
20014
20016 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
20017 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
20018 const Expr *Length = OASE->getLength();
20019 if (Length == nullptr) {
20020 // For array sections of the form [1:] or [:], we would need to analyze
20021 // the lower bound...
20022 if (OASE->getColonLocFirst().isValid())
20023 return false;
20024
20025 // This is an array subscript which has implicit length 1!
20026 SingleElement = true;
20027 ArraySizes.push_back(llvm::APSInt::get(1));
20028 } else {
20029 Expr::EvalResult Result;
20030 if (!Length->EvaluateAsInt(Result, Context))
20031 return false;
20032
20033 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
20034 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
20035 ArraySizes.push_back(ConstantLengthValue);
20036 }
20037
20038 // Get the base of this array section and walk up from there.
20039 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
20040
20041 // We require length = 1 for all array sections except the right-most to
20042 // guarantee that the memory region is contiguous and has no holes in it.
20043 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) {
20044 Length = TempOASE->getLength();
20045 if (Length == nullptr) {
20046 // For array sections of the form [1:] or [:], we would need to analyze
20047 // the lower bound...
20048 if (OASE->getColonLocFirst().isValid())
20049 return false;
20050
20051 // This is an array subscript which has implicit length 1!
20052 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
20053 ArraySizes.push_back(ConstantOne);
20054 } else {
20055 Expr::EvalResult Result;
20056 if (!Length->EvaluateAsInt(Result, Context))
20057 return false;
20058
20059 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
20060 if (ConstantLengthValue.getSExtValue() != 1)
20061 return false;
20062
20063 ArraySizes.push_back(ConstantLengthValue);
20064 }
20065 Base = TempOASE->getBase()->IgnoreParenImpCasts();
20066 }
20067
20068 // If we have a single element, we don't need to add the implicit lengths.
20069 if (!SingleElement) {
20070 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
20071 // Has implicit length 1!
20072 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
20073 ArraySizes.push_back(ConstantOne);
20074 Base = TempASE->getBase()->IgnoreParenImpCasts();
20075 }
20076 }
20077
20078 // This array section can be privatized as a single value or as a constant
20079 // sized array.
20080 return true;
20081}
20082
20083static BinaryOperatorKind
20085 if (BOK == BO_Add)
20086 return BO_AddAssign;
20087 if (BOK == BO_Mul)
20088 return BO_MulAssign;
20089 if (BOK == BO_And)
20090 return BO_AndAssign;
20091 if (BOK == BO_Or)
20092 return BO_OrAssign;
20093 if (BOK == BO_Xor)
20094 return BO_XorAssign;
20095 return BOK;
20096}
20097
20099 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
20100 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20101 SourceLocation ColonLoc, SourceLocation EndLoc,
20102 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20103 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
20104 DeclarationName DN = ReductionId.getName();
20106 BinaryOperatorKind BOK = BO_Comma;
20107
20108 ASTContext &Context = S.Context;
20109 // OpenMP [2.14.3.6, reduction clause]
20110 // C
20111 // reduction-identifier is either an identifier or one of the following
20112 // operators: +, -, *, &, |, ^, && and ||
20113 // C++
20114 // reduction-identifier is either an id-expression or one of the following
20115 // operators: +, -, *, &, |, ^, && and ||
20116 switch (OOK) {
20117 case OO_Plus:
20118 BOK = BO_Add;
20119 break;
20120 case OO_Minus:
20121 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
20122 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
20123 // reduction identifier.
20124 if (S.LangOpts.OpenMP > 52)
20125 BOK = BO_Comma;
20126 else
20127 BOK = BO_Add;
20128 break;
20129 case OO_Star:
20130 BOK = BO_Mul;
20131 break;
20132 case OO_Amp:
20133 BOK = BO_And;
20134 break;
20135 case OO_Pipe:
20136 BOK = BO_Or;
20137 break;
20138 case OO_Caret:
20139 BOK = BO_Xor;
20140 break;
20141 case OO_AmpAmp:
20142 BOK = BO_LAnd;
20143 break;
20144 case OO_PipePipe:
20145 BOK = BO_LOr;
20146 break;
20147 case OO_New:
20148 case OO_Delete:
20149 case OO_Array_New:
20150 case OO_Array_Delete:
20151 case OO_Slash:
20152 case OO_Percent:
20153 case OO_Tilde:
20154 case OO_Exclaim:
20155 case OO_Equal:
20156 case OO_Less:
20157 case OO_Greater:
20158 case OO_LessEqual:
20159 case OO_GreaterEqual:
20160 case OO_PlusEqual:
20161 case OO_MinusEqual:
20162 case OO_StarEqual:
20163 case OO_SlashEqual:
20164 case OO_PercentEqual:
20165 case OO_CaretEqual:
20166 case OO_AmpEqual:
20167 case OO_PipeEqual:
20168 case OO_LessLess:
20169 case OO_GreaterGreater:
20170 case OO_LessLessEqual:
20171 case OO_GreaterGreaterEqual:
20172 case OO_EqualEqual:
20173 case OO_ExclaimEqual:
20174 case OO_Spaceship:
20175 case OO_PlusPlus:
20176 case OO_MinusMinus:
20177 case OO_Comma:
20178 case OO_ArrowStar:
20179 case OO_Arrow:
20180 case OO_Call:
20181 case OO_Subscript:
20182 case OO_Conditional:
20183 case OO_Coawait:
20185 llvm_unreachable("Unexpected reduction identifier");
20186 case OO_None:
20187 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
20188 if (II->isStr("max"))
20189 BOK = BO_GT;
20190 else if (II->isStr("min"))
20191 BOK = BO_LT;
20192 }
20193 break;
20194 }
20195
20196 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
20197 // A reduction clause with the minus (-) operator was deprecated
20198 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
20199 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
20200
20201 SourceRange ReductionIdRange;
20202 if (ReductionIdScopeSpec.isValid())
20203 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
20204 else
20205 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
20206 ReductionIdRange.setEnd(ReductionId.getEndLoc());
20207
20208 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
20209 bool FirstIter = true;
20210 for (Expr *RefExpr : VarList) {
20211 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
20212 // OpenMP [2.1, C/C++]
20213 // A list item is a variable or array section, subject to the restrictions
20214 // specified in Section 2.4 on page 42 and in each of the sections
20215 // describing clauses and directives for which a list appears.
20216 // OpenMP [2.14.3.3, Restrictions, p.1]
20217 // A variable that is part of another variable (as an array or
20218 // structure element) cannot appear in a private clause.
20219 if (!FirstIter && IR != ER)
20220 ++IR;
20221 FirstIter = false;
20222 SourceLocation ELoc;
20223 SourceRange ERange;
20224 bool IsPrivate = false;
20225 Expr *SimpleRefExpr = RefExpr;
20226 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
20227 /*AllowArraySection=*/true);
20228 if (Res.second) {
20229 // Try to find 'declare reduction' corresponding construct before using
20230 // builtin/overloaded operators.
20231 QualType Type = Context.DependentTy;
20232 CXXCastPath BasePath;
20233 ExprResult DeclareReductionRef = buildDeclareReductionRef(
20234 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20235 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
20236 Expr *ReductionOp = nullptr;
20237 if (S.CurContext->isDependentContext() &&
20238 (DeclareReductionRef.isUnset() ||
20239 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
20240 ReductionOp = DeclareReductionRef.get();
20241 // It will be analyzed later.
20242 RD.push(RefExpr, ReductionOp);
20243 }
20244 ValueDecl *D = Res.first;
20245 if (!D)
20246 continue;
20247
20248 Expr *TaskgroupDescriptor = nullptr;
20249 QualType Type;
20250 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
20251 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
20252 if (ASE) {
20253 Type = ASE->getType().getNonReferenceType();
20254 } else if (OASE) {
20255 QualType BaseType =
20257 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20258 Type = ATy->getElementType();
20259 else
20260 Type = BaseType->getPointeeType();
20261 Type = Type.getNonReferenceType();
20262 } else {
20263 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
20264 }
20265 auto *VD = dyn_cast<VarDecl>(D);
20266
20267 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
20268 // A variable that appears in a private clause must not have an incomplete
20269 // type or a reference type.
20270 if (S.RequireCompleteType(ELoc, D->getType(),
20271 diag::err_omp_reduction_incomplete_type))
20272 continue;
20273 // OpenMP [2.14.3.6, reduction clause, Restrictions]
20274 // A list item that appears in a reduction clause must not be
20275 // const-qualified.
20276 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
20277 /*AcceptIfMutable=*/false, ASE || OASE))
20278 continue;
20279
20280 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
20281 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
20282 // If a list-item is a reference type then it must bind to the same object
20283 // for all threads of the team.
20284 if (!ASE && !OASE) {
20285 if (VD) {
20286 VarDecl *VDDef = VD->getDefinition();
20287 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
20288 DSARefChecker Check(Stack);
20289 if (Check.Visit(VDDef->getInit())) {
20290 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
20291 << getOpenMPClauseNameForDiag(ClauseKind) << ERange;
20292 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
20293 continue;
20294 }
20295 }
20296 }
20297
20298 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
20299 // in a Construct]
20300 // Variables with the predetermined data-sharing attributes may not be
20301 // listed in data-sharing attributes clauses, except for the cases
20302 // listed below. For these exceptions only, listing a predetermined
20303 // variable in a data-sharing attribute clause is allowed and overrides
20304 // the variable's predetermined data-sharing attributes.
20305 // OpenMP [2.14.3.6, Restrictions, p.3]
20306 // Any number of reduction clauses can be specified on the directive,
20307 // but a list item can appear only once in the reduction clauses for that
20308 // directive.
20309 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
20310 if (DVar.CKind == OMPC_reduction) {
20311 S.Diag(ELoc, diag::err_omp_once_referenced)
20312 << getOpenMPClauseNameForDiag(ClauseKind);
20313 if (DVar.RefExpr)
20314 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
20315 continue;
20316 }
20317 if (DVar.CKind != OMPC_unknown) {
20318 S.Diag(ELoc, diag::err_omp_wrong_dsa)
20319 << getOpenMPClauseNameForDiag(DVar.CKind)
20320 << getOpenMPClauseNameForDiag(OMPC_reduction);
20321 reportOriginalDsa(S, Stack, D, DVar);
20322 continue;
20323 }
20324
20325 // OpenMP [2.14.3.6, Restrictions, p.1]
20326 // A list item that appears in a reduction clause of a worksharing
20327 // construct must be shared in the parallel regions to which any of the
20328 // worksharing regions arising from the worksharing construct bind.
20329
20330 if (S.getLangOpts().OpenMP <= 52 &&
20332 !isOpenMPParallelDirective(CurrDir) &&
20333 !isOpenMPTeamsDirective(CurrDir)) {
20334 DVar = Stack->getImplicitDSA(D, true);
20335 if (DVar.CKind != OMPC_shared) {
20336 S.Diag(ELoc, diag::err_omp_required_access)
20337 << getOpenMPClauseNameForDiag(OMPC_reduction)
20338 << getOpenMPClauseNameForDiag(OMPC_shared);
20339 reportOriginalDsa(S, Stack, D, DVar);
20340 continue;
20341 }
20342 } else if (isOpenMPWorksharingDirective(CurrDir) &&
20343 !isOpenMPParallelDirective(CurrDir) &&
20344 !isOpenMPTeamsDirective(CurrDir)) {
20345 // OpenMP 6.0 [ 7.6.10 ]
20346 // Support Reduction over private variables with reduction clause.
20347 // A list item in a reduction clause can now be private in the enclosing
20348 // context. For orphaned constructs it is assumed to be shared unless
20349 // the original(private) modifier appears in the clause.
20350 DVar = Stack->getImplicitDSA(D, true);
20351 // Determine if the variable should be considered private
20352 IsPrivate = DVar.CKind != OMPC_shared;
20353 bool IsOrphaned = false;
20354 OpenMPDirectiveKind ParentDir = Stack->getParentDirective();
20355 IsOrphaned = ParentDir == OMPD_unknown;
20356 if ((IsOrphaned &&
20357 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
20358 IsPrivate = true;
20359 }
20360 } else {
20361 // Threadprivates cannot be shared between threads, so dignose if the base
20362 // is a threadprivate variable.
20363 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
20364 if (DVar.CKind == OMPC_threadprivate) {
20365 S.Diag(ELoc, diag::err_omp_wrong_dsa)
20366 << getOpenMPClauseNameForDiag(DVar.CKind)
20367 << getOpenMPClauseNameForDiag(OMPC_reduction);
20368 reportOriginalDsa(S, Stack, D, DVar);
20369 continue;
20370 }
20371 }
20372
20373 // Try to find 'declare reduction' corresponding construct before using
20374 // builtin/overloaded operators.
20375 CXXCastPath BasePath;
20376 ExprResult DeclareReductionRef = buildDeclareReductionRef(
20377 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20378 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
20379 if (DeclareReductionRef.isInvalid())
20380 continue;
20381 if (S.CurContext->isDependentContext() &&
20382 (DeclareReductionRef.isUnset() ||
20383 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
20384 RD.push(RefExpr, DeclareReductionRef.get());
20385 continue;
20386 }
20387 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
20388 // Not allowed reduction identifier is found.
20389 if (S.LangOpts.OpenMP > 52)
20390 S.Diag(ReductionId.getBeginLoc(),
20391 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
20392 << Type << ReductionIdRange;
20393 else
20394 S.Diag(ReductionId.getBeginLoc(),
20395 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
20396 << Type << ReductionIdRange;
20397 continue;
20398 }
20399
20400 // OpenMP [2.14.3.6, reduction clause, Restrictions]
20401 // The type of a list item that appears in a reduction clause must be valid
20402 // for the reduction-identifier. For a max or min reduction in C, the type
20403 // of the list item must be an allowed arithmetic data type: char, int,
20404 // float, double, or _Bool, possibly modified with long, short, signed, or
20405 // unsigned. For a max or min reduction in C++, the type of the list item
20406 // must be an allowed arithmetic data type: char, wchar_t, int, float,
20407 // double, or bool, possibly modified with long, short, signed, or unsigned.
20408 if (DeclareReductionRef.isUnset()) {
20409 if ((BOK == BO_GT || BOK == BO_LT) &&
20410 !(Type->isScalarType() ||
20411 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
20412 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
20413 << getOpenMPClauseNameForDiag(ClauseKind)
20414 << S.getLangOpts().CPlusPlus;
20415 if (!ASE && !OASE) {
20416 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20418 S.Diag(D->getLocation(),
20419 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20420 << D;
20421 }
20422 continue;
20423 }
20424 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
20425 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
20426 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
20427 << getOpenMPClauseNameForDiag(ClauseKind);
20428 if (!ASE && !OASE) {
20429 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20431 S.Diag(D->getLocation(),
20432 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20433 << D;
20434 }
20435 continue;
20436 }
20437 }
20438
20439 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
20440 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
20441 D->hasAttrs() ? &D->getAttrs() : nullptr);
20442 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
20443 D->hasAttrs() ? &D->getAttrs() : nullptr);
20444 QualType PrivateTy = Type;
20445
20446 // Try if we can determine constant lengths for all array sections and avoid
20447 // the VLA.
20448 bool ConstantLengthOASE = false;
20449 if (OASE) {
20450 bool SingleElement;
20452 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
20453 Context, OASE, SingleElement, ArraySizes);
20454
20455 // If we don't have a single element, we must emit a constant array type.
20456 if (ConstantLengthOASE && !SingleElement) {
20457 for (llvm::APSInt &Size : ArraySizes)
20458 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
20460 /*IndexTypeQuals=*/0);
20461 }
20462 }
20463
20464 if ((OASE && !ConstantLengthOASE) ||
20465 (!OASE && !ASE &&
20467 if (!Context.getTargetInfo().isVLASupported()) {
20468 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
20469 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20470 S.Diag(ELoc, diag::note_vla_unsupported);
20471 continue;
20472 } else {
20473 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20474 S.targetDiag(ELoc, diag::note_vla_unsupported);
20475 }
20476 }
20477 // For arrays/array sections only:
20478 // Create pseudo array type for private copy. The size for this array will
20479 // be generated during codegen.
20480 // For array subscripts or single variables Private Ty is the same as Type
20481 // (type of the variable or single array element).
20482 PrivateTy = Context.getVariableArrayType(
20483 Type,
20484 new (Context)
20485 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
20486 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0);
20487 } else if (!ASE && !OASE &&
20488 Context.getAsArrayType(D->getType().getNonReferenceType())) {
20489 PrivateTy = D->getType().getNonReferenceType();
20490 }
20491 // Private copy.
20492 VarDecl *PrivateVD =
20493 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
20494 D->hasAttrs() ? &D->getAttrs() : nullptr,
20495 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
20496 // Add initializer for private variable.
20497 Expr *Init = nullptr;
20498 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
20499 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
20500 if (DeclareReductionRef.isUsable()) {
20501 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
20502 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
20503 if (DRD->getInitializer()) {
20504 Init = DRDRef;
20505 RHSVD->setInit(DRDRef);
20507 }
20508 } else {
20509 switch (BOK) {
20510 case BO_Add:
20511 case BO_Xor:
20512 case BO_Or:
20513 case BO_LOr:
20514 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
20516 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
20517 break;
20518 case BO_Mul:
20519 case BO_LAnd:
20520 if (Type->isScalarType() || Type->isAnyComplexType()) {
20521 // '*' and '&&' reduction ops - initializer is '1'.
20522 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
20523 }
20524 break;
20525 case BO_And: {
20526 // '&' reduction op - initializer is '~0'.
20527 QualType OrigType = Type;
20528 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
20529 Type = ComplexTy->getElementType();
20530 if (Type->isRealFloatingType()) {
20531 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
20532 Context.getFloatTypeSemantics(Type));
20533 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
20534 Type, ELoc);
20535 } else if (Type->isScalarType()) {
20536 uint64_t Size = Context.getTypeSize(Type);
20537 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
20538 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
20539 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
20540 }
20541 if (Init && OrigType->isAnyComplexType()) {
20542 // Init = 0xFFFF + 0xFFFFi;
20543 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
20544 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
20545 }
20546 Type = OrigType;
20547 break;
20548 }
20549 case BO_LT:
20550 case BO_GT: {
20551 // 'min' reduction op - initializer is 'Largest representable number in
20552 // the reduction list item type'.
20553 // 'max' reduction op - initializer is 'Least representable number in
20554 // the reduction list item type'.
20555 if (Type->isIntegerType() || Type->isPointerType()) {
20556 bool IsSigned = Type->hasSignedIntegerRepresentation();
20557 uint64_t Size = Context.getTypeSize(Type);
20558 QualType IntTy =
20559 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
20560 llvm::APInt InitValue =
20561 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
20562 : llvm::APInt::getMinValue(Size)
20563 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
20564 : llvm::APInt::getMaxValue(Size);
20565 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
20566 if (Type->isPointerType()) {
20567 // Cast to pointer type.
20569 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
20570 if (CastExpr.isInvalid())
20571 continue;
20572 Init = CastExpr.get();
20573 }
20574 } else if (Type->isRealFloatingType()) {
20575 llvm::APFloat InitValue = llvm::APFloat::getLargest(
20576 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
20577 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
20578 Type, ELoc);
20579 }
20580 break;
20581 }
20582 case BO_PtrMemD:
20583 case BO_PtrMemI:
20584 case BO_MulAssign:
20585 case BO_Div:
20586 case BO_Rem:
20587 case BO_Sub:
20588 case BO_Shl:
20589 case BO_Shr:
20590 case BO_LE:
20591 case BO_GE:
20592 case BO_EQ:
20593 case BO_NE:
20594 case BO_Cmp:
20595 case BO_AndAssign:
20596 case BO_XorAssign:
20597 case BO_OrAssign:
20598 case BO_Assign:
20599 case BO_AddAssign:
20600 case BO_SubAssign:
20601 case BO_DivAssign:
20602 case BO_RemAssign:
20603 case BO_ShlAssign:
20604 case BO_ShrAssign:
20605 case BO_Comma:
20606 llvm_unreachable("Unexpected reduction operation");
20607 }
20608 }
20609 if (Init && DeclareReductionRef.isUnset()) {
20610 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
20611 // Store initializer for single element in private copy. Will be used
20612 // during codegen.
20613 PrivateVD->setInit(RHSVD->getInit());
20614 PrivateVD->setInitStyle(RHSVD->getInitStyle());
20615 } else if (!Init) {
20616 S.ActOnUninitializedDecl(RHSVD);
20617 // Store initializer for single element in private copy. Will be used
20618 // during codegen.
20619 PrivateVD->setInit(RHSVD->getInit());
20620 PrivateVD->setInitStyle(RHSVD->getInitStyle());
20621 }
20622 if (RHSVD->isInvalidDecl())
20623 continue;
20624 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
20625 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
20626 << Type << ReductionIdRange;
20627 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20629 S.Diag(D->getLocation(),
20630 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20631 << D;
20632 continue;
20633 }
20634 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
20635 ExprResult ReductionOp;
20636 if (DeclareReductionRef.isUsable()) {
20637 QualType RedTy = DeclareReductionRef.get()->getType();
20638 QualType PtrRedTy = Context.getPointerType(RedTy);
20639 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
20640 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
20641 if (!BasePath.empty()) {
20642 LHS = S.DefaultLvalueConversion(LHS.get());
20643 RHS = S.DefaultLvalueConversion(RHS.get());
20645 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
20646 LHS.get()->getValueKind(), FPOptionsOverride());
20648 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
20649 RHS.get()->getValueKind(), FPOptionsOverride());
20650 }
20652 QualType Params[] = {PtrRedTy, PtrRedTy};
20653 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
20654 auto *OVE = new (Context) OpaqueValueExpr(
20655 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
20656 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
20657 Expr *Args[] = {LHS.get(), RHS.get()};
20658 ReductionOp =
20659 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
20661 } else {
20663 if (Type->isRecordType() && CombBOK != BOK) {
20665 ReductionOp =
20666 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20667 CombBOK, LHSDRE, RHSDRE);
20668 }
20669 if (!ReductionOp.isUsable()) {
20670 ReductionOp =
20671 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
20672 LHSDRE, RHSDRE);
20673 if (ReductionOp.isUsable()) {
20674 if (BOK != BO_LT && BOK != BO_GT) {
20675 ReductionOp =
20676 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20677 BO_Assign, LHSDRE, ReductionOp.get());
20678 } else {
20679 auto *ConditionalOp = new (Context)
20680 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
20681 RHSDRE, Type, VK_LValue, OK_Ordinary);
20682 ReductionOp =
20683 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20684 BO_Assign, LHSDRE, ConditionalOp);
20685 }
20686 }
20687 }
20688 if (ReductionOp.isUsable())
20689 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
20690 /*DiscardedValue=*/false);
20691 if (!ReductionOp.isUsable())
20692 continue;
20693 }
20694
20695 // Add copy operations for inscan reductions.
20696 // LHS = RHS;
20697 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
20698 if (ClauseKind == OMPC_reduction &&
20699 RD.RedModifier == OMPC_REDUCTION_inscan) {
20700 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
20701 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
20702 RHS.get());
20703 if (!CopyOpRes.isUsable())
20704 continue;
20705 CopyOpRes =
20706 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
20707 if (!CopyOpRes.isUsable())
20708 continue;
20709 // For simd directive and simd-based directives in simd mode no need to
20710 // construct temp array, need just a single temp element.
20711 if (Stack->getCurrentDirective() == OMPD_simd ||
20712 (S.getLangOpts().OpenMPSimd &&
20713 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
20714 VarDecl *TempArrayVD =
20715 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
20716 D->hasAttrs() ? &D->getAttrs() : nullptr);
20717 // Add a constructor to the temp decl.
20718 S.ActOnUninitializedDecl(TempArrayVD);
20719 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
20720 } else {
20721 // Build temp array for prefix sum.
20722 auto *Dim = new (S.Context)
20725 PrivateTy, Dim, ArraySizeModifier::Normal,
20726 /*IndexTypeQuals=*/0);
20727 VarDecl *TempArrayVD =
20728 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
20729 D->hasAttrs() ? &D->getAttrs() : nullptr);
20730 // Add a constructor to the temp decl.
20731 S.ActOnUninitializedDecl(TempArrayVD);
20732 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
20733 TempArrayElem =
20734 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
20735 auto *Idx = new (S.Context)
20737 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
20738 ELoc, Idx, ELoc);
20739 }
20740 }
20741
20742 // OpenMP [2.15.4.6, Restrictions, p.2]
20743 // A list item that appears in an in_reduction clause of a task construct
20744 // must appear in a task_reduction clause of a construct associated with a
20745 // taskgroup region that includes the participating task in its taskgroup
20746 // set. The construct associated with the innermost region that meets this
20747 // condition must specify the same reduction-identifier as the in_reduction
20748 // clause.
20749 if (ClauseKind == OMPC_in_reduction) {
20750 SourceRange ParentSR;
20751 BinaryOperatorKind ParentBOK;
20752 const Expr *ParentReductionOp = nullptr;
20753 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
20754 DSAStackTy::DSAVarData ParentBOKDSA =
20755 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
20756 ParentBOKTD);
20757 DSAStackTy::DSAVarData ParentReductionOpDSA =
20758 Stack->getTopMostTaskgroupReductionData(
20759 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
20760 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
20761 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
20762 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
20763 (DeclareReductionRef.isUsable() && IsParentBOK) ||
20764 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
20765 bool EmitError = true;
20766 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
20767 llvm::FoldingSetNodeID RedId, ParentRedId;
20768 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
20769 DeclareReductionRef.get()->Profile(RedId, Context,
20770 /*Canonical=*/true);
20771 EmitError = RedId != ParentRedId;
20772 }
20773 if (EmitError) {
20774 S.Diag(ReductionId.getBeginLoc(),
20775 diag::err_omp_reduction_identifier_mismatch)
20776 << ReductionIdRange << RefExpr->getSourceRange();
20777 S.Diag(ParentSR.getBegin(),
20778 diag::note_omp_previous_reduction_identifier)
20779 << ParentSR
20780 << (IsParentBOK ? ParentBOKDSA.RefExpr
20781 : ParentReductionOpDSA.RefExpr)
20782 ->getSourceRange();
20783 continue;
20784 }
20785 }
20786 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
20787 }
20788
20789 DeclRefExpr *Ref = nullptr;
20790 Expr *VarsExpr = RefExpr->IgnoreParens();
20791 if (!VD && !S.CurContext->isDependentContext()) {
20792 if (ASE || OASE) {
20793 TransformExprToCaptures RebuildToCapture(S, D);
20794 VarsExpr =
20795 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
20796 Ref = RebuildToCapture.getCapturedExpr();
20797 } else {
20798 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
20799 }
20800 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
20801 RD.ExprCaptures.emplace_back(Ref->getDecl());
20802 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20803 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
20804 if (!RefRes.isUsable())
20805 continue;
20806 ExprResult PostUpdateRes =
20807 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
20808 RefRes.get());
20809 if (!PostUpdateRes.isUsable())
20810 continue;
20811 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
20812 Stack->getCurrentDirective() == OMPD_taskgroup) {
20813 S.Diag(RefExpr->getExprLoc(),
20814 diag::err_omp_reduction_non_addressable_expression)
20815 << RefExpr->getSourceRange();
20816 continue;
20817 }
20818 RD.ExprPostUpdates.emplace_back(
20819 S.IgnoredValueConversions(PostUpdateRes.get()).get());
20820 }
20821 }
20822 }
20823 // All reduction items are still marked as reduction (to do not increase
20824 // code base size).
20825 unsigned Modifier = RD.RedModifier;
20826 // Consider task_reductions as reductions with task modifier. Required for
20827 // correct analysis of in_reduction clauses.
20828 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
20829 Modifier = OMPC_REDUCTION_task;
20830 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
20831 ASE || OASE);
20832 if (Modifier == OMPC_REDUCTION_task &&
20833 (CurrDir == OMPD_taskgroup ||
20834 ((isOpenMPParallelDirective(CurrDir) ||
20835 isOpenMPWorksharingDirective(CurrDir)) &&
20836 !isOpenMPSimdDirective(CurrDir)))) {
20837 if (DeclareReductionRef.isUsable())
20838 Stack->addTaskgroupReductionData(D, ReductionIdRange,
20839 DeclareReductionRef.get());
20840 else
20841 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
20842 }
20843 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
20844 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
20845 TempArrayElem.get(), IsPrivate);
20846 }
20847 return RD.Vars.empty();
20848}
20849
20851 ArrayRef<Expr *> VarList,
20853 SourceLocation StartLoc, SourceLocation LParenLoc,
20854 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
20855 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20856 ArrayRef<Expr *> UnresolvedReductions) {
20858 static_cast<OpenMPReductionClauseModifier>(Modifiers.ExtraModifier);
20859 OpenMPOriginalSharingModifier OriginalSharingModifier =
20860 static_cast<OpenMPOriginalSharingModifier>(
20861 Modifiers.OriginalSharingModifier);
20862 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
20863 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
20864 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
20865 /*Last=*/OMPC_REDUCTION_unknown)
20866 << getOpenMPClauseNameForDiag(OMPC_reduction);
20867 return nullptr;
20868 }
20869 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
20870 // A reduction clause with the inscan reduction-modifier may only appear on a
20871 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
20872 // construct, a parallel worksharing-loop construct or a parallel
20873 // worksharing-loop SIMD construct.
20874 if (Modifier == OMPC_REDUCTION_inscan &&
20875 (DSAStack->getCurrentDirective() != OMPD_for &&
20876 DSAStack->getCurrentDirective() != OMPD_for_simd &&
20877 DSAStack->getCurrentDirective() != OMPD_simd &&
20878 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
20879 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
20880 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
20881 return nullptr;
20882 }
20883 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
20884 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
20885 StartLoc, LParenLoc, ColonLoc, EndLoc,
20886 ReductionIdScopeSpec, ReductionId,
20887 UnresolvedReductions, RD))
20888 return nullptr;
20889
20890 return OMPReductionClause::Create(
20891 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
20892 Modifier, RD.Vars,
20893 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20894 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
20895 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
20896 buildPreInits(getASTContext(), RD.ExprCaptures),
20897 buildPostUpdate(SemaRef, RD.ExprPostUpdates), RD.IsPrivateVarReduction,
20898 OriginalSharingModifier);
20899}
20900
20902 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20903 SourceLocation ColonLoc, SourceLocation EndLoc,
20904 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20905 ArrayRef<Expr *> UnresolvedReductions) {
20906 ReductionData RD(VarList.size());
20907 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction,
20908 VarList, StartLoc, LParenLoc, ColonLoc,
20909 EndLoc, ReductionIdScopeSpec, ReductionId,
20910 UnresolvedReductions, RD))
20911 return nullptr;
20912
20913 return OMPTaskReductionClause::Create(
20914 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20915 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20916 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
20917 buildPreInits(getASTContext(), RD.ExprCaptures),
20918 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
20919}
20920
20922 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20923 SourceLocation ColonLoc, SourceLocation EndLoc,
20924 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20925 ArrayRef<Expr *> UnresolvedReductions) {
20926 ReductionData RD(VarList.size());
20927 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList,
20928 StartLoc, LParenLoc, ColonLoc, EndLoc,
20929 ReductionIdScopeSpec, ReductionId,
20930 UnresolvedReductions, RD))
20931 return nullptr;
20932
20933 return OMPInReductionClause::Create(
20934 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20935 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20936 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
20937 buildPreInits(getASTContext(), RD.ExprCaptures),
20938 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
20939}
20940
20942 SourceLocation LinLoc) {
20943 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
20944 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
20945 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
20946 << getLangOpts().CPlusPlus;
20947 return true;
20948 }
20949 return false;
20950}
20951
20953 OpenMPLinearClauseKind LinKind,
20954 QualType Type, bool IsDeclareSimd) {
20955 const auto *VD = dyn_cast_or_null<VarDecl>(D);
20956 // A variable must not have an incomplete type or a reference type.
20957 if (SemaRef.RequireCompleteType(ELoc, Type,
20958 diag::err_omp_linear_incomplete_type))
20959 return true;
20960 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
20961 !Type->isReferenceType()) {
20962 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
20963 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
20964 return true;
20965 }
20966 Type = Type.getNonReferenceType();
20967
20968 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
20969 // A variable that is privatized must not have a const-qualified type
20970 // unless it is of class type with a mutable member. This restriction does
20971 // not apply to the firstprivate clause, nor to the linear clause on
20972 // declarative directives (like declare simd).
20973 if (!IsDeclareSimd &&
20974 rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc))
20975 return true;
20976
20977 // A list item must be of integral or pointer type.
20978 Type = Type.getUnqualifiedType().getCanonicalType();
20979 const auto *Ty = Type.getTypePtrOrNull();
20980 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
20981 !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) {
20982 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
20983 if (D) {
20984 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20986 Diag(D->getLocation(),
20987 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20988 << D;
20989 }
20990 return true;
20991 }
20992 return false;
20993}
20994
20996 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
20997 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
20998 SourceLocation LinLoc, SourceLocation ColonLoc,
20999 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
21003 SmallVector<Decl *, 4> ExprCaptures;
21004 SmallVector<Expr *, 4> ExprPostUpdates;
21005 // OpenMP 5.2 [Section 5.4.6, linear clause]
21006 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
21007 // 'ref'
21008 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
21009 getLangOpts().OpenMP >= 52)
21010 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
21011 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
21012 LinKind = OMPC_LINEAR_val;
21013 for (Expr *RefExpr : VarList) {
21014 assert(RefExpr && "NULL expr in OpenMP linear clause.");
21015 SourceLocation ELoc;
21016 SourceRange ERange;
21017 Expr *SimpleRefExpr = RefExpr;
21018 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21019 if (Res.second) {
21020 // It will be analyzed later.
21021 Vars.push_back(RefExpr);
21022 Privates.push_back(nullptr);
21023 Inits.push_back(nullptr);
21024 }
21025 ValueDecl *D = Res.first;
21026 if (!D)
21027 continue;
21028
21029 QualType Type = D->getType();
21030 auto *VD = dyn_cast<VarDecl>(D);
21031
21032 // OpenMP [2.14.3.7, linear clause]
21033 // A list-item cannot appear in more than one linear clause.
21034 // A list-item that appears in a linear clause cannot appear in any
21035 // other data-sharing attribute clause.
21036 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
21037 if (DVar.RefExpr) {
21038 Diag(ELoc, diag::err_omp_wrong_dsa)
21039 << getOpenMPClauseNameForDiag(DVar.CKind)
21040 << getOpenMPClauseNameForDiag(OMPC_linear);
21042 continue;
21043 }
21044
21045 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
21046 continue;
21047 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
21048
21049 // Build private copy of original var.
21050 VarDecl *Private =
21051 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
21052 D->hasAttrs() ? &D->getAttrs() : nullptr,
21053 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
21054 DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc);
21055 // Build var to save initial value.
21056 VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start");
21057 Expr *InitExpr;
21058 DeclRefExpr *Ref = nullptr;
21059 if (!VD && !SemaRef.CurContext->isDependentContext()) {
21060 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
21061 if (!isOpenMPCapturedDecl(D)) {
21062 ExprCaptures.push_back(Ref->getDecl());
21063 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
21064 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
21065 if (!RefRes.isUsable())
21066 continue;
21067 ExprResult PostUpdateRes =
21068 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
21069 SimpleRefExpr, RefRes.get());
21070 if (!PostUpdateRes.isUsable())
21071 continue;
21072 ExprPostUpdates.push_back(
21073 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
21074 }
21075 }
21076 }
21077 if (LinKind == OMPC_LINEAR_uval)
21078 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
21079 else
21080 InitExpr = VD ? SimpleRefExpr : Ref;
21081 SemaRef.AddInitializerToDecl(
21082 Init, SemaRef.DefaultLvalueConversion(InitExpr).get(),
21083 /*DirectInit=*/false);
21084 DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc);
21085
21086 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
21087 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
21088 ? RefExpr->IgnoreParens()
21089 : Ref);
21090 Privates.push_back(PrivateRef);
21091 Inits.push_back(InitRef);
21092 }
21093
21094 if (Vars.empty())
21095 return nullptr;
21096
21097 Expr *StepExpr = Step;
21098 Expr *CalcStepExpr = nullptr;
21099 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
21100 !Step->isInstantiationDependent() &&
21102 SourceLocation StepLoc = Step->getBeginLoc();
21104 if (Val.isInvalid())
21105 return nullptr;
21106 StepExpr = Val.get();
21107
21108 // Build var to save the step value.
21109 VarDecl *SaveVar =
21110 buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step");
21111 ExprResult SaveRef =
21112 buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc);
21113 ExprResult CalcStep = SemaRef.BuildBinOp(
21114 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr);
21115 CalcStep =
21116 SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue=*/false);
21117
21118 // Warn about zero linear step (it would be probably better specified as
21119 // making corresponding variables 'const').
21120 if (std::optional<llvm::APSInt> Result =
21122 if (!Result->isNegative() && !Result->isStrictlyPositive())
21123 Diag(StepLoc, diag::warn_omp_linear_step_zero)
21124 << Vars[0] << (Vars.size() > 1);
21125 } else if (CalcStep.isUsable()) {
21126 // Calculate the step beforehand instead of doing this on each iteration.
21127 // (This is not used if the number of iterations may be kfold-ed).
21128 CalcStepExpr = CalcStep.get();
21129 }
21130 }
21131
21132 return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind,
21133 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
21134 Vars, Privates, Inits, StepExpr, CalcStepExpr,
21135 buildPreInits(getASTContext(), ExprCaptures),
21136 buildPostUpdate(SemaRef, ExprPostUpdates));
21137}
21138
21139static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
21140 Expr *NumIterations, Sema &SemaRef,
21141 Scope *S, DSAStackTy *Stack) {
21142 // Walk the vars and build update/final expressions for the CodeGen.
21145 SmallVector<Expr *, 8> UsedExprs;
21146 Expr *Step = Clause.getStep();
21147 Expr *CalcStep = Clause.getCalcStep();
21148 // OpenMP [2.14.3.7, linear clause]
21149 // If linear-step is not specified it is assumed to be 1.
21150 if (!Step)
21151 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
21152 else if (CalcStep)
21153 Step = cast<BinaryOperator>(CalcStep)->getLHS();
21154 bool HasErrors = false;
21155 auto CurInit = Clause.inits().begin();
21156 auto CurPrivate = Clause.privates().begin();
21157 OpenMPLinearClauseKind LinKind = Clause.getModifier();
21158 for (Expr *RefExpr : Clause.varlist()) {
21159 SourceLocation ELoc;
21160 SourceRange ERange;
21161 Expr *SimpleRefExpr = RefExpr;
21162 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21163 ValueDecl *D = Res.first;
21164 if (Res.second || !D) {
21165 Updates.push_back(nullptr);
21166 Finals.push_back(nullptr);
21167 HasErrors = true;
21168 continue;
21169 }
21170 auto &&Info = Stack->isLoopControlVariable(D);
21171 // OpenMP [2.15.11, distribute simd Construct]
21172 // A list item may not appear in a linear clause, unless it is the loop
21173 // iteration variable.
21174 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
21175 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
21176 SemaRef.Diag(ELoc,
21177 diag::err_omp_linear_distribute_var_non_loop_iteration);
21178 Updates.push_back(nullptr);
21179 Finals.push_back(nullptr);
21180 HasErrors = true;
21181 continue;
21182 }
21183 Expr *InitExpr = *CurInit;
21184
21185 // Build privatized reference to the current linear var.
21186 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
21187 Expr *CapturedRef;
21188 if (LinKind == OMPC_LINEAR_uval)
21189 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
21190 else
21191 CapturedRef =
21192 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
21193 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
21194 /*RefersToCapture=*/true);
21195
21196 // Build update: Var = InitExpr + IV * Step
21198 if (!Info.first)
21200 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
21201 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
21202 else
21203 Update = *CurPrivate;
21204 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
21205 /*DiscardedValue=*/false);
21206
21207 // Build final: Var = PrivCopy;
21208 ExprResult Final;
21209 if (!Info.first)
21210 Final = SemaRef.BuildBinOp(
21211 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
21212 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
21213 else
21214 Final = *CurPrivate;
21215 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
21216 /*DiscardedValue=*/false);
21217
21218 if (!Update.isUsable() || !Final.isUsable()) {
21219 Updates.push_back(nullptr);
21220 Finals.push_back(nullptr);
21221 UsedExprs.push_back(nullptr);
21222 HasErrors = true;
21223 } else {
21224 Updates.push_back(Update.get());
21225 Finals.push_back(Final.get());
21226 if (!Info.first)
21227 UsedExprs.push_back(SimpleRefExpr);
21228 }
21229 ++CurInit;
21230 ++CurPrivate;
21231 }
21232 if (Expr *S = Clause.getStep())
21233 UsedExprs.push_back(S);
21234 // Fill the remaining part with the nullptr.
21235 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
21236 Clause.setUpdates(Updates);
21237 Clause.setFinals(Finals);
21238 Clause.setUsedExprs(UsedExprs);
21239 return HasErrors;
21240}
21241
21243 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
21244 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
21246 for (Expr *RefExpr : VarList) {
21247 assert(RefExpr && "NULL expr in OpenMP aligned clause.");
21248 SourceLocation ELoc;
21249 SourceRange ERange;
21250 Expr *SimpleRefExpr = RefExpr;
21251 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21252 if (Res.second) {
21253 // It will be analyzed later.
21254 Vars.push_back(RefExpr);
21255 }
21256 ValueDecl *D = Res.first;
21257 if (!D)
21258 continue;
21259
21260 QualType QType = D->getType();
21261 auto *VD = dyn_cast<VarDecl>(D);
21262
21263 // OpenMP [2.8.1, simd construct, Restrictions]
21264 // The type of list items appearing in the aligned clause must be
21265 // array, pointer, reference to array, or reference to pointer.
21267 const Type *Ty = QType.getTypePtrOrNull();
21268 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
21269 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
21270 << QType << getLangOpts().CPlusPlus << ERange;
21271 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21273 Diag(D->getLocation(),
21274 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21275 << D;
21276 continue;
21277 }
21278
21279 // OpenMP [2.8.1, simd construct, Restrictions]
21280 // A list-item cannot appear in more than one aligned clause.
21281 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
21282 Diag(ELoc, diag::err_omp_used_in_clause_twice)
21283 << 0 << getOpenMPClauseNameForDiag(OMPC_aligned) << ERange;
21284 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
21285 << getOpenMPClauseNameForDiag(OMPC_aligned);
21286 continue;
21287 }
21288
21289 DeclRefExpr *Ref = nullptr;
21290 if (!VD && isOpenMPCapturedDecl(D))
21291 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
21292 Vars.push_back(SemaRef
21293 .DefaultFunctionArrayConversion(
21294 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
21295 .get());
21296 }
21297
21298 // OpenMP [2.8.1, simd construct, Description]
21299 // The parameter of the aligned clause, alignment, must be a constant
21300 // positive integer expression.
21301 // If no optional parameter is specified, implementation-defined default
21302 // alignments for SIMD instructions on the target platforms are assumed.
21303 if (Alignment != nullptr) {
21304 ExprResult AlignResult =
21305 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
21306 if (AlignResult.isInvalid())
21307 return nullptr;
21308 Alignment = AlignResult.get();
21309 }
21310 if (Vars.empty())
21311 return nullptr;
21312
21313 return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc,
21314 ColonLoc, EndLoc, Vars, Alignment);
21315}
21316
21318 SourceLocation StartLoc,
21319 SourceLocation LParenLoc,
21320 SourceLocation EndLoc) {
21322 SmallVector<Expr *, 8> SrcExprs;
21323 SmallVector<Expr *, 8> DstExprs;
21324 SmallVector<Expr *, 8> AssignmentOps;
21325 for (Expr *RefExpr : VarList) {
21326 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
21327 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21328 // It will be analyzed later.
21329 Vars.push_back(RefExpr);
21330 SrcExprs.push_back(nullptr);
21331 DstExprs.push_back(nullptr);
21332 AssignmentOps.push_back(nullptr);
21333 continue;
21334 }
21335
21336 SourceLocation ELoc = RefExpr->getExprLoc();
21337 // OpenMP [2.1, C/C++]
21338 // A list item is a variable name.
21339 // OpenMP [2.14.4.1, Restrictions, p.1]
21340 // A list item that appears in a copyin clause must be threadprivate.
21341 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
21342 if (!DE || !isa<VarDecl>(DE->getDecl())) {
21343 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
21344 << 0 << RefExpr->getSourceRange();
21345 continue;
21346 }
21347
21348 Decl *D = DE->getDecl();
21349 auto *VD = cast<VarDecl>(D);
21350
21351 QualType Type = VD->getType();
21353 // It will be analyzed later.
21354 Vars.push_back(DE);
21355 SrcExprs.push_back(nullptr);
21356 DstExprs.push_back(nullptr);
21357 AssignmentOps.push_back(nullptr);
21358 continue;
21359 }
21360
21361 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
21362 // A list item that appears in a copyin clause must be threadprivate.
21363 if (!DSAStack->isThreadPrivate(VD)) {
21364 unsigned OMPVersion = getLangOpts().OpenMP;
21365 Diag(ELoc, diag::err_omp_required_access)
21366 << getOpenMPClauseNameForDiag(OMPC_copyin)
21367 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion);
21368 continue;
21369 }
21370
21371 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
21372 // A variable of class type (or array thereof) that appears in a
21373 // copyin clause requires an accessible, unambiguous copy assignment
21374 // operator for the class type.
21375 QualType ElemType =
21377 VarDecl *SrcVD =
21378 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
21379 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
21380 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
21381 SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
21382 VarDecl *DstVD =
21383 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst",
21384 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
21385 DeclRefExpr *PseudoDstExpr =
21386 buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc());
21387 // For arrays generate assignment operation for single element and replace
21388 // it by the original array element in CodeGen.
21389 ExprResult AssignmentOp =
21390 SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
21391 PseudoDstExpr, PseudoSrcExpr);
21392 if (AssignmentOp.isInvalid())
21393 continue;
21394 AssignmentOp =
21395 SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
21396 /*DiscardedValue=*/false);
21397 if (AssignmentOp.isInvalid())
21398 continue;
21399
21400 DSAStack->addDSA(VD, DE, OMPC_copyin);
21401 Vars.push_back(DE);
21402 SrcExprs.push_back(PseudoSrcExpr);
21403 DstExprs.push_back(PseudoDstExpr);
21404 AssignmentOps.push_back(AssignmentOp.get());
21405 }
21406
21407 if (Vars.empty())
21408 return nullptr;
21409
21410 return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21411 Vars, SrcExprs, DstExprs, AssignmentOps);
21412}
21413
21415 SourceLocation StartLoc,
21416 SourceLocation LParenLoc,
21417 SourceLocation EndLoc) {
21419 SmallVector<Expr *, 8> SrcExprs;
21420 SmallVector<Expr *, 8> DstExprs;
21421 SmallVector<Expr *, 8> AssignmentOps;
21422 for (Expr *RefExpr : VarList) {
21423 assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");
21424 SourceLocation ELoc;
21425 SourceRange ERange;
21426 Expr *SimpleRefExpr = RefExpr;
21427 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21428 if (Res.second) {
21429 // It will be analyzed later.
21430 Vars.push_back(RefExpr);
21431 SrcExprs.push_back(nullptr);
21432 DstExprs.push_back(nullptr);
21433 AssignmentOps.push_back(nullptr);
21434 }
21435 ValueDecl *D = Res.first;
21436 if (!D)
21437 continue;
21438
21439 QualType Type = D->getType();
21440 auto *VD = dyn_cast<VarDecl>(D);
21441
21442 // OpenMP [2.14.4.2, Restrictions, p.2]
21443 // A list item that appears in a copyprivate clause may not appear in a
21444 // private or firstprivate clause on the single construct.
21445 if (!VD || !DSAStack->isThreadPrivate(VD)) {
21446 DSAStackTy::DSAVarData DVar =
21447 DSAStack->getTopDSA(D, /*FromParent=*/false);
21448 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
21449 DVar.RefExpr) {
21450 Diag(ELoc, diag::err_omp_wrong_dsa)
21451 << getOpenMPClauseNameForDiag(DVar.CKind)
21452 << getOpenMPClauseNameForDiag(OMPC_copyprivate);
21454 continue;
21455 }
21456
21457 // OpenMP [2.11.4.2, Restrictions, p.1]
21458 // All list items that appear in a copyprivate clause must be either
21459 // threadprivate or private in the enclosing context.
21460 if (DVar.CKind == OMPC_unknown) {
21461 DVar = DSAStack->getImplicitDSA(D, false);
21462 if (DVar.CKind == OMPC_shared) {
21463 Diag(ELoc, diag::err_omp_required_access)
21464 << getOpenMPClauseNameForDiag(OMPC_copyprivate)
21465 << "threadprivate or private in the enclosing context";
21467 continue;
21468 }
21469 }
21470 }
21471
21472 // Variably modified types are not supported.
21474 unsigned OMPVersion = getLangOpts().OpenMP;
21475 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
21476 << getOpenMPClauseNameForDiag(OMPC_copyprivate) << Type
21477 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
21478 OMPVersion);
21479 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21481 Diag(D->getLocation(),
21482 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21483 << D;
21484 continue;
21485 }
21486
21487 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
21488 // A variable of class type (or array thereof) that appears in a
21489 // copyin clause requires an accessible, unambiguous copy assignment
21490 // operator for the class type.
21492 .getBaseElementType(Type.getNonReferenceType())
21494 VarDecl *SrcVD =
21495 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
21496 D->hasAttrs() ? &D->getAttrs() : nullptr);
21497 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc);
21498 VarDecl *DstVD =
21499 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
21500 D->hasAttrs() ? &D->getAttrs() : nullptr);
21501 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
21502 ExprResult AssignmentOp = SemaRef.BuildBinOp(
21503 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
21504 if (AssignmentOp.isInvalid())
21505 continue;
21506 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
21507 /*DiscardedValue=*/false);
21508 if (AssignmentOp.isInvalid())
21509 continue;
21510
21511 // No need to mark vars as copyprivate, they are already threadprivate or
21512 // implicitly private.
21513 assert(VD || isOpenMPCapturedDecl(D));
21514 Vars.push_back(
21515 VD ? RefExpr->IgnoreParens()
21516 : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false));
21517 SrcExprs.push_back(PseudoSrcExpr);
21518 DstExprs.push_back(PseudoDstExpr);
21519 AssignmentOps.push_back(AssignmentOp.get());
21520 }
21521
21522 if (Vars.empty())
21523 return nullptr;
21524
21525 return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc,
21526 EndLoc, Vars, SrcExprs, DstExprs,
21527 AssignmentOps);
21528}
21529
21531 SourceLocation StartLoc,
21532 SourceLocation LParenLoc,
21533 SourceLocation EndLoc) {
21534 if (VarList.empty())
21535 return nullptr;
21536
21537 return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21538 VarList);
21539}
21540
21541/// Tries to find omp_depend_t. type.
21542static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
21543 bool Diagnose = true) {
21544 QualType OMPDependT = Stack->getOMPDependT();
21545 if (!OMPDependT.isNull())
21546 return true;
21547 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
21548 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
21549 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
21550 if (Diagnose)
21551 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
21552 return false;
21553 }
21554 Stack->setOMPDependT(PT.get());
21555 return true;
21556}
21557
21559 SourceLocation StartLoc,
21560 SourceLocation LParenLoc,
21561 SourceLocation EndLoc) {
21562 if (!Depobj)
21563 return nullptr;
21564
21565 bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack);
21566
21567 // OpenMP 5.0, 2.17.10.1 depobj Construct
21568 // depobj is an lvalue expression of type omp_depend_t.
21569 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
21570 !Depobj->isInstantiationDependent() &&
21572 (OMPDependTFound && !getASTContext().typesAreCompatible(
21573 DSAStack->getOMPDependT(), Depobj->getType(),
21574 /*CompareUnqualified=*/true))) {
21575 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21576 << 0 << Depobj->getType() << Depobj->getSourceRange();
21577 }
21578
21579 if (!Depobj->isLValue()) {
21580 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21581 << 1 << Depobj->getSourceRange();
21582 }
21583
21584 return OMPDepobjClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21585 Depobj);
21586}
21587
21588namespace {
21589// Utility struct that gathers the related info for doacross clause.
21590struct DoacrossDataInfoTy {
21591 // The list of expressions.
21593 // The OperatorOffset for doacross loop.
21594 DSAStackTy::OperatorOffsetTy OpsOffs;
21595 // The depended loop count.
21596 llvm::APSInt TotalDepCount;
21597};
21598} // namespace
21599static DoacrossDataInfoTy
21601 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
21602 SourceLocation EndLoc) {
21603
21605 DSAStackTy::OperatorOffsetTy OpsOffs;
21606 llvm::APSInt DepCounter(/*BitWidth=*/32);
21607 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
21608
21609 if (const Expr *OrderedCountExpr =
21610 Stack->getParentOrderedRegionParam().first) {
21611 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
21612 TotalDepCount.setIsUnsigned(/*Val=*/true);
21613 }
21614
21615 for (Expr *RefExpr : VarList) {
21616 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
21617 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21618 // It will be analyzed later.
21619 Vars.push_back(RefExpr);
21620 continue;
21621 }
21622
21623 SourceLocation ELoc = RefExpr->getExprLoc();
21624 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
21625 if (!IsSource) {
21626 if (Stack->getParentOrderedRegionParam().first &&
21627 DepCounter >= TotalDepCount) {
21628 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
21629 continue;
21630 }
21631 ++DepCounter;
21632 // OpenMP [2.13.9, Summary]
21633 // depend(dependence-type : vec), where dependence-type is:
21634 // 'sink' and where vec is the iteration vector, which has the form:
21635 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
21636 // where n is the value specified by the ordered clause in the loop
21637 // directive, xi denotes the loop iteration variable of the i-th nested
21638 // loop associated with the loop directive, and di is a constant
21639 // non-negative integer.
21640 if (SemaRef.CurContext->isDependentContext()) {
21641 // It will be analyzed later.
21642 Vars.push_back(RefExpr);
21643 continue;
21644 }
21645 SimpleExpr = SimpleExpr->IgnoreImplicit();
21647 SourceLocation OOLoc;
21648 Expr *LHS = SimpleExpr;
21649 Expr *RHS = nullptr;
21650 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
21651 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
21652 OOLoc = BO->getOperatorLoc();
21653 LHS = BO->getLHS()->IgnoreParenImpCasts();
21654 RHS = BO->getRHS()->IgnoreParenImpCasts();
21655 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
21656 OOK = OCE->getOperator();
21657 OOLoc = OCE->getOperatorLoc();
21658 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
21659 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
21660 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
21661 OOK = MCE->getMethodDecl()
21662 ->getNameInfo()
21663 .getName()
21664 .getCXXOverloadedOperator();
21665 OOLoc = MCE->getCallee()->getExprLoc();
21666 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
21667 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
21668 }
21669 SourceLocation ELoc;
21670 SourceRange ERange;
21671 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
21672 if (Res.second) {
21673 // It will be analyzed later.
21674 Vars.push_back(RefExpr);
21675 }
21676 ValueDecl *D = Res.first;
21677 if (!D)
21678 continue;
21679
21680 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
21681 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
21682 continue;
21683 }
21684 if (RHS) {
21685 ExprResult RHSRes =
21687 RHS, OMPC_depend, /*StrictlyPositive=*/false);
21688 if (RHSRes.isInvalid())
21689 continue;
21690 }
21691 if (!SemaRef.CurContext->isDependentContext() &&
21692 Stack->getParentOrderedRegionParam().first &&
21693 DepCounter != Stack->isParentLoopControlVariable(D).first) {
21694 const ValueDecl *VD =
21695 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
21696 if (VD)
21697 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21698 << 1 << VD;
21699 else
21700 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21701 << 0;
21702 continue;
21703 }
21704 OpsOffs.emplace_back(RHS, OOK);
21705 }
21706 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21707 }
21708 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
21709 TotalDepCount > VarList.size() &&
21710 Stack->getParentOrderedRegionParam().first &&
21711 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
21712 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
21713 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
21714 }
21715 return {Vars, OpsOffs, TotalDepCount};
21716}
21717
21719 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
21720 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
21721 SourceLocation EndLoc) {
21722 OpenMPDependClauseKind DepKind = Data.DepKind;
21723 SourceLocation DepLoc = Data.DepLoc;
21724 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
21725 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
21726 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21727 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_depend);
21728 return nullptr;
21729 }
21730 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
21731 DepKind == OMPC_DEPEND_mutexinoutset) {
21732 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
21733 return nullptr;
21734 }
21735 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
21736 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21737 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
21738 DepKind == OMPC_DEPEND_sink ||
21739 ((getLangOpts().OpenMP < 50 ||
21740 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21741 DepKind == OMPC_DEPEND_depobj))) {
21742 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
21743 OMPC_DEPEND_outallmemory,
21744 OMPC_DEPEND_inoutallmemory};
21745 if (getLangOpts().OpenMP < 50 ||
21746 DSAStack->getCurrentDirective() == OMPD_depobj)
21747 Except.push_back(OMPC_DEPEND_depobj);
21748 if (getLangOpts().OpenMP < 51)
21749 Except.push_back(OMPC_DEPEND_inoutset);
21750 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
21751 ? "depend modifier(iterator) or "
21752 : "";
21753 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21754 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
21755 /*Last=*/OMPC_DEPEND_unknown,
21756 Except)
21757 << getOpenMPClauseNameForDiag(OMPC_depend);
21758 return nullptr;
21759 }
21760 if (DepModifier &&
21761 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
21762 Diag(DepModifier->getExprLoc(),
21763 diag::err_omp_depend_sink_source_with_modifier);
21764 return nullptr;
21765 }
21766 if (DepModifier &&
21767 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
21768 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
21769
21771 DSAStackTy::OperatorOffsetTy OpsOffs;
21772 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
21773
21774 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
21775 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
21776 SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
21777 Vars = VarOffset.Vars;
21778 OpsOffs = VarOffset.OpsOffs;
21779 TotalDepCount = VarOffset.TotalDepCount;
21780 } else {
21781 for (Expr *RefExpr : VarList) {
21782 assert(RefExpr && "NULL expr in OpenMP depend clause.");
21783 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21784 // It will be analyzed later.
21785 Vars.push_back(RefExpr);
21786 continue;
21787 }
21788
21789 SourceLocation ELoc = RefExpr->getExprLoc();
21790 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
21791 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
21792 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
21793 if (OMPDependTFound)
21794 OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack,
21795 DepKind == OMPC_DEPEND_depobj);
21796 if (DepKind == OMPC_DEPEND_depobj) {
21797 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21798 // List items used in depend clauses with the depobj dependence type
21799 // must be expressions of the omp_depend_t type.
21800 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21801 !RefExpr->isInstantiationDependent() &&
21802 !RefExpr->containsUnexpandedParameterPack() &&
21803 (OMPDependTFound &&
21804 !getASTContext().hasSameUnqualifiedType(
21805 DSAStack->getOMPDependT(), RefExpr->getType()))) {
21806 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21807 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
21808 continue;
21809 }
21810 if (!RefExpr->isLValue()) {
21811 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21812 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
21813 continue;
21814 }
21815 } else {
21816 // OpenMP 5.0 [2.17.11, Restrictions]
21817 // List items used in depend clauses cannot be zero-length array
21818 // sections.
21819 QualType ExprTy = RefExpr->getType().getNonReferenceType();
21820 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
21821 if (OASE) {
21822 QualType BaseType =
21824 if (BaseType.isNull())
21825 return nullptr;
21826 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21827 ExprTy = ATy->getElementType();
21828 else
21829 ExprTy = BaseType->getPointeeType();
21830 if (BaseType.isNull() || ExprTy.isNull())
21831 return nullptr;
21832 ExprTy = ExprTy.getNonReferenceType();
21833 const Expr *Length = OASE->getLength();
21835 if (Length && !Length->isValueDependent() &&
21836 Length->EvaluateAsInt(Result, getASTContext()) &&
21837 Result.Val.getInt().isZero()) {
21838 Diag(ELoc,
21839 diag::err_omp_depend_zero_length_array_section_not_allowed)
21840 << SimpleExpr->getSourceRange();
21841 continue;
21842 }
21843 }
21844
21845 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21846 // List items used in depend clauses with the in, out, inout,
21847 // inoutset, or mutexinoutset dependence types cannot be
21848 // expressions of the omp_depend_t type.
21849 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21850 !RefExpr->isInstantiationDependent() &&
21851 !RefExpr->containsUnexpandedParameterPack() &&
21852 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
21853 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
21854 ExprTy.getTypePtr()))) {
21855 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21856 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21857 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21858 << RefExpr->getSourceRange();
21859 continue;
21860 }
21861
21862 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
21863 if (ASE && !ASE->getBase()->isTypeDependent() &&
21864 !ASE->getBase()
21865 ->getType()
21866 .getNonReferenceType()
21867 ->isPointerType() &&
21868 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
21869 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21870 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21871 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21872 << RefExpr->getSourceRange();
21873 continue;
21874 }
21875
21876 ExprResult Res;
21877 {
21879 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
21880 RefExpr->IgnoreParenImpCasts());
21881 }
21882 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
21884 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21885 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21886 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21887 << RefExpr->getSourceRange();
21888 continue;
21889 }
21890 }
21891 }
21892 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21893 }
21894 }
21895
21896 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
21897 DepKind != OMPC_DEPEND_outallmemory &&
21898 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
21899 return nullptr;
21900
21901 auto *C = OMPDependClause::Create(
21902 getASTContext(), StartLoc, LParenLoc, EndLoc,
21903 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
21904 TotalDepCount.getZExtValue());
21905 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
21906 DSAStack->isParentOrderedRegion())
21907 DSAStack->addDoacrossDependClause(C, OpsOffs);
21908 return C;
21909}
21910
21913 SourceLocation LParenLoc, SourceLocation ModifierLoc,
21914 SourceLocation EndLoc) {
21915 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
21916 "Unexpected device modifier in OpenMP < 50.");
21917
21918 bool ErrorFound = false;
21919 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
21920 std::string Values =
21921 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
21922 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21923 << Values << getOpenMPClauseNameForDiag(OMPC_device);
21924 ErrorFound = true;
21925 }
21926
21927 Expr *ValExpr = Device;
21928 Stmt *HelperValStmt = nullptr;
21929
21930 // OpenMP [2.9.1, Restrictions]
21931 // The device expression must evaluate to a non-negative integer value.
21932 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device,
21933 /*StrictlyPositive=*/false) ||
21934 ErrorFound;
21935 if (ErrorFound)
21936 return nullptr;
21937
21938 // OpenMP 5.0 [2.12.5, Restrictions]
21939 // In case of ancestor device-modifier, a requires directive with
21940 // the reverse_offload clause must be specified.
21941 if (Modifier == OMPC_DEVICE_ancestor) {
21942 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
21943 SemaRef.targetDiag(
21944 StartLoc,
21945 diag::err_omp_device_ancestor_without_requires_reverse_offload);
21946 ErrorFound = true;
21947 }
21948 }
21949
21950 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
21951 OpenMPDirectiveKind CaptureRegion =
21952 getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP);
21953 if (CaptureRegion != OMPD_unknown &&
21954 !SemaRef.CurContext->isDependentContext()) {
21955 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
21956 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21957 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
21958 HelperValStmt = buildPreInits(getASTContext(), Captures);
21959 }
21960
21961 return new (getASTContext())
21962 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
21963 LParenLoc, ModifierLoc, EndLoc);
21964}
21965
21967 DSAStackTy *Stack, QualType QTy,
21968 bool FullCheck = true) {
21969 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
21970 return false;
21971 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
21972 !QTy.isTriviallyCopyableType(SemaRef.Context))
21973 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
21974 return true;
21975}
21976
21977/// Return true if it can be proven that the provided array expression
21978/// (array section or array subscript) does NOT specify the whole size of the
21979/// array whose base type is \a BaseQTy.
21981 const Expr *E,
21982 QualType BaseQTy) {
21983 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21984
21985 // If this is an array subscript, it refers to the whole size if the size of
21986 // the dimension is constant and equals 1. Also, an array section assumes the
21987 // format of an array subscript if no colon is used.
21988 if (isa<ArraySubscriptExpr>(E) ||
21989 (OASE && OASE->getColonLocFirst().isInvalid())) {
21990 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21991 return ATy->getSExtSize() != 1;
21992 // Size can't be evaluated statically.
21993 return false;
21994 }
21995
21996 assert(OASE && "Expecting array section if not an array subscript.");
21997 const Expr *LowerBound = OASE->getLowerBound();
21998 const Expr *Length = OASE->getLength();
21999
22000 // If there is a lower bound that does not evaluates to zero, we are not
22001 // covering the whole dimension.
22002 if (LowerBound) {
22003 Expr::EvalResult Result;
22004 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
22005 return false; // Can't get the integer value as a constant.
22006
22007 llvm::APSInt ConstLowerBound = Result.Val.getInt();
22008 if (ConstLowerBound.getSExtValue())
22009 return true;
22010 }
22011
22012 // If we don't have a length we covering the whole dimension.
22013 if (!Length)
22014 return false;
22015
22016 // If the base is a pointer, we don't have a way to get the size of the
22017 // pointee.
22018 if (BaseQTy->isPointerType())
22019 return false;
22020
22021 // We can only check if the length is the same as the size of the dimension
22022 // if we have a constant array.
22023 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
22024 if (!CATy)
22025 return false;
22026
22027 Expr::EvalResult Result;
22028 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
22029 return false; // Can't get the integer value as a constant.
22030
22031 llvm::APSInt ConstLength = Result.Val.getInt();
22032 return CATy->getSExtSize() != ConstLength.getSExtValue();
22033}
22034
22035// Return true if it can be proven that the provided array expression (array
22036// section or array subscript) does NOT specify a single element of the array
22037// whose base type is \a BaseQTy.
22039 const Expr *E,
22040 QualType BaseQTy) {
22041 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
22042
22043 // An array subscript always refer to a single element. Also, an array section
22044 // assumes the format of an array subscript if no colon is used.
22045 if (isa<ArraySubscriptExpr>(E) ||
22046 (OASE && OASE->getColonLocFirst().isInvalid()))
22047 return false;
22048
22049 assert(OASE && "Expecting array section if not an array subscript.");
22050 const Expr *Length = OASE->getLength();
22051
22052 // If we don't have a length we have to check if the array has unitary size
22053 // for this dimension. Also, we should always expect a length if the base type
22054 // is pointer.
22055 if (!Length) {
22056 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
22057 return ATy->getSExtSize() != 1;
22058 // We cannot assume anything.
22059 return false;
22060 }
22061
22062 // Check if the length evaluates to 1.
22063 Expr::EvalResult Result;
22064 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
22065 return false; // Can't get the integer value as a constant.
22066
22067 llvm::APSInt ConstLength = Result.Val.getInt();
22068 return ConstLength.getSExtValue() != 1;
22069}
22070
22071// The base of elements of list in a map clause have to be either:
22072// - a reference to variable or field.
22073// - a member expression.
22074// - an array expression.
22075//
22076// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
22077// reference to 'r'.
22078//
22079// If we have:
22080//
22081// struct SS {
22082// Bla S;
22083// foo() {
22084// #pragma omp target map (S.Arr[:12]);
22085// }
22086// }
22087//
22088// We want to retrieve the member expression 'this->S';
22089
22090// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
22091// If a list item is an array section, it must specify contiguous storage.
22092//
22093// For this restriction it is sufficient that we make sure only references
22094// to variables or fields and array expressions, and that no array sections
22095// exist except in the rightmost expression (unless they cover the whole
22096// dimension of the array). E.g. these would be invalid:
22097//
22098// r.ArrS[3:5].Arr[6:7]
22099//
22100// r.ArrS[3:5].x
22101//
22102// but these would be valid:
22103// r.ArrS[3].Arr[6:7]
22104//
22105// r.ArrS[3].x
22106namespace {
22107class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
22108 Sema &SemaRef;
22109 OpenMPClauseKind CKind = OMPC_unknown;
22110 OpenMPDirectiveKind DKind = OMPD_unknown;
22112 bool IsNonContiguous = false;
22113 bool NoDiagnose = false;
22114 const Expr *RelevantExpr = nullptr;
22115 bool AllowUnitySizeArraySection = true;
22116 bool AllowWholeSizeArraySection = true;
22117 bool AllowAnotherPtr = true;
22118 SourceLocation ELoc;
22119 SourceRange ERange;
22120
22121 void emitErrorMsg() {
22122 // If nothing else worked, this is not a valid map clause expression.
22123 if (SemaRef.getLangOpts().OpenMP < 50) {
22124 SemaRef.Diag(ELoc,
22125 diag::err_omp_expected_named_var_member_or_array_expression)
22126 << ERange;
22127 } else {
22128 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22129 << getOpenMPClauseNameForDiag(CKind) << ERange;
22130 }
22131 }
22132
22133public:
22134 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
22135 if (!isa<VarDecl>(DRE->getDecl())) {
22136 emitErrorMsg();
22137 return false;
22138 }
22139 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22140 RelevantExpr = DRE;
22141 // Record the component.
22142 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
22143 return true;
22144 }
22145
22146 bool VisitMemberExpr(MemberExpr *ME) {
22147 Expr *E = ME;
22148 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
22149
22150 if (isa<CXXThisExpr>(BaseE)) {
22151 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22152 // We found a base expression: this->Val.
22153 RelevantExpr = ME;
22154 } else {
22155 E = BaseE;
22156 }
22157
22158 if (!isa<FieldDecl>(ME->getMemberDecl())) {
22159 if (!NoDiagnose) {
22160 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
22161 << ME->getSourceRange();
22162 return false;
22163 }
22164 if (RelevantExpr)
22165 return false;
22166 return Visit(E);
22167 }
22168
22169 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
22170
22171 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
22172 // A bit-field cannot appear in a map clause.
22173 //
22174 if (FD->isBitField()) {
22175 if (!NoDiagnose) {
22176 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
22177 << ME->getSourceRange() << getOpenMPClauseNameForDiag(CKind);
22178 return false;
22179 }
22180 if (RelevantExpr)
22181 return false;
22182 return Visit(E);
22183 }
22184
22185 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22186 // If the type of a list item is a reference to a type T then the type
22187 // will be considered to be T for all purposes of this clause.
22188 QualType CurType = BaseE->getType().getNonReferenceType();
22189
22190 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
22191 // A list item cannot be a variable that is a member of a structure with
22192 // a union type.
22193 //
22194 if (CurType->isUnionType()) {
22195 if (!NoDiagnose) {
22196 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
22197 << ME->getSourceRange();
22198 return false;
22199 }
22200 return RelevantExpr || Visit(E);
22201 }
22202
22203 // If we got a member expression, we should not expect any array section
22204 // before that:
22205 //
22206 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
22207 // If a list item is an element of a structure, only the rightmost symbol
22208 // of the variable reference can be an array section.
22209 //
22210 AllowUnitySizeArraySection = false;
22211 AllowWholeSizeArraySection = false;
22212
22213 // Record the component.
22214 Components.emplace_back(ME, FD, IsNonContiguous);
22215 return RelevantExpr || Visit(E);
22216 }
22217
22218 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
22219 Expr *E = AE->getBase()->IgnoreParenImpCasts();
22220
22221 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
22222 if (!NoDiagnose) {
22223 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22224 << 0 << AE->getSourceRange();
22225 return false;
22226 }
22227 return RelevantExpr || Visit(E);
22228 }
22229
22230 // If we got an array subscript that express the whole dimension we
22231 // can have any array expressions before. If it only expressing part of
22232 // the dimension, we can only have unitary-size array expressions.
22234 AllowWholeSizeArraySection = false;
22235
22236 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
22237 Expr::EvalResult Result;
22238 if (!AE->getIdx()->isValueDependent() &&
22239 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
22240 !Result.Val.getInt().isZero()) {
22241 SemaRef.Diag(AE->getIdx()->getExprLoc(),
22242 diag::err_omp_invalid_map_this_expr);
22243 SemaRef.Diag(AE->getIdx()->getExprLoc(),
22244 diag::note_omp_invalid_subscript_on_this_ptr_map);
22245 }
22246 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22247 RelevantExpr = TE;
22248 }
22249
22250 // Record the component - we don't have any declaration associated.
22251 Components.emplace_back(AE, nullptr, IsNonContiguous);
22252
22253 return RelevantExpr || Visit(E);
22254 }
22255
22256 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
22257 // After OMP 5.0 Array section in reduction clause will be implicitly
22258 // mapped
22259 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
22260 "Array sections cannot be implicitly mapped.");
22261 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
22262 QualType CurType =
22264
22265 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22266 // If the type of a list item is a reference to a type T then the type
22267 // will be considered to be T for all purposes of this clause.
22268 if (CurType->isReferenceType())
22269 CurType = CurType->getPointeeType();
22270
22271 bool IsPointer = CurType->isAnyPointerType();
22272
22273 if (!IsPointer && !CurType->isArrayType()) {
22274 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22275 << 0 << OASE->getSourceRange();
22276 return false;
22277 }
22278
22279 bool NotWhole =
22280 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
22281 bool NotUnity =
22282 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
22283
22284 if (AllowWholeSizeArraySection) {
22285 // Any array section is currently allowed. Allowing a whole size array
22286 // section implies allowing a unity array section as well.
22287 //
22288 // If this array section refers to the whole dimension we can still
22289 // accept other array sections before this one, except if the base is a
22290 // pointer. Otherwise, only unitary sections are accepted.
22291 if (NotWhole || IsPointer)
22292 AllowWholeSizeArraySection = false;
22293 } else if (DKind == OMPD_target_update &&
22294 SemaRef.getLangOpts().OpenMP >= 50) {
22295 if (IsPointer && !AllowAnotherPtr)
22296 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
22297 << /*array of unknown bound */ 1;
22298 else
22299 IsNonContiguous = true;
22300 } else if (AllowUnitySizeArraySection && NotUnity) {
22301 // A unity or whole array section is not allowed and that is not
22302 // compatible with the properties of the current array section.
22303 if (NoDiagnose)
22304 return false;
22305 SemaRef.Diag(ELoc,
22306 diag::err_array_section_does_not_specify_contiguous_storage)
22307 << OASE->getSourceRange();
22308 return false;
22309 }
22310
22311 if (IsPointer)
22312 AllowAnotherPtr = false;
22313
22314 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
22315 Expr::EvalResult ResultR;
22316 Expr::EvalResult ResultL;
22317 if (!OASE->getLength()->isValueDependent() &&
22318 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
22319 !ResultR.Val.getInt().isOne()) {
22320 SemaRef.Diag(OASE->getLength()->getExprLoc(),
22321 diag::err_omp_invalid_map_this_expr);
22322 SemaRef.Diag(OASE->getLength()->getExprLoc(),
22323 diag::note_omp_invalid_length_on_this_ptr_mapping);
22324 }
22325 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
22326 OASE->getLowerBound()->EvaluateAsInt(ResultL,
22327 SemaRef.getASTContext()) &&
22328 !ResultL.Val.getInt().isZero()) {
22329 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
22330 diag::err_omp_invalid_map_this_expr);
22331 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
22332 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
22333 }
22334 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22335 RelevantExpr = TE;
22336 }
22337
22338 // Record the component - we don't have any declaration associated.
22339 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
22340 return RelevantExpr || Visit(E);
22341 }
22342 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
22343 Expr *Base = E->getBase();
22344
22345 // Record the component - we don't have any declaration associated.
22346 Components.emplace_back(E, nullptr, IsNonContiguous);
22347
22348 return Visit(Base->IgnoreParenImpCasts());
22349 }
22350
22351 bool VisitUnaryOperator(UnaryOperator *UO) {
22352 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
22353 UO->getOpcode() != UO_Deref) {
22354 emitErrorMsg();
22355 return false;
22356 }
22357 if (!RelevantExpr) {
22358 // Record the component if haven't found base decl.
22359 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
22360 }
22361 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
22362 }
22363 bool VisitBinaryOperator(BinaryOperator *BO) {
22364 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
22365 emitErrorMsg();
22366 return false;
22367 }
22368
22369 // Pointer arithmetic is the only thing we expect to happen here so after we
22370 // make sure the binary operator is a pointer type, the only thing we need
22371 // to do is to visit the subtree that has the same type as root (so that we
22372 // know the other subtree is just an offset)
22373 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
22374 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
22375 Components.emplace_back(BO, nullptr, false);
22376 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
22377 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
22378 "Either LHS or RHS have base decl inside");
22379 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
22380 return RelevantExpr || Visit(LE);
22381 return RelevantExpr || Visit(RE);
22382 }
22383 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
22384 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22385 RelevantExpr = CTE;
22386 Components.emplace_back(CTE, nullptr, IsNonContiguous);
22387 return true;
22388 }
22389 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
22390 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22391 Components.emplace_back(COCE, nullptr, IsNonContiguous);
22392 return true;
22393 }
22394 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
22395 Expr *Source = E->getSourceExpr();
22396 if (!Source) {
22397 emitErrorMsg();
22398 return false;
22399 }
22400 return Visit(Source);
22401 }
22402 bool VisitStmt(Stmt *) {
22403 emitErrorMsg();
22404 return false;
22405 }
22406 const Expr *getFoundBase() const { return RelevantExpr; }
22407 explicit MapBaseChecker(
22408 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
22410 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
22411 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
22412 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
22413};
22414} // namespace
22415
22416/// Return the expression of the base of the mappable expression or null if it
22417/// cannot be determined and do all the necessary checks to see if the
22418/// expression is valid as a standalone mappable expression. In the process,
22419/// record all the components of the expression.
22421 Sema &SemaRef, Expr *E,
22423 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
22424 SourceLocation ELoc = E->getExprLoc();
22425 SourceRange ERange = E->getSourceRange();
22426 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
22427 ERange);
22428 if (Checker.Visit(E->IgnoreParens())) {
22429 // Check if the highest dimension array section has length specified
22430 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
22431 (CKind == OMPC_to || CKind == OMPC_from)) {
22432 auto CI = CurComponents.rbegin();
22433 auto CE = CurComponents.rend();
22434 for (; CI != CE; ++CI) {
22435 const auto *OASE =
22436 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
22437 if (!OASE)
22438 continue;
22439 if (OASE && OASE->getLength())
22440 break;
22441 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
22442 << ERange;
22443 }
22444 }
22445 return Checker.getFoundBase();
22446 }
22447 return nullptr;
22448}
22449
22450// Return true if expression E associated with value VD has conflicts with other
22451// map information.
22453 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
22454 bool CurrentRegionOnly,
22456 OpenMPClauseKind CKind) {
22457 assert(VD && E);
22458 SourceLocation ELoc = E->getExprLoc();
22459 SourceRange ERange = E->getSourceRange();
22460
22461 // In order to easily check the conflicts we need to match each component of
22462 // the expression under test with the components of the expressions that are
22463 // already in the stack.
22464
22465 assert(!CurComponents.empty() && "Map clause expression with no components!");
22466 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
22467 "Map clause expression with unexpected base!");
22468
22469 // Variables to help detecting enclosing problems in data environment nests.
22470 bool IsEnclosedByDataEnvironmentExpr = false;
22471 const Expr *EnclosingExpr = nullptr;
22472
22473 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
22474 VD, CurrentRegionOnly,
22475 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
22476 ERange, CKind, &EnclosingExpr,
22478 StackComponents,
22479 OpenMPClauseKind Kind) {
22480 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
22481 return false;
22482 assert(!StackComponents.empty() &&
22483 "Map clause expression with no components!");
22484 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
22485 "Map clause expression with unexpected base!");
22486 (void)VD;
22487
22488 // The whole expression in the stack.
22489 const Expr *RE = StackComponents.front().getAssociatedExpression();
22490
22491 // Expressions must start from the same base. Here we detect at which
22492 // point both expressions diverge from each other and see if we can
22493 // detect if the memory referred to both expressions is contiguous and
22494 // do not overlap.
22495 auto CI = CurComponents.rbegin();
22496 auto CE = CurComponents.rend();
22497 auto SI = StackComponents.rbegin();
22498 auto SE = StackComponents.rend();
22499 for (; CI != CE && SI != SE; ++CI, ++SI) {
22500
22501 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
22502 // At most one list item can be an array item derived from a given
22503 // variable in map clauses of the same construct.
22504 if (CurrentRegionOnly &&
22505 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
22506 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
22507 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
22508 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
22509 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
22510 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
22511 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
22512 diag::err_omp_multiple_array_items_in_map_clause)
22513 << CI->getAssociatedExpression()->getSourceRange();
22514 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
22515 diag::note_used_here)
22516 << SI->getAssociatedExpression()->getSourceRange();
22517 return true;
22518 }
22519
22520 // Do both expressions have the same kind?
22521 if (CI->getAssociatedExpression()->getStmtClass() !=
22522 SI->getAssociatedExpression()->getStmtClass())
22523 break;
22524
22525 // Are we dealing with different variables/fields?
22526 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
22527 break;
22528 }
22529 // Check if the extra components of the expressions in the enclosing
22530 // data environment are redundant for the current base declaration.
22531 // If they are, the maps completely overlap, which is legal.
22532 for (; SI != SE; ++SI) {
22533 QualType Type;
22534 if (const auto *ASE =
22535 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
22536 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
22537 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
22538 SI->getAssociatedExpression())) {
22539 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
22541 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
22542 SI->getAssociatedExpression())) {
22543 Type = OASE->getBase()->getType()->getPointeeType();
22544 }
22545 if (Type.isNull() || Type->isAnyPointerType() ||
22547 SemaRef, SI->getAssociatedExpression(), Type))
22548 break;
22549 }
22550
22551 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
22552 // List items of map clauses in the same construct must not share
22553 // original storage.
22554 //
22555 // If the expressions are exactly the same or one is a subset of the
22556 // other, it means they are sharing storage.
22557 if (CI == CE && SI == SE) {
22558 if (CurrentRegionOnly) {
22559 if (CKind == OMPC_map) {
22560 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22561 } else {
22562 assert(CKind == OMPC_to || CKind == OMPC_from);
22563 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22564 << ERange;
22565 }
22566 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22567 << RE->getSourceRange();
22568 return true;
22569 }
22570 // If we find the same expression in the enclosing data environment,
22571 // that is legal.
22572 IsEnclosedByDataEnvironmentExpr = true;
22573 return false;
22574 }
22575
22576 QualType DerivedType =
22577 std::prev(CI)->getAssociatedDeclaration()->getType();
22578 SourceLocation DerivedLoc =
22579 std::prev(CI)->getAssociatedExpression()->getExprLoc();
22580
22581 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22582 // If the type of a list item is a reference to a type T then the type
22583 // will be considered to be T for all purposes of this clause.
22584 DerivedType = DerivedType.getNonReferenceType();
22585
22586 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
22587 // A variable for which the type is pointer and an array section
22588 // derived from that variable must not appear as list items of map
22589 // clauses of the same construct.
22590 //
22591 // Also, cover one of the cases in:
22592 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
22593 // If any part of the original storage of a list item has corresponding
22594 // storage in the device data environment, all of the original storage
22595 // must have corresponding storage in the device data environment.
22596 //
22597 if (DerivedType->isAnyPointerType()) {
22598 if (CI == CE || SI == SE) {
22599 SemaRef.Diag(
22600 DerivedLoc,
22601 diag::err_omp_pointer_mapped_along_with_derived_section)
22602 << DerivedLoc;
22603 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22604 << RE->getSourceRange();
22605 return true;
22606 }
22607 if (CI->getAssociatedExpression()->getStmtClass() !=
22608 SI->getAssociatedExpression()->getStmtClass() ||
22609 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
22610 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
22611 assert(CI != CE && SI != SE);
22612 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
22613 << DerivedLoc;
22614 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22615 << RE->getSourceRange();
22616 return true;
22617 }
22618 }
22619
22620 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
22621 // List items of map clauses in the same construct must not share
22622 // original storage.
22623 //
22624 // An expression is a subset of the other.
22625 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
22626 if (CKind == OMPC_map) {
22627 if (CI != CE || SI != SE) {
22628 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
22629 // a pointer.
22630 auto Begin =
22631 CI != CE ? CurComponents.begin() : StackComponents.begin();
22632 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
22633 auto It = Begin;
22634 while (It != End && !It->getAssociatedDeclaration())
22635 std::advance(It, 1);
22636 assert(It != End &&
22637 "Expected at least one component with the declaration.");
22638 if (It != Begin && It->getAssociatedDeclaration()
22639 ->getType()
22640 .getCanonicalType()
22641 ->isAnyPointerType()) {
22642 IsEnclosedByDataEnvironmentExpr = false;
22643 EnclosingExpr = nullptr;
22644 return false;
22645 }
22646 }
22647 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22648 } else {
22649 assert(CKind == OMPC_to || CKind == OMPC_from);
22650 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22651 << ERange;
22652 }
22653 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22654 << RE->getSourceRange();
22655 return true;
22656 }
22657
22658 // The current expression uses the same base as other expression in the
22659 // data environment but does not contain it completely.
22660 if (!CurrentRegionOnly && SI != SE)
22661 EnclosingExpr = RE;
22662
22663 // The current expression is a subset of the expression in the data
22664 // environment.
22665 IsEnclosedByDataEnvironmentExpr |=
22666 (!CurrentRegionOnly && CI != CE && SI == SE);
22667
22668 return false;
22669 });
22670
22671 if (CurrentRegionOnly)
22672 return FoundError;
22673
22674 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
22675 // If any part of the original storage of a list item has corresponding
22676 // storage in the device data environment, all of the original storage must
22677 // have corresponding storage in the device data environment.
22678 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
22679 // If a list item is an element of a structure, and a different element of
22680 // the structure has a corresponding list item in the device data environment
22681 // prior to a task encountering the construct associated with the map clause,
22682 // then the list item must also have a corresponding list item in the device
22683 // data environment prior to the task encountering the construct.
22684 //
22685 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
22686 SemaRef.Diag(ELoc,
22687 diag::err_omp_original_storage_is_shared_and_does_not_contain)
22688 << ERange;
22689 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
22690 << EnclosingExpr->getSourceRange();
22691 return true;
22692 }
22693
22694 return FoundError;
22695}
22696
22697// Look up the user-defined mapper given the mapper name and mapped type, and
22698// build a reference to it.
22700 CXXScopeSpec &MapperIdScopeSpec,
22701 const DeclarationNameInfo &MapperId,
22702 QualType Type,
22703 Expr *UnresolvedMapper) {
22704 if (MapperIdScopeSpec.isInvalid())
22705 return ExprError();
22706 // Get the actual type for the array type.
22707 if (Type->isArrayType()) {
22708 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
22710 }
22711 // Find all user-defined mappers with the given MapperId.
22712 SmallVector<UnresolvedSet<8>, 4> Lookups;
22713 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
22714 Lookup.suppressDiagnostics();
22715 if (S) {
22716 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
22717 /*ObjectType=*/QualType())) {
22718 NamedDecl *D = Lookup.getRepresentativeDecl();
22719 while (S && !S->isDeclScope(D))
22720 S = S->getParent();
22721 if (S)
22722 S = S->getParent();
22723 Lookups.emplace_back();
22724 Lookups.back().append(Lookup.begin(), Lookup.end());
22725 Lookup.clear();
22726 }
22727 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
22728 // Extract the user-defined mappers with the given MapperId.
22729 Lookups.push_back(UnresolvedSet<8>());
22730 for (NamedDecl *D : ULE->decls()) {
22731 auto *DMD = cast<OMPDeclareMapperDecl>(D);
22732 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
22733 Lookups.back().addDecl(DMD);
22734 }
22735 }
22736 // Defer the lookup for dependent types. The results will be passed through
22737 // UnresolvedMapper on instantiation.
22738 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
22742 return !D->isInvalidDecl() &&
22743 (D->getType()->isDependentType() ||
22744 D->getType()->isInstantiationDependentType() ||
22745 D->getType()->containsUnexpandedParameterPack());
22746 })) {
22747 UnresolvedSet<8> URS;
22748 for (const UnresolvedSet<8> &Set : Lookups) {
22749 if (Set.empty())
22750 continue;
22751 URS.append(Set.begin(), Set.end());
22752 }
22754 SemaRef.Context, /*NamingClass=*/nullptr,
22755 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
22756 /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false,
22757 /*KnownInstantiationDependent=*/false);
22758 }
22759 SourceLocation Loc = MapperId.getLoc();
22760 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22761 // The type must be of struct, union or class type in C and C++
22763 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
22764 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
22765 return ExprError();
22766 }
22767 // Perform argument dependent lookup.
22768 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
22769 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
22770 // Return the first user-defined mapper with the desired type.
22772 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
22773 if (!D->isInvalidDecl() &&
22774 SemaRef.Context.hasSameType(D->getType(), Type))
22775 return D;
22776 return nullptr;
22777 }))
22778 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
22779 // Find the first user-defined mapper with a type derived from the desired
22780 // type.
22782 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
22783 if (!D->isInvalidDecl() &&
22784 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
22785 !Type.isMoreQualifiedThan(D->getType(),
22786 SemaRef.getASTContext()))
22787 return D;
22788 return nullptr;
22789 })) {
22790 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
22791 /*DetectVirtual=*/false);
22792 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
22793 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
22794 VD->getType().getUnqualifiedType()))) {
22795 if (SemaRef.CheckBaseClassAccess(
22796 Loc, VD->getType(), Type, Paths.front(),
22797 /*DiagID=*/0) != Sema::AR_inaccessible) {
22798 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
22799 }
22800 }
22801 }
22802 }
22803 // Report error if a mapper is specified, but cannot be found.
22804 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
22805 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
22806 << Type << MapperId.getName();
22807 return ExprError();
22808 }
22809 return ExprEmpty();
22810}
22811
22812namespace {
22813// Utility struct that gathers all the related lists associated with a mappable
22814// expression.
22815struct MappableVarListInfo {
22816 // The list of expressions.
22817 ArrayRef<Expr *> VarList;
22818 // The list of processed expressions.
22819 SmallVector<Expr *, 16> ProcessedVarList;
22820 // The mappble components for each expression.
22822 // The base declaration of the variable.
22823 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
22824 // The reference to the user-defined mapper associated with every expression.
22825 SmallVector<Expr *, 16> UDMapperList;
22826
22827 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
22828 // We have a list of components and base declarations for each entry in the
22829 // variable list.
22830 VarComponents.reserve(VarList.size());
22831 VarBaseDeclarations.reserve(VarList.size());
22832 }
22833};
22834} // namespace
22835
22837 DSAStackTy *Stack,
22839
22840 const RecordDecl *RD = BaseType->getAsRecordDecl();
22841 SourceRange Range = RD->getSourceRange();
22842 DeclarationNameInfo ImplicitName;
22843 // Dummy variable _s for Mapper.
22844 VarDecl *VD = buildVarDecl(S, Range.getEnd(), BaseType, "_s");
22845 DeclRefExpr *MapperVarRef =
22846 buildDeclRefExpr(S, VD, BaseType, SourceLocation());
22847
22848 // Create implicit map clause for mapper.
22850 for (auto *FD : RD->fields()) {
22851 Expr *BE = S.BuildMemberExpr(
22852 MapperVarRef, /*IsArrow=*/false, Range.getBegin(),
22853 NestedNameSpecifierLoc(), Range.getBegin(), FD,
22855 /*HadMultipleCandidates=*/false,
22857 FD->getType(), VK_LValue, OK_Ordinary);
22858 SExprs.push_back(BE);
22859 }
22860 CXXScopeSpec MapperIdScopeSpec;
22861 DeclarationNameInfo MapperId;
22862 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
22863
22864 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
22865 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec,
22866 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
22867 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), SExprs,
22868 OMPVarListLocTy());
22869 Maps.push_back(MapClause);
22870 return MapperVarRef;
22871}
22872
22874 DSAStackTy *Stack) {
22875
22876 // Build impilicit map for mapper
22878 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
22879
22880 const RecordDecl *RD = BaseType->getAsRecordDecl();
22881 // AST context is RD's ParentASTContext().
22882 ASTContext &Ctx = RD->getParentASTContext();
22883 // DeclContext is RD's DeclContext.
22884 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
22885
22886 // Create implicit default mapper for "RD".
22887 DeclarationName MapperId;
22888 auto &DeclNames = Ctx.DeclarationNames;
22889 MapperId = DeclNames.getIdentifier(&Ctx.Idents.get("default"));
22890 auto *DMD = OMPDeclareMapperDecl::Create(Ctx, DCT, SourceLocation(), MapperId,
22891 BaseType, MapperId, Maps, nullptr);
22892 Scope *Scope = S.getScopeForContext(DCT);
22893 if (Scope)
22894 S.PushOnScopeChains(DMD, Scope, /*AddToContext=*/false);
22895 DCT->addDecl(DMD);
22896 DMD->setAccess(clang::AS_none);
22897 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22898 VD->setDeclContext(DMD);
22899 VD->setLexicalDeclContext(DMD);
22900 DMD->addDecl(VD);
22901 DMD->setMapperVarRef(MapperVarRef);
22902 FieldDecl *FD = *RD->field_begin();
22903 // create mapper refence.
22905 DMD, false, SourceLocation(), BaseType, VK_LValue);
22906}
22907
22908// Look up the user-defined mapper given the mapper name and mapper type,
22909// return true if found one.
22910static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
22911 CXXScopeSpec &MapperIdScopeSpec,
22912 const DeclarationNameInfo &MapperId,
22913 QualType Type) {
22914 // Find all user-defined mappers with the given MapperId.
22915 SmallVector<UnresolvedSet<8>, 4> Lookups;
22916 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
22917 Lookup.suppressDiagnostics();
22918 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
22919 /*ObjectType=*/QualType())) {
22920 NamedDecl *D = Lookup.getRepresentativeDecl();
22921 while (S && !S->isDeclScope(D))
22922 S = S->getParent();
22923 if (S)
22924 S = S->getParent();
22925 Lookups.emplace_back();
22926 Lookups.back().append(Lookup.begin(), Lookup.end());
22927 Lookup.clear();
22928 }
22929 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
22933 return !D->isInvalidDecl() &&
22934 (D->getType()->isDependentType() ||
22935 D->getType()->isInstantiationDependentType() ||
22936 D->getType()->containsUnexpandedParameterPack());
22937 }))
22938 return false;
22939 // Perform argument dependent lookup.
22940 SourceLocation Loc = MapperId.getLoc();
22941 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
22942 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
22944 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
22945 if (!D->isInvalidDecl() &&
22946 SemaRef.Context.hasSameType(D->getType(), Type))
22947 return D;
22948 return nullptr;
22949 }))
22950 return true;
22951 // Find the first user-defined mapper with a type derived from the desired
22952 // type.
22954 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
22955 if (!D->isInvalidDecl() &&
22956 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
22957 !Type.isMoreQualifiedThan(D->getType(), SemaRef.getASTContext()))
22958 return D;
22959 return nullptr;
22960 });
22961 if (!VD)
22962 return false;
22963 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
22964 /*DetectVirtual=*/false);
22965 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
22966 bool IsAmbiguous = !Paths.isAmbiguous(
22968 if (IsAmbiguous)
22969 return false;
22970 if (SemaRef.CheckBaseClassAccess(Loc, VD->getType(), Type, Paths.front(),
22971 /*DiagID=*/0) != Sema::AR_inaccessible)
22972 return true;
22973 }
22974 return false;
22975}
22976
22977static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
22978 QualType CanonType, const Expr *E) {
22979
22980 // DFS over data members in structures/classes.
22982 {CanonType, nullptr});
22983 llvm::DenseMap<const Type *, bool> Visited;
22984 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
22985 while (!Types.empty()) {
22986 auto [BaseType, CurFD] = Types.pop_back_val();
22987 while (ParentChain.back().second == 0)
22988 ParentChain.pop_back();
22989 --ParentChain.back().second;
22990 if (BaseType.isNull())
22991 continue;
22992 // Only structs/classes are allowed to have mappers.
22993 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
22994 if (!RD)
22995 continue;
22996 auto It = Visited.find(BaseType.getTypePtr());
22997 if (It == Visited.end()) {
22998 // Try to find the associated user-defined mapper.
22999 CXXScopeSpec MapperIdScopeSpec;
23000 DeclarationNameInfo DefaultMapperId;
23002 &S.Context.Idents.get("default")));
23003 DefaultMapperId.setLoc(E->getExprLoc());
23004 bool HasUDMapper =
23005 hasUserDefinedMapper(S, Stack->getCurScope(), MapperIdScopeSpec,
23006 DefaultMapperId, BaseType);
23007 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
23008 }
23009 // Found default mapper.
23010 if (It->second)
23011 return true;
23012 // Check for the "default" mapper for data members.
23013 bool FirstIter = true;
23014 for (FieldDecl *FD : RD->fields()) {
23015 if (!FD)
23016 continue;
23017 QualType FieldTy = FD->getType();
23018 if (FieldTy.isNull() ||
23019 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
23020 continue;
23021 if (FirstIter) {
23022 FirstIter = false;
23023 ParentChain.emplace_back(CurFD, 1);
23024 } else {
23025 ++ParentChain.back().second;
23026 }
23027 Types.emplace_back(FieldTy, FD);
23028 }
23029 }
23030 return false;
23031}
23032
23033// Check the validity of the provided variable list for the provided clause kind
23034// \a CKind. In the check process the valid expressions, mappable expression
23035// components, variables, and user-defined mappers are extracted and used to
23036// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
23037// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
23038// and \a MapperId are expected to be valid if the clause kind is 'map'.
23040 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
23041 MappableVarListInfo &MVLI, SourceLocation StartLoc,
23042 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
23043 ArrayRef<Expr *> UnresolvedMappers,
23045 ArrayRef<OpenMPMapModifierKind> Modifiers = {},
23046 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
23047 // We only expect mappable expressions in 'to', 'from', 'map', and
23048 // 'use_device_addr' clauses.
23049 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from ||
23050 CKind == OMPC_use_device_addr) &&
23051 "Unexpected clause kind with mappable expressions!");
23052 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
23053
23054 // If the identifier of user-defined mapper is not specified, it is "default".
23055 // We do not change the actual name in this clause to distinguish whether a
23056 // mapper is specified explicitly, i.e., it is not explicitly specified when
23057 // MapperId.getName() is empty.
23058 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
23059 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
23060 MapperId.setName(DeclNames.getIdentifier(
23061 &SemaRef.getASTContext().Idents.get("default")));
23062 MapperId.setLoc(StartLoc);
23063 }
23064
23065 // Iterators to find the current unresolved mapper expression.
23066 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
23067 bool UpdateUMIt = false;
23068 Expr *UnresolvedMapper = nullptr;
23069
23070 bool HasHoldModifier =
23071 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
23072
23073 // Keep track of the mappable components and base declarations in this clause.
23074 // Each entry in the list is going to have a list of components associated. We
23075 // record each set of the components so that we can build the clause later on.
23076 // In the end we should have the same amount of declarations and component
23077 // lists.
23078
23079 for (Expr *RE : MVLI.VarList) {
23080 assert(RE && "Null expr in omp to/from/map clause");
23081 SourceLocation ELoc = RE->getExprLoc();
23082
23083 // Find the current unresolved mapper expression.
23084 if (UpdateUMIt && UMIt != UMEnd) {
23085 UMIt++;
23086 assert(
23087 UMIt != UMEnd &&
23088 "Expect the size of UnresolvedMappers to match with that of VarList");
23089 }
23090 UpdateUMIt = true;
23091 if (UMIt != UMEnd)
23092 UnresolvedMapper = *UMIt;
23093
23094 const Expr *VE = RE->IgnoreParenLValueCasts();
23095
23096 if (VE->isValueDependent() || VE->isTypeDependent() ||
23097 VE->isInstantiationDependent() ||
23098 VE->containsUnexpandedParameterPack()) {
23099 // Try to find the associated user-defined mapper.
23101 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23102 VE->getType().getCanonicalType(), UnresolvedMapper);
23103 if (ER.isInvalid())
23104 continue;
23105 MVLI.UDMapperList.push_back(ER.get());
23106 // We can only analyze this information once the missing information is
23107 // resolved.
23108 MVLI.ProcessedVarList.push_back(RE);
23109 continue;
23110 }
23111
23113
23114 if (!RE->isLValue()) {
23115 if (SemaRef.getLangOpts().OpenMP < 50) {
23116 SemaRef.Diag(
23117 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
23118 << RE->getSourceRange();
23119 } else {
23120 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
23121 << getOpenMPClauseNameForDiag(CKind) << RE->getSourceRange();
23122 }
23123 continue;
23124 }
23125
23127 ValueDecl *CurDeclaration = nullptr;
23128
23129 // Obtain the array or member expression bases if required. Also, fill the
23130 // components array with all the components identified in the process.
23131 const Expr *BE =
23132 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
23133 DSAS->getCurrentDirective(), NoDiagnose);
23134 if (!BE)
23135 continue;
23136
23137 assert(!CurComponents.empty() &&
23138 "Invalid mappable expression information.");
23139
23140 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
23141 // Add store "this" pointer to class in DSAStackTy for future checking
23142 DSAS->addMappedClassesQualTypes(TE->getType());
23143 // Try to find the associated user-defined mapper.
23145 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23146 VE->getType().getCanonicalType(), UnresolvedMapper);
23147 if (ER.isInvalid())
23148 continue;
23149 MVLI.UDMapperList.push_back(ER.get());
23150 // Skip restriction checking for variable or field declarations
23151 MVLI.ProcessedVarList.push_back(RE);
23152 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23153 MVLI.VarComponents.back().append(CurComponents.begin(),
23154 CurComponents.end());
23155 MVLI.VarBaseDeclarations.push_back(nullptr);
23156 continue;
23157 }
23158
23159 // For the following checks, we rely on the base declaration which is
23160 // expected to be associated with the last component. The declaration is
23161 // expected to be a variable or a field (if 'this' is being mapped).
23162 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
23163 assert(CurDeclaration && "Null decl on map clause.");
23164 assert(
23165 CurDeclaration->isCanonicalDecl() &&
23166 "Expecting components to have associated only canonical declarations.");
23167
23168 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
23169 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
23170
23171 assert((VD || FD) && "Only variables or fields are expected here!");
23172 (void)FD;
23173
23174 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
23175 // threadprivate variables cannot appear in a map clause.
23176 // OpenMP 4.5 [2.10.5, target update Construct]
23177 // threadprivate variables cannot appear in a from clause.
23178 if (VD && DSAS->isThreadPrivate(VD)) {
23179 if (NoDiagnose)
23180 continue;
23181 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
23182 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
23184 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
23185 continue;
23186 }
23187
23188 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
23189 // A list item cannot appear in both a map clause and a data-sharing
23190 // attribute clause on the same construct.
23191
23192 // Check conflicts with other map clause expressions. We check the conflicts
23193 // with the current construct separately from the enclosing data
23194 // environment, because the restrictions are different. We only have to
23195 // check conflicts across regions for the map clauses.
23196 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
23197 /*CurrentRegionOnly=*/true, CurComponents, CKind))
23198 break;
23199 if (CKind == OMPC_map &&
23200 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
23201 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
23202 /*CurrentRegionOnly=*/false, CurComponents, CKind))
23203 break;
23204
23205 // OpenMP 4.5 [2.10.5, target update Construct]
23206 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
23207 // If the type of a list item is a reference to a type T then the type will
23208 // be considered to be T for all purposes of this clause.
23209 auto I = llvm::find_if(
23210 CurComponents,
23211 [](const OMPClauseMappableExprCommon::MappableComponent &MC) {
23212 return MC.getAssociatedDeclaration();
23213 });
23214 assert(I != CurComponents.end() && "Null decl on map clause.");
23215 (void)I;
23216 QualType Type;
23217 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
23218 auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens());
23219 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
23220 if (ASE) {
23221 Type = ASE->getType().getNonReferenceType();
23222 } else if (OASE) {
23223 QualType BaseType =
23225 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
23226 Type = ATy->getElementType();
23227 else
23228 Type = BaseType->getPointeeType();
23229 Type = Type.getNonReferenceType();
23230 } else if (OAShE) {
23231 Type = OAShE->getBase()->getType()->getPointeeType();
23232 } else {
23233 Type = VE->getType();
23234 }
23235
23236 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
23237 // A list item in a to or from clause must have a mappable type.
23238 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
23239 // A list item must have a mappable type.
23240 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
23241 DSAS, Type, /*FullCheck=*/true))
23242 continue;
23243
23244 if (CKind == OMPC_map) {
23245 // target enter data
23246 // OpenMP [2.10.2, Restrictions, p. 99]
23247 // A map-type must be specified in all map clauses and must be either
23248 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
23249 // no map type is present.
23250 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
23251 if (DKind == OMPD_target_enter_data &&
23252 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
23253 SemaRef.getLangOpts().OpenMP >= 52)) {
23254 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23255 << (IsMapTypeImplicit ? 1 : 0)
23256 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
23257 << getOpenMPDirectiveName(DKind, OMPVersion);
23258 continue;
23259 }
23260
23261 // target exit_data
23262 // OpenMP [2.10.3, Restrictions, p. 102]
23263 // A map-type must be specified in all map clauses and must be either
23264 // from, release, or delete. Starting with OpenMP 5.2 the default map
23265 // type is `from` if no map type is present.
23266 if (DKind == OMPD_target_exit_data &&
23267 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
23268 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
23269 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23270 << (IsMapTypeImplicit ? 1 : 0)
23271 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
23272 << getOpenMPDirectiveName(DKind, OMPVersion);
23273 continue;
23274 }
23275
23276 // The 'ompx_hold' modifier is specifically intended to be used on a
23277 // 'target' or 'target data' directive to prevent data from being unmapped
23278 // during the associated statement. It is not permitted on a 'target
23279 // enter data' or 'target exit data' directive, which have no associated
23280 // statement.
23281 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
23282 HasHoldModifier) {
23283 SemaRef.Diag(StartLoc,
23284 diag::err_omp_invalid_map_type_modifier_for_directive)
23286 OMPC_MAP_MODIFIER_ompx_hold)
23287 << getOpenMPDirectiveName(DKind, OMPVersion);
23288 continue;
23289 }
23290
23291 // target, target data
23292 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
23293 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
23294 // A map-type in a map clause must be to, from, tofrom or alloc
23295 if ((DKind == OMPD_target_data ||
23297 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
23298 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
23299 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23300 << (IsMapTypeImplicit ? 1 : 0)
23301 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
23302 << getOpenMPDirectiveName(DKind, OMPVersion);
23303 continue;
23304 }
23305
23306 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
23307 // A list item cannot appear in both a map clause and a data-sharing
23308 // attribute clause on the same construct
23309 //
23310 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
23311 // A list item cannot appear in both a map clause and a data-sharing
23312 // attribute clause on the same construct unless the construct is a
23313 // combined construct.
23314 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
23316 DKind == OMPD_target)) {
23317 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
23318 if (isOpenMPPrivate(DVar.CKind)) {
23319 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23320 << getOpenMPClauseNameForDiag(DVar.CKind)
23321 << getOpenMPClauseNameForDiag(OMPC_map)
23322 << getOpenMPDirectiveName(DSAS->getCurrentDirective(),
23323 OMPVersion);
23324 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
23325 continue;
23326 }
23327 }
23328 }
23329
23330 // Try to find the associated user-defined mapper.
23332 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23333 Type.getCanonicalType(), UnresolvedMapper);
23334 if (ER.isInvalid())
23335 continue;
23336
23337 // If no user-defined mapper is found, we need to create an implicit one for
23338 // arrays/array-sections on structs that have members that have
23339 // user-defined mappers. This is needed to ensure that the mapper for the
23340 // member is invoked when mapping each element of the array/array-section.
23341 if (!ER.get()) {
23342 QualType BaseType;
23343
23345 BaseType = VE->getType().getCanonicalType();
23346 if (BaseType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
23347 const auto *OASE = cast<ArraySectionExpr>(VE->IgnoreParenImpCasts());
23348 QualType BType =
23350 QualType ElemType;
23351 if (const auto *ATy = BType->getAsArrayTypeUnsafe())
23352 ElemType = ATy->getElementType();
23353 else
23354 ElemType = BType->getPointeeType();
23355 BaseType = ElemType.getCanonicalType();
23356 }
23357 } else if (VE->getType()->isArrayType()) {
23358 const ArrayType *AT = VE->getType()->getAsArrayTypeUnsafe();
23359 const QualType ElemType = AT->getElementType();
23360 BaseType = ElemType.getCanonicalType();
23361 }
23362
23363 if (!BaseType.isNull() && BaseType->getAsRecordDecl() &&
23364 isImplicitMapperNeeded(SemaRef, DSAS, BaseType, VE)) {
23365 ER = buildImplicitMapper(SemaRef, BaseType, DSAS);
23366 }
23367 }
23368 MVLI.UDMapperList.push_back(ER.get());
23369
23370 // Save the current expression.
23371 MVLI.ProcessedVarList.push_back(RE);
23372
23373 // Store the components in the stack so that they can be used to check
23374 // against other clauses later on.
23375 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
23376 /*WhereFoundClauseKind=*/OMPC_map);
23377
23378 // Save the components and declaration to create the clause. For purposes of
23379 // the clause creation, any component list that has base 'this' uses
23380 // null as base declaration.
23381 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23382 MVLI.VarComponents.back().append(CurComponents.begin(),
23383 CurComponents.end());
23384 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
23385 : CurDeclaration);
23386 }
23387}
23388
23390 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
23391 ArrayRef<SourceLocation> MapTypeModifiersLoc,
23392 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23393 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
23394 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23395 const OMPVarListLocTy &Locs, bool NoDiagnose,
23396 ArrayRef<Expr *> UnresolvedMappers) {
23397 OpenMPMapModifierKind Modifiers[] = {
23403
23404 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
23405 BuiltinType::OMPIterator))
23406 Diag(IteratorModifier->getExprLoc(),
23407 diag::err_omp_map_modifier_not_iterator);
23408
23409 // Process map-type-modifiers, flag errors for duplicate modifiers.
23410 unsigned Count = 0;
23411 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
23412 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
23413 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
23414 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
23415 continue;
23416 }
23417 assert(Count < NumberOfOMPMapClauseModifiers &&
23418 "Modifiers exceed the allowed number of map type modifiers");
23419 Modifiers[Count] = MapTypeModifiers[I];
23420 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
23421 ++Count;
23422 }
23423
23424 MappableVarListInfo MVLI(VarList);
23426 MapperIdScopeSpec, MapperId, UnresolvedMappers,
23427 MapType, Modifiers, IsMapTypeImplicit,
23428 NoDiagnose);
23429
23430 // We need to produce a map clause even if we don't have variables so that
23431 // other diagnostics related with non-existing map clauses are accurate.
23432 return OMPMapClause::Create(
23433 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23434 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
23435 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
23436 MapperId, MapType, IsMapTypeImplicit, MapLoc);
23437}
23438
23441 assert(ParsedType.isUsable());
23442
23443 QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get());
23444 if (ReductionType.isNull())
23445 return QualType();
23446
23447 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
23448 // A type name in a declare reduction directive cannot be a function type, an
23449 // array type, a reference type, or a type qualified with const, volatile or
23450 // restrict.
23451 if (ReductionType.hasQualifiers()) {
23452 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
23453 return QualType();
23454 }
23455
23456 if (ReductionType->isFunctionType()) {
23457 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
23458 return QualType();
23459 }
23460 if (ReductionType->isReferenceType()) {
23461 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
23462 return QualType();
23463 }
23464 if (ReductionType->isArrayType()) {
23465 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
23466 return QualType();
23467 }
23468 return ReductionType;
23469}
23470
23473 Scope *S, DeclContext *DC, DeclarationName Name,
23474 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
23475 AccessSpecifier AS, Decl *PrevDeclInScope) {
23477 Decls.reserve(ReductionTypes.size());
23478
23479 LookupResult Lookup(SemaRef, Name, SourceLocation(),
23481 SemaRef.forRedeclarationInCurContext());
23482 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
23483 // A reduction-identifier may not be re-declared in the current scope for the
23484 // same type or for a type that is compatible according to the base language
23485 // rules.
23486 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
23487 OMPDeclareReductionDecl *PrevDRD = nullptr;
23488 bool InCompoundScope = true;
23489 if (S != nullptr) {
23490 // Find previous declaration with the same name not referenced in other
23491 // declarations.
23492 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
23493 InCompoundScope =
23494 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
23495 SemaRef.LookupName(Lookup, S);
23496 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
23497 /*AllowInlineNamespace=*/false);
23498 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
23499 LookupResult::Filter Filter = Lookup.makeFilter();
23500 while (Filter.hasNext()) {
23501 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
23502 if (InCompoundScope) {
23503 UsedAsPrevious.try_emplace(PrevDecl, false);
23504 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
23505 UsedAsPrevious[D] = true;
23506 }
23507 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
23508 PrevDecl->getLocation();
23509 }
23510 Filter.done();
23511 if (InCompoundScope) {
23512 for (const auto &PrevData : UsedAsPrevious) {
23513 if (!PrevData.second) {
23514 PrevDRD = PrevData.first;
23515 break;
23516 }
23517 }
23518 }
23519 } else if (PrevDeclInScope != nullptr) {
23520 auto *PrevDRDInScope = PrevDRD =
23521 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
23522 do {
23523 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
23524 PrevDRDInScope->getLocation();
23525 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
23526 } while (PrevDRDInScope != nullptr);
23527 }
23528 for (const auto &TyData : ReductionTypes) {
23529 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
23530 bool Invalid = false;
23531 if (I != PreviousRedeclTypes.end()) {
23532 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
23533 << TyData.first;
23534 Diag(I->second, diag::note_previous_definition);
23535 Invalid = true;
23536 }
23537 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
23539 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
23540 DC->addDecl(DRD);
23541 DRD->setAccess(AS);
23542 Decls.push_back(DRD);
23543 if (Invalid)
23544 DRD->setInvalidDecl();
23545 else
23546 PrevDRD = DRD;
23547 }
23548
23549 return DeclGroupPtrTy::make(
23550 DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size()));
23551}
23552
23554 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23555
23556 // Enter new function scope.
23557 SemaRef.PushFunctionScope();
23558 SemaRef.setFunctionHasBranchProtectedScope();
23559 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
23560
23561 if (S != nullptr)
23562 SemaRef.PushDeclContext(S, DRD);
23563 else
23564 SemaRef.CurContext = DRD;
23565
23566 SemaRef.PushExpressionEvaluationContext(
23568
23569 QualType ReductionType = DRD->getType();
23570 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
23571 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
23572 // uses semantics of argument handles by value, but it should be passed by
23573 // reference. C lang does not support references, so pass all parameters as
23574 // pointers.
23575 // Create 'T omp_in;' variable.
23576 VarDecl *OmpInParm =
23577 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in");
23578 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
23579 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
23580 // uses semantics of argument handles by value, but it should be passed by
23581 // reference. C lang does not support references, so pass all parameters as
23582 // pointers.
23583 // Create 'T omp_out;' variable.
23584 VarDecl *OmpOutParm =
23585 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out");
23586 if (S != nullptr) {
23587 SemaRef.PushOnScopeChains(OmpInParm, S);
23588 SemaRef.PushOnScopeChains(OmpOutParm, S);
23589 } else {
23590 DRD->addDecl(OmpInParm);
23591 DRD->addDecl(OmpOutParm);
23592 }
23593 Expr *InE =
23594 ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation());
23595 Expr *OutE =
23596 ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation());
23597 DRD->setCombinerData(InE, OutE);
23598}
23599
23601 Expr *Combiner) {
23602 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23603 SemaRef.DiscardCleanupsInEvaluationContext();
23604 SemaRef.PopExpressionEvaluationContext();
23605
23606 SemaRef.PopDeclContext();
23607 SemaRef.PopFunctionScopeInfo();
23608
23609 if (Combiner != nullptr)
23610 DRD->setCombiner(Combiner);
23611 else
23612 DRD->setInvalidDecl();
23613}
23614
23616 Decl *D) {
23617 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23618
23619 // Enter new function scope.
23620 SemaRef.PushFunctionScope();
23621 SemaRef.setFunctionHasBranchProtectedScope();
23622
23623 if (S != nullptr)
23624 SemaRef.PushDeclContext(S, DRD);
23625 else
23626 SemaRef.CurContext = DRD;
23627
23628 SemaRef.PushExpressionEvaluationContext(
23630
23631 QualType ReductionType = DRD->getType();
23632 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
23633 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
23634 // uses semantics of argument handles by value, but it should be passed by
23635 // reference. C lang does not support references, so pass all parameters as
23636 // pointers.
23637 // Create 'T omp_priv;' variable.
23638 VarDecl *OmpPrivParm =
23639 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv");
23640 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
23641 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
23642 // uses semantics of argument handles by value, but it should be passed by
23643 // reference. C lang does not support references, so pass all parameters as
23644 // pointers.
23645 // Create 'T omp_orig;' variable.
23646 VarDecl *OmpOrigParm =
23647 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig");
23648 if (S != nullptr) {
23649 SemaRef.PushOnScopeChains(OmpPrivParm, S);
23650 SemaRef.PushOnScopeChains(OmpOrigParm, S);
23651 } else {
23652 DRD->addDecl(OmpPrivParm);
23653 DRD->addDecl(OmpOrigParm);
23654 }
23655 Expr *OrigE =
23656 ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation());
23657 Expr *PrivE =
23658 ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation());
23659 DRD->setInitializerData(OrigE, PrivE);
23660 return OmpPrivParm;
23661}
23662
23664 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
23665 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23666 SemaRef.DiscardCleanupsInEvaluationContext();
23667 SemaRef.PopExpressionEvaluationContext();
23668
23669 SemaRef.PopDeclContext();
23670 SemaRef.PopFunctionScopeInfo();
23671
23672 if (Initializer != nullptr) {
23673 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
23674 } else if (OmpPrivParm->hasInit()) {
23675 DRD->setInitializer(OmpPrivParm->getInit(),
23676 OmpPrivParm->isDirectInit()
23679 } else {
23680 DRD->setInvalidDecl();
23681 }
23682}
23683
23685 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
23686 for (Decl *D : DeclReductions.get()) {
23687 if (IsValid) {
23688 if (S)
23689 SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
23690 /*AddToContext=*/false);
23691 } else {
23692 D->setInvalidDecl();
23693 }
23694 }
23695 return DeclReductions;
23696}
23697
23699 Declarator &D) {
23700 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
23701 QualType T = TInfo->getType();
23702 if (D.isInvalidType())
23703 return true;
23704
23705 if (getLangOpts().CPlusPlus) {
23706 // Check that there are no default arguments (C++ only).
23707 SemaRef.CheckExtraCXXDefaultArguments(D);
23708 }
23709
23710 return SemaRef.CreateParsedType(T, TInfo);
23711}
23712
23715 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
23716
23717 QualType MapperType = SemaRef.GetTypeFromParser(ParsedType.get());
23718 assert(!MapperType.isNull() && "Expect valid mapper type");
23719
23720 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
23721 // The type must be of struct, union or class type in C and C++
23722 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
23723 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
23724 return QualType();
23725 }
23726 return MapperType;
23727}
23728
23730 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
23732 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
23733 LookupResult Lookup(SemaRef, Name, SourceLocation(),
23735 SemaRef.forRedeclarationInCurContext());
23736 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
23737 // A mapper-identifier may not be redeclared in the current scope for the
23738 // same type or for a type that is compatible according to the base language
23739 // rules.
23740 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
23741 OMPDeclareMapperDecl *PrevDMD = nullptr;
23742 bool InCompoundScope = true;
23743 if (S != nullptr) {
23744 // Find previous declaration with the same name not referenced in other
23745 // declarations.
23746 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
23747 InCompoundScope =
23748 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
23749 SemaRef.LookupName(Lookup, S);
23750 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
23751 /*AllowInlineNamespace=*/false);
23752 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
23753 LookupResult::Filter Filter = Lookup.makeFilter();
23754 while (Filter.hasNext()) {
23755 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
23756 if (InCompoundScope) {
23757 UsedAsPrevious.try_emplace(PrevDecl, false);
23758 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
23759 UsedAsPrevious[D] = true;
23760 }
23761 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
23762 PrevDecl->getLocation();
23763 }
23764 Filter.done();
23765 if (InCompoundScope) {
23766 for (const auto &PrevData : UsedAsPrevious) {
23767 if (!PrevData.second) {
23768 PrevDMD = PrevData.first;
23769 break;
23770 }
23771 }
23772 }
23773 } else if (PrevDeclInScope) {
23774 auto *PrevDMDInScope = PrevDMD =
23775 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
23776 do {
23777 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
23778 PrevDMDInScope->getLocation();
23779 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
23780 } while (PrevDMDInScope != nullptr);
23781 }
23782 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
23783 bool Invalid = false;
23784 if (I != PreviousRedeclTypes.end()) {
23785 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
23786 << MapperType << Name;
23787 Diag(I->second, diag::note_previous_definition);
23788 Invalid = true;
23789 }
23790 // Build expressions for implicit maps of data members with 'default'
23791 // mappers.
23792 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
23793 if (getLangOpts().OpenMP >= 50)
23795 ClausesWithImplicit);
23796 auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name,
23797 MapperType, VN, ClausesWithImplicit,
23798 PrevDMD);
23799 if (S)
23800 SemaRef.PushOnScopeChains(DMD, S);
23801 else
23802 DC->addDecl(DMD);
23803 DMD->setAccess(AS);
23804 if (Invalid)
23805 DMD->setInvalidDecl();
23806
23807 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
23808 VD->setDeclContext(DMD);
23809 VD->setLexicalDeclContext(DMD);
23810 DMD->addDecl(VD);
23811 DMD->setMapperVarRef(MapperVarRef);
23812
23814}
23815
23817 Scope *S, QualType MapperType, SourceLocation StartLoc,
23818 DeclarationName VN) {
23819 TypeSourceInfo *TInfo =
23820 getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc);
23821 auto *VD = VarDecl::Create(
23822 getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc,
23823 StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None);
23824 if (S)
23825 SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false);
23826 Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc);
23827 DSAStack->addDeclareMapperVarRef(E);
23828 return E;
23829}
23830
23832 bool IsGlobalVar =
23834 if (DSAStack->getDeclareMapperVarRef()) {
23835 if (IsGlobalVar)
23836 SemaRef.Consumer.HandleTopLevelDecl(DeclGroupRef(VD));
23837 DSAStack->addIteratorVarDecl(VD);
23838 } else {
23839 // Currently, only declare mapper handles global-scope iterator vars.
23840 assert(!IsGlobalVar && "Only declare mapper handles TU-scope iterators.");
23841 }
23842}
23843
23845 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
23846 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
23847 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
23848 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
23849 return true;
23851 return true;
23852 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
23853 return true;
23854 return false;
23855 }
23856 return true;
23857}
23858
23860 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
23861 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
23862}
23863
23865 SourceLocation StartLoc,
23866 SourceLocation LParenLoc,
23867 SourceLocation EndLoc) {
23868 if (VarList.empty())
23869 return nullptr;
23870
23871 for (Expr *ValExpr : VarList) {
23872 // OpenMP [teams Constrcut, Restrictions]
23873 // The num_teams expression must evaluate to a positive integer value.
23874 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams,
23875 /*StrictlyPositive=*/true))
23876 return nullptr;
23877 }
23878
23879 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23881 DKind, OMPC_num_teams, getLangOpts().OpenMP);
23882 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
23883 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
23884 LParenLoc, EndLoc, VarList,
23885 /*PreInit=*/nullptr);
23886
23887 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23889 for (Expr *ValExpr : VarList) {
23890 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23891 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23892 Vars.push_back(ValExpr);
23893 }
23894
23895 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
23896 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
23897 LParenLoc, EndLoc, Vars, PreInit);
23898}
23899
23901 SourceLocation StartLoc,
23902 SourceLocation LParenLoc,
23903 SourceLocation EndLoc) {
23904 if (VarList.empty())
23905 return nullptr;
23906
23907 for (Expr *ValExpr : VarList) {
23908 // OpenMP [teams Constrcut, Restrictions]
23909 // The thread_limit expression must evaluate to a positive integer value.
23910 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit,
23911 /*StrictlyPositive=*/true))
23912 return nullptr;
23913 }
23914
23915 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23917 DKind, OMPC_thread_limit, getLangOpts().OpenMP);
23918 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
23919 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion,
23920 StartLoc, LParenLoc, EndLoc, VarList,
23921 /*PreInit=*/nullptr);
23922
23923 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23925 for (Expr *ValExpr : VarList) {
23926 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23927 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23928 Vars.push_back(ValExpr);
23929 }
23930
23931 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
23932 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion, StartLoc,
23933 LParenLoc, EndLoc, Vars, PreInit);
23934}
23935
23937 SourceLocation StartLoc,
23938 SourceLocation LParenLoc,
23939 SourceLocation EndLoc) {
23940 Expr *ValExpr = Priority;
23941 Stmt *HelperValStmt = nullptr;
23942 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23943
23944 // OpenMP [2.9.1, task Constrcut]
23945 // The priority-value is a non-negative numerical scalar expression.
23947 ValExpr, SemaRef, OMPC_priority,
23948 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
23949 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23950 return nullptr;
23951
23952 return new (getASTContext()) OMPPriorityClause(
23953 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23954}
23955
23957 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
23958 SourceLocation StartLoc, SourceLocation LParenLoc,
23959 SourceLocation ModifierLoc, SourceLocation EndLoc) {
23960 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
23961 "Unexpected grainsize modifier in OpenMP < 51.");
23962
23963 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
23964 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
23966 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23967 << Values << getOpenMPClauseNameForDiag(OMPC_grainsize);
23968 return nullptr;
23969 }
23970
23971 Expr *ValExpr = Grainsize;
23972 Stmt *HelperValStmt = nullptr;
23973 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23974
23975 // OpenMP [2.9.2, taskloop Constrcut]
23976 // The parameter of the grainsize clause must be a positive integer
23977 // expression.
23978 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize,
23979 /*StrictlyPositive=*/true,
23980 /*BuildCapture=*/true,
23981 DSAStack->getCurrentDirective(),
23982 &CaptureRegion, &HelperValStmt))
23983 return nullptr;
23984
23985 return new (getASTContext())
23986 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
23987 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23988}
23989
23991 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
23992 SourceLocation StartLoc, SourceLocation LParenLoc,
23993 SourceLocation ModifierLoc, SourceLocation EndLoc) {
23994 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
23995 "Unexpected num_tasks modifier in OpenMP < 51.");
23996
23997 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
23998 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
24000 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
24001 << Values << getOpenMPClauseNameForDiag(OMPC_num_tasks);
24002 return nullptr;
24003 }
24004
24005 Expr *ValExpr = NumTasks;
24006 Stmt *HelperValStmt = nullptr;
24007 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
24008
24009 // OpenMP [2.9.2, taskloop Constrcut]
24010 // The parameter of the num_tasks clause must be a positive integer
24011 // expression.
24013 ValExpr, SemaRef, OMPC_num_tasks,
24014 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
24015 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
24016 return nullptr;
24017
24018 return new (getASTContext())
24019 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
24020 StartLoc, LParenLoc, ModifierLoc, EndLoc);
24021}
24022
24024 SourceLocation StartLoc,
24025 SourceLocation LParenLoc,
24026 SourceLocation EndLoc) {
24027 // OpenMP [2.13.2, critical construct, Description]
24028 // ... where hint-expression is an integer constant expression that evaluates
24029 // to a valid lock hint.
24030 ExprResult HintExpr =
24031 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
24032 if (HintExpr.isInvalid())
24033 return nullptr;
24034 return new (getASTContext())
24035 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
24036}
24037
24038/// Tries to find omp_event_handle_t type.
24040 DSAStackTy *Stack) {
24041 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
24042 if (!OMPEventHandleT.isNull())
24043 return true;
24044 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
24045 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
24046 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
24047 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
24048 return false;
24049 }
24050 Stack->setOMPEventHandleT(PT.get());
24051 return true;
24052}
24053
24055 SourceLocation StartLoc,
24056 SourceLocation LParenLoc,
24057 SourceLocation EndLoc) {
24058 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
24059 !Evt->isInstantiationDependent() &&
24062 return nullptr;
24063 // OpenMP 5.0, 2.10.1 task Construct.
24064 // event-handle is a variable of the omp_event_handle_t type.
24065 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
24066 if (!Ref) {
24067 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
24068 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
24069 return nullptr;
24070 }
24071 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
24072 if (!VD) {
24073 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
24074 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
24075 return nullptr;
24076 }
24077 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
24078 VD->getType()) ||
24079 VD->getType().isConstant(getASTContext())) {
24080 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
24081 << "omp_event_handle_t" << 1 << VD->getType()
24082 << Evt->getSourceRange();
24083 return nullptr;
24084 }
24085 // OpenMP 5.0, 2.10.1 task Construct
24086 // [detach clause]... The event-handle will be considered as if it was
24087 // specified on a firstprivate clause.
24088 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
24089 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
24090 DVar.RefExpr) {
24091 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
24092 << getOpenMPClauseNameForDiag(DVar.CKind)
24093 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
24095 return nullptr;
24096 }
24097 }
24098
24099 return new (getASTContext())
24100 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
24101}
24102
24104 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
24105 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
24106 SourceLocation EndLoc) {
24107 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
24108 std::string Values;
24109 Values += "'";
24110 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
24111 Values += "'";
24112 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24113 << Values << getOpenMPClauseNameForDiag(OMPC_dist_schedule);
24114 return nullptr;
24115 }
24116 Expr *ValExpr = ChunkSize;
24117 Stmt *HelperValStmt = nullptr;
24118 if (ChunkSize) {
24119 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
24120 !ChunkSize->isInstantiationDependent() &&
24121 !ChunkSize->containsUnexpandedParameterPack()) {
24122 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
24123 ExprResult Val =
24124 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
24125 if (Val.isInvalid())
24126 return nullptr;
24127
24128 ValExpr = Val.get();
24129
24130 // OpenMP [2.7.1, Restrictions]
24131 // chunk_size must be a loop invariant integer expression with a positive
24132 // value.
24133 if (std::optional<llvm::APSInt> Result =
24135 if (Result->isSigned() && !Result->isStrictlyPositive()) {
24136 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
24137 << "dist_schedule" << /*strictly positive*/ 1
24138 << ChunkSize->getSourceRange();
24139 return nullptr;
24140 }
24142 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
24143 getLangOpts().OpenMP) != OMPD_unknown &&
24144 !SemaRef.CurContext->isDependentContext()) {
24145 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
24146 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24147 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
24148 HelperValStmt = buildPreInits(getASTContext(), Captures);
24149 }
24150 }
24151 }
24152
24153 return new (getASTContext())
24154 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
24155 Kind, ValExpr, HelperValStmt);
24156}
24157
24160 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
24161 SourceLocation KindLoc, SourceLocation EndLoc) {
24162 if (getLangOpts().OpenMP < 50) {
24163 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
24164 Kind != OMPC_DEFAULTMAP_scalar) {
24165 std::string Value;
24166 SourceLocation Loc;
24167 Value += "'";
24168 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
24169 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
24170 OMPC_DEFAULTMAP_MODIFIER_tofrom);
24171 Loc = MLoc;
24172 } else {
24173 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
24174 OMPC_DEFAULTMAP_scalar);
24175 Loc = KindLoc;
24176 }
24177 Value += "'";
24178 Diag(Loc, diag::err_omp_unexpected_clause_value)
24179 << Value << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24180 return nullptr;
24181 }
24182 } else {
24183 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
24184 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
24185 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
24186 if (!isDefaultmapKind || !isDefaultmapModifier) {
24187 StringRef KindValue = getLangOpts().OpenMP < 52
24188 ? "'scalar', 'aggregate', 'pointer'"
24189 : "'scalar', 'aggregate', 'pointer', 'all'";
24190 if (getLangOpts().OpenMP == 50) {
24191 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
24192 "'firstprivate', 'none', 'default'";
24193 if (!isDefaultmapKind && isDefaultmapModifier) {
24194 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24195 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24196 } else if (isDefaultmapKind && !isDefaultmapModifier) {
24197 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24198 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24199 } else {
24200 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24201 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24202 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24203 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24204 }
24205 } else {
24206 StringRef ModifierValue =
24207 getLangOpts().OpenMP < 60
24208 ? "'alloc', 'from', 'to', 'tofrom', "
24209 "'firstprivate', 'none', 'default', 'present'"
24210 : "'storage', 'from', 'to', 'tofrom', "
24211 "'firstprivate', 'private', 'none', 'default', 'present'";
24212 if (!isDefaultmapKind && isDefaultmapModifier) {
24213 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24214 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24215 } else if (isDefaultmapKind && !isDefaultmapModifier) {
24216 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24217 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24218 } else {
24219 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24220 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24221 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24222 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24223 }
24224 }
24225 return nullptr;
24226 }
24227
24228 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
24229 // At most one defaultmap clause for each category can appear on the
24230 // directive.
24231 if (DSAStack->checkDefaultmapCategory(Kind)) {
24232 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
24233 return nullptr;
24234 }
24235 }
24236 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
24237 // Variable category is not specified - mark all categories.
24238 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
24239 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
24240 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
24241 } else {
24242 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
24243 }
24244
24245 return new (getASTContext())
24246 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
24247}
24248
24251 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
24252 if (!CurLexicalContext->isFileContext() &&
24253 !CurLexicalContext->isExternCContext() &&
24254 !CurLexicalContext->isExternCXXContext() &&
24255 !isa<CXXRecordDecl>(CurLexicalContext) &&
24256 !isa<ClassTemplateDecl>(CurLexicalContext) &&
24257 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
24258 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
24259 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
24260 return false;
24261 }
24262
24263 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
24264 if (getLangOpts().HIP)
24265 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
24266
24267 DeclareTargetNesting.push_back(DTCI);
24268 return true;
24269}
24270
24273 assert(!DeclareTargetNesting.empty() &&
24274 "check isInOpenMPDeclareTargetContext() first!");
24275 return DeclareTargetNesting.pop_back_val();
24276}
24277
24280 for (auto &It : DTCI.ExplicitlyMapped)
24281 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
24282}
24283
24285 if (DeclareTargetNesting.empty())
24286 return;
24287 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
24288 unsigned OMPVersion = getLangOpts().OpenMP;
24289 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
24290 << getOpenMPDirectiveName(DTCI.Kind, OMPVersion);
24291}
24292
24294 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
24296 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
24297 /*ObjectType=*/QualType(),
24298 /*AllowBuiltinCreation=*/true);
24299
24300 if (Lookup.isAmbiguous())
24301 return nullptr;
24302 Lookup.suppressDiagnostics();
24303
24304 if (!Lookup.isSingleResult()) {
24305 VarOrFuncDeclFilterCCC CCC(SemaRef);
24306 if (TypoCorrection Corrected =
24307 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
24309 SemaRef.diagnoseTypo(Corrected,
24310 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
24311 << Id.getName());
24312 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
24313 return nullptr;
24314 }
24315
24316 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
24317 return nullptr;
24318 }
24319
24320 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
24321 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
24323 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
24324 return nullptr;
24325 }
24326 return ND;
24327}
24328
24330 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
24332 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
24334 "Expected variable, function or function template.");
24335
24336 if (auto *VD = dyn_cast<VarDecl>(ND)) {
24337 // Only global variables can be marked as declare target.
24338 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24339 !VD->isStaticDataMember()) {
24340 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
24341 << VD->getNameAsString();
24342 return;
24343 }
24344 }
24345 // Diagnose marking after use as it may lead to incorrect diagnosis and
24346 // codegen.
24347 if (getLangOpts().OpenMP >= 50 &&
24348 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
24349 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
24350
24351 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
24352 if (getLangOpts().HIP)
24353 Diag(Loc, diag::warn_hip_omp_target_directives);
24354
24355 // Explicit declare target lists have precedence.
24356 const unsigned Level = -1;
24357
24358 auto *VD = cast<ValueDecl>(ND);
24359 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24360 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24361 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
24362 (*ActiveAttr)->getLevel() == Level) {
24363 Diag(Loc, diag::err_omp_device_type_mismatch)
24364 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
24365 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
24366 (*ActiveAttr)->getDevType());
24367 return;
24368 }
24369 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
24370 (*ActiveAttr)->getLevel() == Level) {
24371 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
24372 return;
24373 }
24374
24375 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
24376 return;
24377
24378 Expr *IndirectE = nullptr;
24379 bool IsIndirect = false;
24380 if (DTCI.Indirect) {
24381 IndirectE = *DTCI.Indirect;
24382 if (!IndirectE)
24383 IsIndirect = true;
24384 }
24385 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
24386 getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level,
24387 SourceRange(Loc, Loc));
24388 ND->addAttr(A);
24389 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
24390 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
24391 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
24392 if (auto *VD = dyn_cast<VarDecl>(ND);
24393 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
24394 VD->hasGlobalStorage())
24396}
24397
24399 Sema &SemaRef, Decl *D) {
24400 if (!D || !isa<VarDecl>(D))
24401 return;
24402 auto *VD = cast<VarDecl>(D);
24403 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
24404 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
24405 if (SemaRef.LangOpts.OpenMP >= 50 &&
24406 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
24407 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
24408 VD->hasGlobalStorage()) {
24409 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
24410 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
24411 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
24412 // If a lambda declaration and definition appears between a
24413 // declare target directive and the matching end declare target
24414 // directive, all variables that are captured by the lambda
24415 // expression must also appear in a to clause.
24416 SemaRef.Diag(VD->getLocation(),
24417 diag::err_omp_lambda_capture_in_declare_target_not_to);
24418 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
24419 << VD << 0 << SR;
24420 return;
24421 }
24422 }
24423 if (MapTy)
24424 return;
24425 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
24426 SemaRef.Diag(SL, diag::note_used_here) << SR;
24427}
24428
24430 Sema &SemaRef, DSAStackTy *Stack,
24431 ValueDecl *VD) {
24432 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
24433 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
24434 /*FullCheck=*/false);
24435}
24436
24438 SourceLocation IdLoc) {
24439 if (!D || D->isInvalidDecl())
24440 return;
24441 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
24442 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
24443 if (auto *VD = dyn_cast<VarDecl>(D)) {
24444 // Only global variables can be marked as declare target.
24445 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24446 !VD->isStaticDataMember())
24447 return;
24448 // 2.10.6: threadprivate variable cannot appear in a declare target
24449 // directive.
24450 if (DSAStack->isThreadPrivate(VD)) {
24451 Diag(SL, diag::err_omp_threadprivate_in_target);
24452 reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false));
24453 return;
24454 }
24455 }
24456 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
24457 D = FTD->getTemplatedDecl();
24458 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
24459 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
24460 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
24461 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
24462 Diag(IdLoc, diag::err_omp_function_in_link_clause);
24463 Diag(FD->getLocation(), diag::note_defined_here) << FD;
24464 return;
24465 }
24466 }
24467 if (auto *VD = dyn_cast<ValueDecl>(D)) {
24468 // Problem if any with var declared with incomplete type will be reported
24469 // as normal, so no need to check it here.
24470 if ((E || !VD->getType()->isIncompleteType()) &&
24472 return;
24473 if (!E && isInOpenMPDeclareTargetContext()) {
24474 // Checking declaration inside declare target region.
24475 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
24477 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24478 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24479 unsigned Level = DeclareTargetNesting.size();
24480 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
24481 return;
24482 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
24483 Expr *IndirectE = nullptr;
24484 bool IsIndirect = false;
24485 if (DTCI.Indirect) {
24486 IndirectE = *DTCI.Indirect;
24487 if (!IndirectE)
24488 IsIndirect = true;
24489 }
24490 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
24491 getASTContext(),
24492 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
24493 : OMPDeclareTargetDeclAttr::MT_To,
24494 DTCI.DT, IndirectE, IsIndirect, Level,
24495 SourceRange(DTCI.Loc, DTCI.Loc));
24496 D->addAttr(A);
24497 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
24498 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
24499 }
24500 return;
24501 }
24502 }
24503 if (!E)
24504 return;
24506}
24507
24508/// This class visits every VarDecl that the initializer references and adds
24509/// OMPDeclareTargetDeclAttr to each of them.
24510class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
24511 SmallVector<VarDecl *> DeclVector;
24512 Attr *A;
24513
24514public:
24515 /// A StmtVisitor class function that visits all DeclRefExpr and adds
24516 /// OMPDeclareTargetDeclAttr to them.
24518 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
24519 VD->addAttr(A);
24520 DeclVector.push_back(VD);
24521 }
24522 }
24523 /// A function that iterates across each of the Expr's children.
24524 void VisitExpr(Expr *Ex) {
24525 for (auto *Child : Ex->children()) {
24526 Visit(Child);
24527 }
24528 }
24529 /// A function that keeps a record of all the Decls that are variables, has
24530 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
24531 /// each Decl one at a time and use the inherited 'visit' functions to look
24532 /// for DeclRefExpr.
24534 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
24535 DeclVector.push_back(cast<VarDecl>(TD));
24536 llvm::SmallDenseSet<Decl *> Visited;
24537 while (!DeclVector.empty()) {
24538 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
24539 if (!Visited.insert(TargetVarDecl).second)
24540 continue;
24541
24542 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
24543 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
24544 if (Expr *Ex = TargetVarDecl->getInit())
24545 Visit(Ex);
24546 }
24547 }
24548 }
24549};
24550
24551/// Adding OMPDeclareTargetDeclAttr to variables with static storage
24552/// duration that are referenced in the initializer expression list of
24553/// variables with static storage duration in declare target directive.
24555 GlobalDeclRefChecker Checker;
24556 if (isa<VarDecl>(TargetDecl))
24557 Checker.declareTargetInitializer(TargetDecl);
24558}
24559
24561 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
24562 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
24563 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
24564 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
24565 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
24570
24571 // Process motion-modifiers, flag errors for duplicate modifiers.
24572 unsigned Count = 0;
24573 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
24574 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
24575 llvm::is_contained(Modifiers, MotionModifiers[I])) {
24576 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
24577 continue;
24578 }
24579 assert(Count < NumberOfOMPMotionModifiers &&
24580 "Modifiers exceed the allowed number of motion modifiers");
24581 Modifiers[Count] = MotionModifiers[I];
24582 ModifiersLoc[Count] = MotionModifiersLoc[I];
24583 ++Count;
24584 }
24585
24586 MappableVarListInfo MVLI(VarList);
24588 MapperIdScopeSpec, MapperId, UnresolvedMappers);
24589 if (MVLI.ProcessedVarList.empty())
24590 return nullptr;
24591 if (IteratorExpr)
24592 if (auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
24593 if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
24594 DSAStack->addIteratorVarDecl(VD);
24595 return OMPToClause::Create(
24596 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24597 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
24598 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
24599 MapperId);
24600}
24601
24603 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
24604 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
24605 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
24606 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
24607 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
24612
24613 // Process motion-modifiers, flag errors for duplicate modifiers.
24614 unsigned Count = 0;
24615 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
24616 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
24617 llvm::is_contained(Modifiers, MotionModifiers[I])) {
24618 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
24619 continue;
24620 }
24621 assert(Count < NumberOfOMPMotionModifiers &&
24622 "Modifiers exceed the allowed number of motion modifiers");
24623 Modifiers[Count] = MotionModifiers[I];
24624 ModifiersLoc[Count] = MotionModifiersLoc[I];
24625 ++Count;
24626 }
24627
24628 MappableVarListInfo MVLI(VarList);
24629 checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
24630 MapperIdScopeSpec, MapperId, UnresolvedMappers);
24631 if (MVLI.ProcessedVarList.empty())
24632 return nullptr;
24633 if (IteratorExpr)
24634 if (auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
24635 if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
24636 DSAStack->addIteratorVarDecl(VD);
24637 return OMPFromClause::Create(
24638 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24639 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
24640 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
24641 MapperId);
24642}
24643
24645 ArrayRef<Expr *> VarList, const OMPVarListLocTy &Locs,
24646 OpenMPUseDevicePtrFallbackModifier FallbackModifier,
24647 SourceLocation FallbackModifierLoc) {
24648 MappableVarListInfo MVLI(VarList);
24649 SmallVector<Expr *, 8> PrivateCopies;
24651
24652 for (Expr *RefExpr : VarList) {
24653 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
24654 SourceLocation ELoc;
24655 SourceRange ERange;
24656 Expr *SimpleRefExpr = RefExpr;
24657 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24658 if (Res.second) {
24659 // It will be analyzed later.
24660 MVLI.ProcessedVarList.push_back(RefExpr);
24661 PrivateCopies.push_back(nullptr);
24662 Inits.push_back(nullptr);
24663 }
24664 ValueDecl *D = Res.first;
24665 if (!D)
24666 continue;
24667
24668 QualType Type = D->getType();
24669 Type = Type.getNonReferenceType().getUnqualifiedType();
24670
24671 auto *VD = dyn_cast<VarDecl>(D);
24672
24673 // Item should be a pointer or reference to pointer.
24674 if (!Type->isPointerType()) {
24675 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
24676 << 0 << RefExpr->getSourceRange();
24677 continue;
24678 }
24679
24680 // Build the private variable and the expression that refers to it.
24681 auto VDPrivate =
24682 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
24683 D->hasAttrs() ? &D->getAttrs() : nullptr,
24684 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
24685 if (VDPrivate->isInvalidDecl())
24686 continue;
24687
24688 SemaRef.CurContext->addDecl(VDPrivate);
24689 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
24690 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
24691
24692 // Add temporary variable to initialize the private copy of the pointer.
24693 VarDecl *VDInit =
24694 buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp");
24695 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
24696 SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
24697 SemaRef.AddInitializerToDecl(
24698 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
24699 /*DirectInit=*/false);
24700
24701 // If required, build a capture to implement the privatization initialized
24702 // with the current list item value.
24703 DeclRefExpr *Ref = nullptr;
24704 if (!VD)
24705 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
24706 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
24707 PrivateCopies.push_back(VDPrivateRefExpr);
24708 Inits.push_back(VDInitRefExpr);
24709
24710 // We need to add a data sharing attribute for this variable to make sure it
24711 // is correctly captured. A variable that shows up in a use_device_ptr has
24712 // similar properties of a first private variable.
24713 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24714
24715 // Create a mappable component for the list item. List items in this clause
24716 // only need a component.
24717 MVLI.VarBaseDeclarations.push_back(D);
24718 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24719 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
24720 /*IsNonContiguous=*/false);
24721 }
24722
24723 if (MVLI.ProcessedVarList.empty())
24724 return nullptr;
24725
24727 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
24728 MVLI.VarBaseDeclarations, MVLI.VarComponents, FallbackModifier,
24729 FallbackModifierLoc);
24730}
24731
24732OMPClause *
24734 const OMPVarListLocTy &Locs) {
24735 MappableVarListInfo MVLI(VarList);
24736
24737 for (Expr *RefExpr : VarList) {
24738 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
24739 SourceLocation ELoc;
24740 SourceRange ERange;
24741 Expr *SimpleRefExpr = RefExpr;
24742 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24743 /*AllowArraySection=*/true,
24744 /*AllowAssumedSizeArray=*/true);
24745 if (Res.second) {
24746 // It will be analyzed later.
24747 MVLI.ProcessedVarList.push_back(RefExpr);
24748 }
24749 ValueDecl *D = Res.first;
24750 if (!D)
24751 continue;
24752 auto *VD = dyn_cast<VarDecl>(D);
24753
24754 // If required, build a capture to implement the privatization initialized
24755 // with the current list item value.
24756 DeclRefExpr *Ref = nullptr;
24757 if (!VD)
24758 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
24759 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
24760
24761 // We need to add a data sharing attribute for this variable to make sure it
24762 // is correctly captured. A variable that shows up in a use_device_addr has
24763 // similar properties of a first private variable.
24764 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24765
24766 // Use the map-like approach to fully populate VarComponents
24768
24770 SemaRef, RefExpr, CurComponents, OMPC_use_device_addr,
24771 DSAStack->getCurrentDirective(),
24772 /*NoDiagnose=*/false);
24773
24774 if (!BE)
24775 continue;
24776
24777 assert(!CurComponents.empty() &&
24778 "use_device_addr clause expression with no components!");
24779
24780 // OpenMP use_device_addr: If a list item is an array section, the array
24781 // base must be a base language identifier. We caught the cases where
24782 // the array-section has a base-variable in getPrivateItem. e.g.
24783 // struct S {
24784 // int a[10];
24785 // }; S s1;
24786 // ... use_device_addr(s1.a[0]) // not ok, caught already
24787 //
24788 // But we still neeed to verify that the base-pointer is also a
24789 // base-language identifier, and catch cases like:
24790 // int *pa[10]; *p;
24791 // ... use_device_addr(pa[1][2]) // not ok, base-pointer is pa[1]
24792 // ... use_device_addr(p[1]) // ok
24793 // ... use_device_addr(this->p[1]) // ok
24795 CurComponents, DSAStack->getCurrentDirective());
24796 const Expr *AttachPtrExpr = AttachPtrResult.first;
24797
24798 if (AttachPtrExpr) {
24799 const Expr *BaseExpr = AttachPtrExpr->IgnoreParenImpCasts();
24800 bool IsValidBase = false;
24801
24802 if (isa<DeclRefExpr>(BaseExpr))
24803 IsValidBase = true;
24804 else if (const auto *ME = dyn_cast<MemberExpr>(BaseExpr);
24806 IsValidBase = true;
24807
24808 if (!IsValidBase) {
24809 SemaRef.Diag(ELoc,
24810 diag::err_omp_expected_base_pointer_var_name_member_expr)
24811 << (SemaRef.getCurrentThisType().isNull() ? 0 : 1)
24812 << AttachPtrExpr->getSourceRange();
24813 continue;
24814 }
24815 }
24816
24817 // Get the declaration from the components
24818 ValueDecl *CurDeclaration = CurComponents.back().getAssociatedDeclaration();
24819 assert((isa<CXXThisExpr>(BE) || CurDeclaration) &&
24820 "Unexpected null decl for use_device_addr clause.");
24821
24822 MVLI.VarBaseDeclarations.push_back(CurDeclaration);
24823 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24824 MVLI.VarComponents.back().append(CurComponents.begin(),
24825 CurComponents.end());
24826 }
24827
24828 if (MVLI.ProcessedVarList.empty())
24829 return nullptr;
24830
24832 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24833 MVLI.VarComponents);
24834}
24835
24836OMPClause *
24838 const OMPVarListLocTy &Locs) {
24839 MappableVarListInfo MVLI(VarList);
24840 for (Expr *RefExpr : VarList) {
24841 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
24842 SourceLocation ELoc;
24843 SourceRange ERange;
24844 Expr *SimpleRefExpr = RefExpr;
24845 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24846 if (Res.second) {
24847 // It will be analyzed later.
24848 MVLI.ProcessedVarList.push_back(RefExpr);
24849 }
24850 ValueDecl *D = Res.first;
24851 if (!D)
24852 continue;
24853
24854 QualType Type = D->getType();
24855 // item should be a pointer or array or reference to pointer or array
24856 if (!Type.getNonReferenceType()->isPointerType() &&
24857 !Type.getNonReferenceType()->isArrayType()) {
24858 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
24859 << 0 << RefExpr->getSourceRange();
24860 continue;
24861 }
24862
24863 // Check if the declaration in the clause does not show up in any data
24864 // sharing attribute.
24865 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
24866 if (isOpenMPPrivate(DVar.CKind)) {
24867 unsigned OMPVersion = getLangOpts().OpenMP;
24868 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24869 << getOpenMPClauseNameForDiag(DVar.CKind)
24870 << getOpenMPClauseNameForDiag(OMPC_is_device_ptr)
24871 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
24872 OMPVersion);
24874 continue;
24875 }
24876
24877 const Expr *ConflictExpr;
24878 if (DSAStack->checkMappableExprComponentListsForDecl(
24879 D, /*CurrentRegionOnly=*/true,
24880 [&ConflictExpr](
24882 OpenMPClauseKind) -> bool {
24883 ConflictExpr = R.front().getAssociatedExpression();
24884 return true;
24885 })) {
24886 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24887 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
24888 << ConflictExpr->getSourceRange();
24889 continue;
24890 }
24891
24892 // Store the components in the stack so that they can be used to check
24893 // against other clauses later on.
24895 SimpleRefExpr, D, /*IsNonContiguous=*/false);
24896 DSAStack->addMappableExpressionComponents(
24897 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
24898
24899 // Record the expression we've just processed.
24900 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
24901
24902 // Create a mappable component for the list item. List items in this clause
24903 // only need a component. We use a null declaration to signal fields in
24904 // 'this'.
24905 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
24906 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
24907 "Unexpected device pointer expression!");
24908 MVLI.VarBaseDeclarations.push_back(
24909 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
24910 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24911 MVLI.VarComponents.back().push_back(MC);
24912 }
24913
24914 if (MVLI.ProcessedVarList.empty())
24915 return nullptr;
24916
24918 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24919 MVLI.VarComponents);
24920}
24921
24922OMPClause *
24924 const OMPVarListLocTy &Locs) {
24925 MappableVarListInfo MVLI(VarList);
24926 for (Expr *RefExpr : VarList) {
24927 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
24928 SourceLocation ELoc;
24929 SourceRange ERange;
24930 Expr *SimpleRefExpr = RefExpr;
24931 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24932 /*AllowArraySection=*/true);
24933 if (Res.second) {
24934 // It will be analyzed later.
24935 MVLI.ProcessedVarList.push_back(RefExpr);
24936 }
24937 ValueDecl *D = Res.first;
24938 if (!D)
24939 continue;
24940
24941 // Check if the declaration in the clause does not show up in any data
24942 // sharing attribute.
24943 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
24944 if (isOpenMPPrivate(DVar.CKind)) {
24945 unsigned OMPVersion = getLangOpts().OpenMP;
24946 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24947 << getOpenMPClauseNameForDiag(DVar.CKind)
24948 << getOpenMPClauseNameForDiag(OMPC_has_device_addr)
24949 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
24950 OMPVersion);
24952 continue;
24953 }
24954
24955 const Expr *ConflictExpr;
24956 if (DSAStack->checkMappableExprComponentListsForDecl(
24957 D, /*CurrentRegionOnly=*/true,
24958 [&ConflictExpr](
24960 OpenMPClauseKind) -> bool {
24961 ConflictExpr = R.front().getAssociatedExpression();
24962 return true;
24963 })) {
24964 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24965 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
24966 << ConflictExpr->getSourceRange();
24967 continue;
24968 }
24969
24970 // Store the components in the stack so that they can be used to check
24971 // against other clauses later on.
24972 Expr *Component = SimpleRefExpr;
24973 auto *VD = dyn_cast<VarDecl>(D);
24974 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
24975 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
24976 Component =
24977 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
24979 Component, D, /*IsNonContiguous=*/false);
24980 DSAStack->addMappableExpressionComponents(
24981 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
24982
24983 // Record the expression we've just processed.
24984 if (!VD && !SemaRef.CurContext->isDependentContext()) {
24985 DeclRefExpr *Ref =
24986 buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
24987 assert(Ref && "has_device_addr capture failed");
24988 MVLI.ProcessedVarList.push_back(Ref);
24989 } else
24990 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
24991
24992 // Create a mappable component for the list item. List items in this clause
24993 // only need a component. We use a null declaration to signal fields in
24994 // 'this'.
24995 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
24996 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
24997 "Unexpected device pointer expression!");
24998 MVLI.VarBaseDeclarations.push_back(
24999 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
25000 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
25001 MVLI.VarComponents.back().push_back(MC);
25002 }
25003
25004 if (MVLI.ProcessedVarList.empty())
25005 return nullptr;
25006
25008 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
25009 MVLI.VarComponents);
25010}
25011
25013 Expr *Allocator, Expr *Alignment,
25014 OpenMPAllocateClauseModifier FirstAllocateModifier,
25015 SourceLocation FirstAllocateModifierLoc,
25016 OpenMPAllocateClauseModifier SecondAllocateModifier,
25017 SourceLocation SecondAllocateModifierLoc, ArrayRef<Expr *> VarList,
25018 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
25019 SourceLocation EndLoc) {
25020 if (Allocator) {
25021 // Allocator expression is dependent - skip it for now and build the
25022 // allocator when instantiated.
25023 bool AllocDependent =
25024 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
25025 Allocator->isInstantiationDependent() ||
25026 Allocator->containsUnexpandedParameterPack());
25027 if (!AllocDependent) {
25028 // OpenMP [2.11.4 allocate Clause, Description]
25029 // allocator is an expression of omp_allocator_handle_t type.
25031 return nullptr;
25032
25033 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
25034 if (AllocatorRes.isInvalid())
25035 return nullptr;
25036 AllocatorRes = SemaRef.PerformImplicitConversion(
25037 AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
25039 /*AllowExplicit=*/true);
25040 if (AllocatorRes.isInvalid())
25041 return nullptr;
25042 Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr;
25043 }
25044 } else {
25045 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
25046 // allocate clauses that appear on a target construct or on constructs in a
25047 // target region must specify an allocator expression unless a requires
25048 // directive with the dynamic_allocators clause is present in the same
25049 // compilation unit.
25050 if (getLangOpts().OpenMPIsTargetDevice &&
25051 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
25052 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
25053 }
25054 if (Alignment) {
25055 bool AlignmentDependent = Alignment->isTypeDependent() ||
25056 Alignment->isValueDependent() ||
25057 Alignment->isInstantiationDependent() ||
25059 if (!AlignmentDependent) {
25060 ExprResult AlignResult =
25061 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_allocate);
25062 Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr;
25063 }
25064 }
25065 // Analyze and build list of variables.
25067 for (Expr *RefExpr : VarList) {
25068 assert(RefExpr && "NULL expr in OpenMP allocate clause.");
25069 SourceLocation ELoc;
25070 SourceRange ERange;
25071 Expr *SimpleRefExpr = RefExpr;
25072 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
25073 if (Res.second) {
25074 // It will be analyzed later.
25075 Vars.push_back(RefExpr);
25076 }
25077 ValueDecl *D = Res.first;
25078 if (!D)
25079 continue;
25080
25081 auto *VD = dyn_cast<VarDecl>(D);
25082 DeclRefExpr *Ref = nullptr;
25083 if (!VD && !SemaRef.CurContext->isDependentContext())
25084 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
25085 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
25086 ? RefExpr->IgnoreParens()
25087 : Ref);
25088 }
25089
25090 if (Vars.empty())
25091 return nullptr;
25092
25093 if (Allocator)
25094 DSAStack->addInnerAllocatorExpr(Allocator);
25095
25097 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
25098 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
25099 SecondAllocateModifierLoc, EndLoc, Vars);
25100}
25101
25103 SourceLocation StartLoc,
25104 SourceLocation LParenLoc,
25105 SourceLocation EndLoc) {
25107 for (Expr *RefExpr : VarList) {
25108 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
25109 SourceLocation ELoc;
25110 SourceRange ERange;
25111 Expr *SimpleRefExpr = RefExpr;
25112 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
25113 if (Res.second)
25114 // It will be analyzed later.
25115 Vars.push_back(RefExpr);
25116 ValueDecl *D = Res.first;
25117 if (!D)
25118 continue;
25119
25120 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
25121 // A list-item cannot appear in more than one nontemporal clause.
25122 if (const Expr *PrevRef =
25123 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
25124 Diag(ELoc, diag::err_omp_used_in_clause_twice)
25125 << 0 << getOpenMPClauseNameForDiag(OMPC_nontemporal) << ERange;
25126 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
25127 << getOpenMPClauseNameForDiag(OMPC_nontemporal);
25128 continue;
25129 }
25130
25131 Vars.push_back(RefExpr);
25132 }
25133
25134 if (Vars.empty())
25135 return nullptr;
25136
25137 return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc,
25138 EndLoc, Vars);
25139}
25140
25142 Stmt *AStmt,
25143 SourceLocation StartLoc,
25144 SourceLocation EndLoc) {
25145 if (!AStmt)
25146 return StmtError();
25147
25148 SemaRef.setFunctionHasBranchProtectedScope();
25149
25150 return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
25151 AStmt);
25152}
25153
25155 SourceLocation StartLoc,
25156 SourceLocation LParenLoc,
25157 SourceLocation EndLoc) {
25159 for (Expr *RefExpr : VarList) {
25160 assert(RefExpr && "NULL expr in OpenMP inclusive clause.");
25161 SourceLocation ELoc;
25162 SourceRange ERange;
25163 Expr *SimpleRefExpr = RefExpr;
25164 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
25165 /*AllowArraySection=*/true);
25166 if (Res.second)
25167 // It will be analyzed later.
25168 Vars.push_back(RefExpr);
25169 ValueDecl *D = Res.first;
25170 if (!D)
25171 continue;
25172
25173 const DSAStackTy::DSAVarData DVar =
25174 DSAStack->getTopDSA(D, /*FromParent=*/true);
25175 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
25176 // A list item that appears in the inclusive or exclusive clause must appear
25177 // in a reduction clause with the inscan modifier on the enclosing
25178 // worksharing-loop, worksharing-loop SIMD, or simd construct.
25179 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
25180 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
25181 << RefExpr->getSourceRange();
25182
25183 if (DSAStack->getParentDirective() != OMPD_unknown)
25184 DSAStack->markDeclAsUsedInScanDirective(D);
25185 Vars.push_back(RefExpr);
25186 }
25187
25188 if (Vars.empty())
25189 return nullptr;
25190
25191 return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
25192 EndLoc, Vars);
25193}
25194
25196 SourceLocation StartLoc,
25197 SourceLocation LParenLoc,
25198 SourceLocation EndLoc) {
25200 for (Expr *RefExpr : VarList) {
25201 assert(RefExpr && "NULL expr in OpenMP exclusive clause.");
25202 SourceLocation ELoc;
25203 SourceRange ERange;
25204 Expr *SimpleRefExpr = RefExpr;
25205 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
25206 /*AllowArraySection=*/true);
25207 if (Res.second)
25208 // It will be analyzed later.
25209 Vars.push_back(RefExpr);
25210 ValueDecl *D = Res.first;
25211 if (!D)
25212 continue;
25213
25214 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
25215 DSAStackTy::DSAVarData DVar;
25216 if (ParentDirective != OMPD_unknown)
25217 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
25218 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
25219 // A list item that appears in the inclusive or exclusive clause must appear
25220 // in a reduction clause with the inscan modifier on the enclosing
25221 // worksharing-loop, worksharing-loop SIMD, or simd construct.
25222 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
25223 DVar.Modifier != OMPC_REDUCTION_inscan) {
25224 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
25225 << RefExpr->getSourceRange();
25226 } else {
25227 DSAStack->markDeclAsUsedInScanDirective(D);
25228 }
25229 Vars.push_back(RefExpr);
25230 }
25231
25232 if (Vars.empty())
25233 return nullptr;
25234
25235 return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
25236 EndLoc, Vars);
25237}
25238
25239/// Tries to find omp_alloctrait_t type.
25240static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
25241 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
25242 if (!OMPAlloctraitT.isNull())
25243 return true;
25244 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
25245 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
25246 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
25247 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
25248 return false;
25249 }
25250 Stack->setOMPAlloctraitT(PT.get());
25251 return true;
25252}
25253
25255 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
25257 ASTContext &Context = getASTContext();
25258 // OpenMP [2.12.5, target Construct]
25259 // allocator is an identifier of omp_allocator_handle_t type.
25260 if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack))
25261 return nullptr;
25262 // OpenMP [2.12.5, target Construct]
25263 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
25264 if (llvm::any_of(
25265 Data,
25266 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
25267 !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack))
25268 return nullptr;
25269 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
25270 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
25271 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
25272 StringRef Allocator =
25273 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
25274 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
25275 PredefinedAllocators.insert(SemaRef.LookupSingleName(
25276 SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
25277 }
25278
25280 for (const UsesAllocatorsData &D : Data) {
25281 Expr *AllocatorExpr = nullptr;
25282 // Check allocator expression.
25283 if (D.Allocator->isTypeDependent()) {
25284 AllocatorExpr = D.Allocator;
25285 } else {
25286 // Traits were specified - need to assign new allocator to the specified
25287 // allocator, so it must be an lvalue.
25288 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
25289 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
25290 bool IsPredefinedAllocator = false;
25291 if (DRE) {
25292 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
25293 getAllocatorKind(SemaRef, DSAStack, AllocatorExpr);
25294 IsPredefinedAllocator =
25295 AllocatorTy !=
25296 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
25297 }
25298 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
25299 QualType AllocatorExprType = AllocatorExpr->getType();
25300 bool IsTypeCompatible = IsPredefinedAllocator;
25301 IsTypeCompatible = IsTypeCompatible ||
25302 Context.hasSameUnqualifiedType(AllocatorExprType,
25303 OMPAllocatorHandleT);
25304 IsTypeCompatible =
25305 IsTypeCompatible ||
25306 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
25307 bool IsNonConstantLValue =
25308 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
25309 if (!DRE || !IsTypeCompatible ||
25310 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
25311 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
25312 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
25313 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
25314 continue;
25315 }
25316 // OpenMP [2.12.5, target Construct]
25317 // Predefined allocators appearing in a uses_allocators clause cannot have
25318 // traits specified.
25319 if (IsPredefinedAllocator && D.AllocatorTraits) {
25321 diag::err_omp_predefined_allocator_with_traits)
25323 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
25324 << cast<NamedDecl>(DRE->getDecl())->getName()
25325 << D.Allocator->getSourceRange();
25326 continue;
25327 }
25328 // OpenMP [2.12.5, target Construct]
25329 // Non-predefined allocators appearing in a uses_allocators clause must
25330 // have traits specified.
25331 if (getLangOpts().OpenMP < 52) {
25332 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
25334 diag::err_omp_nonpredefined_allocator_without_traits);
25335 continue;
25336 }
25337 }
25338 // No allocator traits - just convert it to rvalue.
25339 if (!D.AllocatorTraits)
25340 AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
25341 DSAStack->addUsesAllocatorsDecl(
25342 DRE->getDecl(),
25343 IsPredefinedAllocator
25344 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
25345 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
25346 }
25347 Expr *AllocatorTraitsExpr = nullptr;
25348 if (D.AllocatorTraits) {
25350 AllocatorTraitsExpr = D.AllocatorTraits;
25351 } else {
25352 // OpenMP [2.12.5, target Construct]
25353 // Arrays that contain allocator traits that appear in a uses_allocators
25354 // clause must be constant arrays, have constant values and be defined
25355 // in the same scope as the construct in which the clause appears.
25356 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
25357 // Check that traits expr is a constant array.
25358 QualType TraitTy;
25359 if (const ArrayType *Ty =
25360 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
25361 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
25362 TraitTy = ConstArrayTy->getElementType();
25363 if (TraitTy.isNull() ||
25364 !(Context.hasSameUnqualifiedType(TraitTy,
25365 DSAStack->getOMPAlloctraitT()) ||
25366 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
25367 /*CompareUnqualified=*/true))) {
25369 diag::err_omp_expected_array_alloctraits)
25370 << AllocatorTraitsExpr->getType();
25371 continue;
25372 }
25373 // Do not map by default allocator traits if it is a standalone
25374 // variable.
25375 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
25376 DSAStack->addUsesAllocatorsDecl(
25377 DRE->getDecl(),
25378 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
25379 }
25380 }
25381 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
25382 NewD.Allocator = AllocatorExpr;
25383 NewD.AllocatorTraits = AllocatorTraitsExpr;
25384 NewD.LParenLoc = D.LParenLoc;
25385 NewD.RParenLoc = D.RParenLoc;
25386 }
25387 return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc,
25388 EndLoc, NewData);
25389}
25390
25392 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
25393 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
25395 for (Expr *RefExpr : Locators) {
25396 assert(RefExpr && "NULL expr in OpenMP affinity clause.");
25397 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
25398 // It will be analyzed later.
25399 Vars.push_back(RefExpr);
25400 continue;
25401 }
25402
25403 SourceLocation ELoc = RefExpr->getExprLoc();
25404 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
25405
25406 if (!SimpleExpr->isLValue()) {
25407 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
25408 << 1 << 0 << RefExpr->getSourceRange();
25409 continue;
25410 }
25411
25412 ExprResult Res;
25413 {
25415 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
25416 }
25417 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
25419 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
25420 << 1 << 0 << RefExpr->getSourceRange();
25421 continue;
25422 }
25423 Vars.push_back(SimpleExpr);
25424 }
25425
25426 return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc,
25427 ColonLoc, EndLoc, Modifier, Vars);
25428}
25429
25431 SourceLocation KindLoc,
25432 SourceLocation StartLoc,
25433 SourceLocation LParenLoc,
25434 SourceLocation EndLoc) {
25435 if (Kind == OMPC_BIND_unknown) {
25436 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
25437 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
25438 /*Last=*/unsigned(OMPC_BIND_unknown))
25439 << getOpenMPClauseNameForDiag(OMPC_bind);
25440 return nullptr;
25441 }
25442
25443 return OMPBindClause::Create(getASTContext(), Kind, KindLoc, StartLoc,
25444 LParenLoc, EndLoc);
25445}
25446
25448 SourceLocation StartLoc,
25449 SourceLocation LParenLoc,
25450 SourceLocation EndLoc) {
25451 Expr *ValExpr = Size;
25452 Stmt *HelperValStmt = nullptr;
25453
25454 // OpenMP [2.5, Restrictions]
25455 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
25456 // value.
25457 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem,
25458 /*StrictlyPositive=*/false))
25459 return nullptr;
25460
25461 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
25463 DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP);
25464 if (CaptureRegion != OMPD_unknown &&
25465 !SemaRef.CurContext->isDependentContext()) {
25466 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
25467 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
25468 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
25469 HelperValStmt = buildPreInits(getASTContext(), Captures);
25470 }
25471
25473 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
25474}
25475
25479 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc,
25480 SourceLocation M2Loc, SourceLocation EndLoc) {
25481
25482 if ((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ||
25484 std::string Values = getListOfPossibleValues(
25485 OMPC_dyn_groupprivate, /*First=*/0, OMPC_DYN_GROUPPRIVATE_unknown);
25486 Diag((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ? M1Loc
25487 : M2Loc,
25488 diag::err_omp_unexpected_clause_value)
25489 << Values << getOpenMPClauseName(OMPC_dyn_groupprivate);
25490 return nullptr;
25491 }
25492
25493 Expr *ValExpr = Size;
25494 Stmt *HelperValStmt = nullptr;
25495
25496 // OpenMP [2.5, Restrictions]
25497 // The dyn_groupprivate expression must evaluate to a positive integer
25498 // value.
25499 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_dyn_groupprivate,
25500 /*StrictlyPositive=*/false))
25501 return nullptr;
25502
25503 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
25505 DKind, OMPC_dyn_groupprivate, getLangOpts().OpenMP);
25506 if (CaptureRegion != OMPD_unknown &&
25507 !SemaRef.CurContext->isDependentContext()) {
25508 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
25509 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
25510 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
25511 HelperValStmt = buildPreInits(getASTContext(), Captures);
25512 }
25513
25515 StartLoc, LParenLoc, EndLoc, ValExpr, HelperValStmt, CaptureRegion, M1,
25516 M1Loc, M2, M2Loc);
25517}
25518
25521 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
25522 SourceLocation LParenLoc, SourceLocation EndLoc) {
25523
25524 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
25525 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
25526 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
25527 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
25528 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
25529 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_doacross);
25530 return nullptr;
25531 }
25532
25534 DSAStackTy::OperatorOffsetTy OpsOffs;
25535 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
25536 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
25537 SemaRef,
25538 DepType == OMPC_DOACROSS_source ||
25539 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
25540 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
25541 VarList, DSAStack, EndLoc);
25542 Vars = VarOffset.Vars;
25543 OpsOffs = VarOffset.OpsOffs;
25544 TotalDepCount = VarOffset.TotalDepCount;
25545 auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc,
25546 EndLoc, DepType, DepLoc, ColonLoc, Vars,
25547 TotalDepCount.getZExtValue());
25548 if (DSAStack->isParentOrderedRegion())
25549 DSAStack->addDoacrossDependClause(C, OpsOffs);
25550 return C;
25551}
25552
25554 SourceLocation StartLoc,
25555 SourceLocation LParenLoc,
25556 SourceLocation EndLoc) {
25557 return new (getASTContext())
25558 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
25559}
25560
25562 SourceLocation EndLoc) {
25563 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
25564}
25565
25567 SourceLocation LParenLoc,
25568 SourceLocation EndLoc) {
25569 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
25570}
25571
25575 switch (CK) {
25576 case OMPC_absent:
25577 return OMPAbsentClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
25578 case OMPC_contains:
25579 return OMPContainsClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
25580 default:
25581 llvm_unreachable("Unexpected OpenMP clause");
25582 }
25583}
25584
25586 SourceLocation Loc,
25587 SourceLocation RLoc) {
25588 switch (CK) {
25589 case OMPC_no_openmp:
25590 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
25591 case OMPC_no_openmp_routines:
25592 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
25593 case OMPC_no_parallelism:
25594 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
25595 case OMPC_no_openmp_constructs:
25596 return new (getASTContext()) OMPNoOpenMPConstructsClause(Loc, RLoc);
25597 default:
25598 llvm_unreachable("Unexpected OpenMP clause");
25599 }
25600}
25601
25603 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
25604 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
25605 Expr *Stride, SourceLocation RBLoc) {
25606 ASTContext &Context = getASTContext();
25607 if (Base->hasPlaceholderType() &&
25608 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
25609 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
25610 if (Result.isInvalid())
25611 return ExprError();
25612 Base = Result.get();
25613 }
25614 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
25615 ExprResult Result = SemaRef.CheckPlaceholderExpr(LowerBound);
25616 if (Result.isInvalid())
25617 return ExprError();
25618 Result = SemaRef.DefaultLvalueConversion(Result.get());
25619 if (Result.isInvalid())
25620 return ExprError();
25621 LowerBound = Result.get();
25622 }
25623 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
25624 ExprResult Result = SemaRef.CheckPlaceholderExpr(Length);
25625 if (Result.isInvalid())
25626 return ExprError();
25627 Result = SemaRef.DefaultLvalueConversion(Result.get());
25628 if (Result.isInvalid())
25629 return ExprError();
25630 Length = Result.get();
25631 }
25632 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
25633 ExprResult Result = SemaRef.CheckPlaceholderExpr(Stride);
25634 if (Result.isInvalid())
25635 return ExprError();
25636 Result = SemaRef.DefaultLvalueConversion(Result.get());
25637 if (Result.isInvalid())
25638 return ExprError();
25639 Stride = Result.get();
25640 }
25641
25642 // Build an unanalyzed expression if either operand is type-dependent.
25643 if (Base->isTypeDependent() ||
25644 (LowerBound &&
25645 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
25646 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
25647 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
25648 return new (Context) ArraySectionExpr(
25649 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
25650 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
25651 }
25652
25653 // Perform default conversions.
25655 QualType ResultTy;
25656 if (OriginalTy->isAnyPointerType()) {
25657 ResultTy = OriginalTy->getPointeeType();
25658 } else if (OriginalTy->isArrayType()) {
25659 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
25660 } else {
25661 return ExprError(
25662 Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
25663 << Base->getSourceRange());
25664 }
25665 // C99 6.5.2.1p1
25666 if (LowerBound) {
25667 auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
25668 LowerBound);
25669 if (Res.isInvalid())
25670 return ExprError(Diag(LowerBound->getExprLoc(),
25671 diag::err_omp_typecheck_section_not_integer)
25672 << 0 << LowerBound->getSourceRange());
25673 LowerBound = Res.get();
25674
25675 if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25676 LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25677 Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
25678 << 0 << LowerBound->getSourceRange();
25679 }
25680 if (Length) {
25681 auto Res =
25682 PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
25683 if (Res.isInvalid())
25684 return ExprError(Diag(Length->getExprLoc(),
25685 diag::err_omp_typecheck_section_not_integer)
25686 << 1 << Length->getSourceRange());
25687 Length = Res.get();
25688
25689 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25690 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25691 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
25692 << 1 << Length->getSourceRange();
25693 }
25694 if (Stride) {
25695 ExprResult Res =
25697 if (Res.isInvalid())
25698 return ExprError(Diag(Stride->getExprLoc(),
25699 diag::err_omp_typecheck_section_not_integer)
25700 << 1 << Stride->getSourceRange());
25701 Stride = Res.get();
25702
25703 if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25704 Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25705 Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
25706 << 1 << Stride->getSourceRange();
25707 }
25708
25709 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
25710 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
25711 // type. Note that functions are not objects, and that (in C99 parlance)
25712 // incomplete types are not object types.
25713 if (ResultTy->isFunctionType()) {
25714 Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
25715 << ResultTy << Base->getSourceRange();
25716 return ExprError();
25717 }
25718
25719 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
25720 diag::err_omp_section_incomplete_type, Base))
25721 return ExprError();
25722
25723 if (LowerBound && !OriginalTy->isAnyPointerType()) {
25725 if (LowerBound->EvaluateAsInt(Result, Context)) {
25726 // OpenMP 5.0, [2.1.5 Array Sections]
25727 // The array section must be a subset of the original array.
25728 llvm::APSInt LowerBoundValue = Result.Val.getInt();
25729 if (LowerBoundValue.isNegative()) {
25730 Diag(LowerBound->getExprLoc(),
25731 diag::err_omp_section_not_subset_of_array)
25732 << LowerBound->getSourceRange();
25733 return ExprError();
25734 }
25735 }
25736 }
25737
25738 if (Length) {
25740 if (Length->EvaluateAsInt(Result, Context)) {
25741 // OpenMP 5.0, [2.1.5 Array Sections]
25742 // The length must evaluate to non-negative integers.
25743 llvm::APSInt LengthValue = Result.Val.getInt();
25744 if (LengthValue.isNegative()) {
25745 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
25746 << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
25747 << Length->getSourceRange();
25748 return ExprError();
25749 }
25750 }
25751 } else if (SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.isValid() &&
25752 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
25753 !OriginalTy->isVariableArrayType()))) {
25754 // OpenMP 5.0, [2.1.5 Array Sections]
25755 // When the size of the array dimension is not known, the length must be
25756 // specified explicitly.
25757 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
25758 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
25759 return ExprError();
25760 }
25761
25762 if (Stride) {
25764 if (Stride->EvaluateAsInt(Result, Context)) {
25765 // OpenMP 5.0, [2.1.5 Array Sections]
25766 // The stride must evaluate to a positive integer.
25767 llvm::APSInt StrideValue = Result.Val.getInt();
25768 if (!StrideValue.isStrictlyPositive()) {
25769 Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
25770 << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
25771 << Stride->getSourceRange();
25772 return ExprError();
25773 }
25774 }
25775 }
25776
25777 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
25778 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(Base);
25779 if (Result.isInvalid())
25780 return ExprError();
25781 Base = Result.get();
25782 }
25783 return new (Context) ArraySectionExpr(
25784 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
25785 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
25786}
25787
25789 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
25790 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
25791 ASTContext &Context = getASTContext();
25792 if (Base->hasPlaceholderType()) {
25793 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
25794 if (Result.isInvalid())
25795 return ExprError();
25796 Result = SemaRef.DefaultLvalueConversion(Result.get());
25797 if (Result.isInvalid())
25798 return ExprError();
25799 Base = Result.get();
25800 }
25801 QualType BaseTy = Base->getType();
25802 // Delay analysis of the types/expressions if instantiation/specialization is
25803 // required.
25804 if (!BaseTy->isPointerType() && Base->isTypeDependent())
25805 return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
25806 LParenLoc, RParenLoc, Dims, Brackets);
25807 if (!BaseTy->isPointerType() ||
25808 (!Base->isTypeDependent() &&
25809 BaseTy->getPointeeType()->isIncompleteType()))
25810 return ExprError(Diag(Base->getExprLoc(),
25811 diag::err_omp_non_pointer_type_array_shaping_base)
25812 << Base->getSourceRange());
25813
25814 SmallVector<Expr *, 4> NewDims;
25815 bool ErrorFound = false;
25816 for (Expr *Dim : Dims) {
25817 if (Dim->hasPlaceholderType()) {
25818 ExprResult Result = SemaRef.CheckPlaceholderExpr(Dim);
25819 if (Result.isInvalid()) {
25820 ErrorFound = true;
25821 continue;
25822 }
25823 Result = SemaRef.DefaultLvalueConversion(Result.get());
25824 if (Result.isInvalid()) {
25825 ErrorFound = true;
25826 continue;
25827 }
25828 Dim = Result.get();
25829 }
25830 if (!Dim->isTypeDependent()) {
25833 if (Result.isInvalid()) {
25834 ErrorFound = true;
25835 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
25836 << Dim->getSourceRange();
25837 continue;
25838 }
25839 Dim = Result.get();
25840 Expr::EvalResult EvResult;
25841 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
25842 // OpenMP 5.0, [2.1.4 Array Shaping]
25843 // Each si is an integral type expression that must evaluate to a
25844 // positive integer.
25845 llvm::APSInt Value = EvResult.Val.getInt();
25846 if (!Value.isStrictlyPositive()) {
25847 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
25848 << toString(Value, /*Radix=*/10, /*Signed=*/true)
25849 << Dim->getSourceRange();
25850 ErrorFound = true;
25851 continue;
25852 }
25853 }
25854 }
25855 NewDims.push_back(Dim);
25856 }
25857 if (ErrorFound)
25858 return ExprError();
25859 return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
25860 LParenLoc, RParenLoc, NewDims, Brackets);
25861}
25862
25864 SourceLocation IteratorKwLoc,
25865 SourceLocation LLoc,
25866 SourceLocation RLoc,
25868 ASTContext &Context = getASTContext();
25870 bool IsCorrect = true;
25871 for (const OMPIteratorData &D : Data) {
25872 TypeSourceInfo *TInfo = nullptr;
25873 SourceLocation StartLoc;
25874 QualType DeclTy;
25875 if (!D.Type.getAsOpaquePtr()) {
25876 // OpenMP 5.0, 2.1.6 Iterators
25877 // In an iterator-specifier, if the iterator-type is not specified then
25878 // the type of that iterator is of int type.
25879 DeclTy = Context.IntTy;
25880 StartLoc = D.DeclIdentLoc;
25881 } else {
25882 DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo);
25883 StartLoc = TInfo->getTypeLoc().getBeginLoc();
25884 }
25885
25886 bool IsDeclTyDependent = DeclTy->isDependentType() ||
25887 DeclTy->containsUnexpandedParameterPack() ||
25888 DeclTy->isInstantiationDependentType();
25889 if (!IsDeclTyDependent) {
25890 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
25891 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
25892 // The iterator-type must be an integral or pointer type.
25893 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25894 << DeclTy;
25895 IsCorrect = false;
25896 continue;
25897 }
25898 if (DeclTy.isConstant(Context)) {
25899 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
25900 // The iterator-type must not be const qualified.
25901 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25902 << DeclTy;
25903 IsCorrect = false;
25904 continue;
25905 }
25906 }
25907
25908 // Iterator declaration.
25909 assert(D.DeclIdent && "Identifier expected.");
25910 // Always try to create iterator declarator to avoid extra error messages
25911 // about unknown declarations use.
25912 auto *VD =
25913 VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc,
25914 D.DeclIdent, DeclTy, TInfo, SC_None);
25915 VD->setImplicit();
25916 if (S) {
25917 // Check for conflicting previous declaration.
25918 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
25921 Previous.suppressDiagnostics();
25922 SemaRef.LookupName(Previous, S);
25923
25924 SemaRef.FilterLookupForScope(Previous, SemaRef.CurContext, S,
25925 /*ConsiderLinkage=*/false,
25926 /*AllowInlineNamespace=*/false);
25927 if (!Previous.empty()) {
25928 NamedDecl *Old = Previous.getRepresentativeDecl();
25929 Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
25930 Diag(Old->getLocation(), diag::note_previous_definition);
25931 } else {
25932 SemaRef.PushOnScopeChains(VD, S);
25933 }
25934 } else {
25935 SemaRef.CurContext->addDecl(VD);
25936 }
25937
25938 /// Act on the iterator variable declaration.
25940
25941 Expr *Begin = D.Range.Begin;
25942 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
25943 ExprResult BeginRes = SemaRef.PerformImplicitConversion(
25944 Begin, DeclTy, AssignmentAction::Converting);
25945 Begin = BeginRes.get();
25946 }
25947 Expr *End = D.Range.End;
25948 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
25949 ExprResult EndRes = SemaRef.PerformImplicitConversion(
25950 End, DeclTy, AssignmentAction::Converting);
25951 End = EndRes.get();
25952 }
25953 Expr *Step = D.Range.Step;
25954 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
25955 if (!Step->getType()->isIntegralType(Context)) {
25956 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
25957 << Step << Step->getSourceRange();
25958 IsCorrect = false;
25959 continue;
25960 }
25961 std::optional<llvm::APSInt> Result =
25962 Step->getIntegerConstantExpr(Context);
25963 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
25964 // If the step expression of a range-specification equals zero, the
25965 // behavior is unspecified.
25966 if (Result && Result->isZero()) {
25967 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
25968 << Step << Step->getSourceRange();
25969 IsCorrect = false;
25970 continue;
25971 }
25972 }
25973 if (!Begin || !End || !IsCorrect) {
25974 IsCorrect = false;
25975 continue;
25976 }
25977 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
25978 IDElem.IteratorDecl = VD;
25979 IDElem.AssignmentLoc = D.AssignLoc;
25980 IDElem.Range.Begin = Begin;
25981 IDElem.Range.End = End;
25982 IDElem.Range.Step = Step;
25983 IDElem.ColonLoc = D.ColonLoc;
25984 IDElem.SecondColonLoc = D.SecColonLoc;
25985 }
25986 if (!IsCorrect) {
25987 // Invalidate all created iterator declarations if error is found.
25988 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
25989 if (Decl *ID = D.IteratorDecl)
25990 ID->setInvalidDecl();
25991 }
25992 return ExprError();
25993 }
25995 if (!SemaRef.CurContext->isDependentContext()) {
25996 // Build number of ityeration for each iteration range.
25997 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
25998 // ((Begini-Stepi-1-Endi) / -Stepi);
26000 // (Endi - Begini)
26001 ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub,
26002 D.Range.End, D.Range.Begin);
26003 if (!Res.isUsable()) {
26004 IsCorrect = false;
26005 continue;
26006 }
26007 ExprResult St, St1;
26008 if (D.Range.Step) {
26009 St = D.Range.Step;
26010 // (Endi - Begini) + Stepi
26011 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(),
26012 St.get());
26013 if (!Res.isUsable()) {
26014 IsCorrect = false;
26015 continue;
26016 }
26017 // (Endi - Begini) + Stepi - 1
26018 Res = SemaRef.CreateBuiltinBinOp(
26019 D.AssignmentLoc, BO_Sub, Res.get(),
26020 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
26021 if (!Res.isUsable()) {
26022 IsCorrect = false;
26023 continue;
26024 }
26025 // ((Endi - Begini) + Stepi - 1) / Stepi
26026 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(),
26027 St.get());
26028 if (!Res.isUsable()) {
26029 IsCorrect = false;
26030 continue;
26031 }
26032 St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
26033 D.Range.Step);
26034 // (Begini - Endi)
26035 ExprResult Res1 = SemaRef.CreateBuiltinBinOp(
26036 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
26037 if (!Res1.isUsable()) {
26038 IsCorrect = false;
26039 continue;
26040 }
26041 // (Begini - Endi) - Stepi
26042 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(),
26043 St1.get());
26044 if (!Res1.isUsable()) {
26045 IsCorrect = false;
26046 continue;
26047 }
26048 // (Begini - Endi) - Stepi - 1
26049 Res1 = SemaRef.CreateBuiltinBinOp(
26050 D.AssignmentLoc, BO_Sub, Res1.get(),
26051 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
26052 if (!Res1.isUsable()) {
26053 IsCorrect = false;
26054 continue;
26055 }
26056 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
26057 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(),
26058 St1.get());
26059 if (!Res1.isUsable()) {
26060 IsCorrect = false;
26061 continue;
26062 }
26063 // Stepi > 0.
26064 ExprResult CmpRes = SemaRef.CreateBuiltinBinOp(
26065 D.AssignmentLoc, BO_GT, D.Range.Step,
26066 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
26067 if (!CmpRes.isUsable()) {
26068 IsCorrect = false;
26069 continue;
26070 }
26071 Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
26072 CmpRes.get(), Res.get(), Res1.get());
26073 if (!Res.isUsable()) {
26074 IsCorrect = false;
26075 continue;
26076 }
26077 }
26078 Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false);
26079 if (!Res.isUsable()) {
26080 IsCorrect = false;
26081 continue;
26082 }
26083
26084 // Build counter update.
26085 // Build counter.
26086 auto *CounterVD = VarDecl::Create(Context, SemaRef.CurContext,
26087 D.IteratorDecl->getBeginLoc(),
26088 D.IteratorDecl->getBeginLoc(), nullptr,
26089 Res.get()->getType(), nullptr, SC_None);
26090 CounterVD->setImplicit();
26091 ExprResult RefRes =
26092 SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue,
26093 D.IteratorDecl->getBeginLoc());
26094 // Build counter update.
26095 // I = Begini + counter * Stepi;
26096 ExprResult UpdateRes;
26097 if (D.Range.Step) {
26098 UpdateRes = SemaRef.CreateBuiltinBinOp(
26099 D.AssignmentLoc, BO_Mul,
26100 SemaRef.DefaultLvalueConversion(RefRes.get()).get(), St.get());
26101 } else {
26102 UpdateRes = SemaRef.DefaultLvalueConversion(RefRes.get());
26103 }
26104 if (!UpdateRes.isUsable()) {
26105 IsCorrect = false;
26106 continue;
26107 }
26108 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
26109 D.Range.Begin, UpdateRes.get());
26110 if (!UpdateRes.isUsable()) {
26111 IsCorrect = false;
26112 continue;
26113 }
26114 ExprResult VDRes =
26115 SemaRef.BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl),
26116 cast<VarDecl>(D.IteratorDecl)->getType(),
26117 VK_LValue, D.IteratorDecl->getBeginLoc());
26118 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
26119 VDRes.get(), UpdateRes.get());
26120 if (!UpdateRes.isUsable()) {
26121 IsCorrect = false;
26122 continue;
26123 }
26124 UpdateRes =
26125 SemaRef.ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true);
26126 if (!UpdateRes.isUsable()) {
26127 IsCorrect = false;
26128 continue;
26129 }
26130 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
26131 D.AssignmentLoc, UO_PreInc, RefRes.get());
26132 if (!CounterUpdateRes.isUsable()) {
26133 IsCorrect = false;
26134 continue;
26135 }
26136 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(CounterUpdateRes.get(),
26137 /*DiscardedValue=*/true);
26138 if (!CounterUpdateRes.isUsable()) {
26139 IsCorrect = false;
26140 continue;
26141 }
26142 OMPIteratorHelperData &HD = Helpers.emplace_back();
26143 HD.CounterVD = CounterVD;
26144 HD.Upper = Res.get();
26145 HD.Update = UpdateRes.get();
26146 HD.CounterUpdate = CounterUpdateRes.get();
26147 }
26148 } else {
26149 Helpers.assign(ID.size(), {});
26150 }
26151 if (!IsCorrect) {
26152 // Invalidate all created iterator declarations if error is found.
26153 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
26154 if (Decl *ID = D.IteratorDecl)
26155 ID->setInvalidDecl();
26156 }
26157 return ExprError();
26158 }
26159 return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc,
26160 LLoc, RLoc, ID, Helpers);
26161}
26162
26163/// Check if \p AssumptionStr is a known assumption and warn if not.
26165 StringRef AssumptionStr) {
26166 if (llvm::getKnownAssumptionStrings().count(AssumptionStr))
26167 return;
26168
26169 unsigned BestEditDistance = 3;
26170 StringRef Suggestion;
26171 for (const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) {
26172 unsigned EditDistance =
26173 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
26174 if (EditDistance < BestEditDistance) {
26175 Suggestion = KnownAssumptionIt.getKey();
26176 BestEditDistance = EditDistance;
26177 }
26178 }
26179
26180 if (!Suggestion.empty())
26181 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
26182 << AssumptionStr << Suggestion;
26183 else
26184 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
26185 << AssumptionStr;
26186}
26187
26189 // Handle the case where the attribute has a text message.
26190 StringRef Str;
26191 SourceLocation AttrStrLoc;
26192 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
26193 return;
26194
26195 checkOMPAssumeAttr(SemaRef, AttrStrLoc, Str);
26196
26197 D->addAttr(::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
26198}
26199
26201 : 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:489
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:220
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:794
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:870
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:790
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:909
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:7171
Expr * getBase()
Get base of the array section.
Definition Expr.h:7249
Expr * getLength()
Get length of array section.
Definition Expr.h:7259
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition Expr.cpp:5272
Expr * getLowerBound()
Get lower bound of array section.
Definition Expr.h:7253
SourceLocation getColonLocFirst() const
Definition Expr.h:7280
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3723
QualType getElementType() const
Definition TypeBase.h:3735
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:436
SourceLocation getBeginLoc() const
Definition Stmt.h:2234
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4038
Expr * getLHS() const
Definition Expr.h:4088
static bool isRelationalOp(Opcode Opc)
Definition Expr.h:4132
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition Expr.cpp:2179
static Opcode getOpForCompoundAssignment(Opcode Opc)
Definition Expr.h:4185
SourceLocation getOperatorLoc() const
Definition Expr.h:4080
SourceLocation getExprLoc() const
Definition Expr.h:4079
static Opcode reverseComparisonOp(Opcode Opc)
Definition Expr.h:4157
Expr * getRHS() const
Definition Expr.h:4090
Opcode getOpcode() const
Definition Expr.h:4083
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition Expr.cpp:2141
BinaryOperatorKind Opcode
Definition Expr.h:4043
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:2604
Represents a C++ conversion function within a class.
Definition DeclCXX.h:2939
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:73
bool isValid() const
A scope specifier is present, and it refers to a real scope.
Definition DeclSpec.h:185
SourceLocation getBeginLoc() const
Definition DeclSpec.h:83
bool isSet() const
Deprecated.
Definition DeclSpec.h:198
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:183
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2943
SourceLocation getBeginLoc() const
Definition Expr.h:3277
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:1516
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3126
Expr * getCallee()
Definition Expr.h:3090
arg_range arguments()
Definition Expr.h:3195
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:4943
unsigned getNumParams() const
Definition Decl.h:4981
void setNothrow(bool Nothrow=true)
Definition Decl.cpp:5697
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:5693
ImplicitParamDecl * getParam(unsigned i) const
Definition Decl.h:4983
This captures a statement into a function.
Definition Stmt.h:3929
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
Definition Stmt.cpp:1488
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:1512
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:3676
Declaration of a class template.
Complex values, per C99 6.2.5p11.
Definition TypeBase.h:3276
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:394
ConditionalOperator - The ?
Definition Expr.h:4391
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:1270
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:487
ValueDecl * getDecl()
Definition Expr.h:1338
NonOdrUseReason isNonOdrUse() const
Is this expression a non-odr-use reference, and if so, why?
Definition Expr.h:1468
SourceLocation getEndLoc() const LLVM_READONLY
Definition Expr.cpp:550
SourceLocation getBeginLoc() const
Definition Expr.h:1349
ConstexprSpecKind getConstexprSpecifier() const
Definition DeclSpec.h:802
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:1874
const DeclSpec & getDeclSpec() const
getDeclSpec - Return the declaration-specifier that this declarator was declared with.
Definition DeclSpec.h:2021
SourceLocation getIdentifierLoc() const
Definition DeclSpec.h:2310
void SetIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc)
Set the name of this declarator to be the given identifier.
Definition DeclSpec.h:2313
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclSpec.h:2057
void setFunctionDefinitionKind(FunctionDefinitionKind Val)
Definition DeclSpec.h:2707
const CXXScopeSpec & getCXXScopeSpec() const
getCXXScopeSpec - Return the C++ scope specifier (global scope or nested-name-specifier) that is part...
Definition DeclSpec.h:2036
bool isInvalidType() const
Definition DeclSpec.h:2688
const IdentifierInfo * getIdentifier() const
Definition DeclSpec.h:2304
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:674
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition Expr.cpp:3094
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:444
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:3106
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:3089
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3077
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:3085
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:451
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:3069
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:276
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:4826
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:1075
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:3826
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:5269
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:1039
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:1731
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition Expr.cpp:2072
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:974
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:3447
Expr * getBase() const
Definition Expr.h:3441
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:3425
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:3559
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:1845
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:5380
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:5507
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:1178
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition Expr.h:1228
void setIsUnique(bool V)
Definition Expr.h:1230
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:2957
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:5076
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:2867
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition TypeBase.h:8381
QualType withRestrict() const
Definition TypeBase.h:1175
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
Definition Type.cpp:3556
QualType withConst() const
Definition TypeBase.h:1159
void addConst()
Add the const type qualifier to this QualType.
Definition TypeBase.h:1156
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:8292
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:8477
QualType getCanonicalType() const
Definition TypeBase.h:8344
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8386
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:8446
const Type * getTypePtrOrNull() const
Definition TypeBase.h:8296
Represents a struct/union/class.
Definition Decl.h:4324
field_range fields() const
Definition Decl.h:4527
field_iterator field_begin() const
Definition Decl.cpp:5270
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3574
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:1295
Expr * get() const
Definition Sema.h:7788
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition Sema.h:12520
Abstract base class used for diagnosing integer constant expression violations.
Definition Sema.h:7739
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:856
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition Sema.h:1121
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:9353
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
Definition Sema.h:9394
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
Definition Sema.h:9396
@ LookupAnyName
Look up any declaration with any name.
Definition Sema.h:9398
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:1508
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
Definition Sema.h:4760
@ AR_inaccessible
Definition Sema.h:1662
Scope * getScopeForContext(DeclContext *Ctx)
Determines the active Scope associated with the given declaration context.
Definition Sema.cpp:2318
FPOptionsOverride CurFPFeatureOverrides()
Definition Sema.h:2052
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:1288
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:755
ASTContext & getASTContext() const
Definition Sema.h:927
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:9346
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition Sema.h:1192
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:920
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:1287
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:1286
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
Definition Sema.cpp:2564
llvm::SmallSetVector< DeclContext *, 16 > AssociatedNamespaceSet
Definition Sema.h:9345
DeclContext * getCurLexicalContext() const
Definition Sema.h:1125
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:640
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
Definition Sema.h:15495
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
Definition Sema.cpp:2519
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition Sema.h:1421
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:15450
void setFunctionHasBranchProtectedScope()
Definition Sema.cpp:2504
std::pair< StringRef, QualType > CapturedParamNameType
Definition Sema.h:11248
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:6761
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
Definition Sema.h:6730
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:1247
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:2110
sema::CapturedRegionScopeInfo * getCurCapturedRegion()
Retrieve the current captured region, if any.
Definition Sema.cpp:2893
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:7802
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition Sema.h:8681
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:362
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:299
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:338
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:205
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:350
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4893
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:8263
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:8274
The base class of the type hierarchy.
Definition TypeBase.h:1833
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
Definition TypeBase.h:9071
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:8632
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:2067
bool isArrayType() const
Definition TypeBase.h:8628
bool isArithmeticType() const
Definition Type.cpp:2338
bool isPointerType() const
Definition TypeBase.h:8529
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:8935
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9178
bool isReferenceType() const
Definition TypeBase.h:8553
bool isEnumeralType() const
Definition TypeBase.h:8660
bool isScalarType() const
Definition TypeBase.h:8993
bool isVariableArrayType() const
Definition TypeBase.h:8640
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
Definition Type.cpp:2104
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:2292
bool isAnyCharacterType() const
Determine whether this type is any of the built-in character types.
Definition Type.cpp:2169
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
Definition TypeBase.h:8885
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition TypeBase.h:2791
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition TypeBase.h:8860
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition TypeBase.h:2783
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
Definition Type.cpp:2412
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
bool isAnyComplexType() const
Definition TypeBase.h:8664
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
Definition TypeBase.h:2405
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition Type.cpp:2244
bool isFunctionProtoType() const
Definition TypeBase.h:2601
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
Definition TypeBase.h:9034
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2801
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition TypeBase.h:9164
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition Type.cpp:2436
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
Definition TypeBase.h:9128
bool isFunctionType() const
Definition TypeBase.h:8525
bool isStructureOrClassType() const
Definition Type.cpp:707
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2321
bool isFloatingType() const
Definition Type.cpp:2305
bool isAnyPointerType() const
Definition TypeBase.h:8537
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9111
bool isRecordType() const
Definition TypeBase.h:8656
bool isUnionType() const
Definition Type.cpp:719
bool isFunctionNoProtoType() const
Definition TypeBase.h:2600
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:2285
Opcode getOpcode() const
Definition Expr.h:2280
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:3635
const Expr * getExprStmt() const
Definition Stmt.cpp:415
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:2162
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:2179
bool hasInit() const
Definition Decl.cpp:2409
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:2271
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2201
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition Decl.cpp:2268
@ 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:2488
@ 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:2539
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:816
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:1310
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:5384
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
const FunctionProtoType * T
OpenMPLastprivateModifier
OpenMP 'lastprivate' clause modifier.
@ OMPC_LASTPRIVATE_unknown
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
Definition OpenMPKinds.h:55
@ OMPC_DEPEND_unknown
Definition OpenMPKinds.h:59
bool isOpenMPCanonicalLoopSequenceTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive that applies to a canonical loop...
OpenMPGrainsizeClauseModifier
@ OMPC_GRAINSIZE_unknown
bool 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:149
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:5889
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:313
BinaryOperatorKind Opcode
The original opcode, prior to rewriting.
Definition ExprCXX.h:309
const Expr * LHS
The original left-hand side.
Definition ExprCXX.h:311
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:645
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:647
Extra information about a function prototype.
Definition TypeBase.h:5354
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.