clang 22.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[] | bycopy|
2210 // | ptr | n.a. | - | - | x | | bycopy|
2211 // | ptr | n.a. | - | - | x | x | bycopy|
2212 // | ptr | n.a. | - | - | x | x[] | bycopy|
2213 // =========================================================================
2214 // Legend:
2215 // scl - scalar
2216 // ptr - pointer
2217 // agg - aggregate
2218 // x - applies
2219 // - - invalid in this combination
2220 // [] - mapped with an array section
2221 // byref - should be mapped by reference
2222 // byval - should be mapped by value
2223 // null - initialize a local variable to null on the device
2224 //
2225 // Observations:
2226 // - All scalar declarations that show up in a map clause have to be passed
2227 // by reference, because they may have been mapped in the enclosing data
2228 // environment.
2229 // - If the scalar value does not fit the size of uintptr, it has to be
2230 // passed by reference, regardless the result in the table above.
2231 // - For pointers mapped by value that have either an implicit map or an
2232 // array section, the runtime library may pass the NULL value to the
2233 // device instead of the value passed to it by the compiler.
2234
2235 if (Ty->isReferenceType())
2236 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2237
2238 // Locate map clauses and see if the variable being captured is referred to
2239 // in any of those clauses. Here we only care about variables, not fields,
2240 // because fields are part of aggregates.
2241 bool IsVariableAssociatedWithSection = false;
2242
2243 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2244 D, Level,
2245 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2247 MapExprComponents,
2248 OpenMPClauseKind WhereFoundClauseKind) {
2249 // Both map and has_device_addr clauses information influences how a
2250 // variable is captured. E.g. is_device_ptr does not require changing
2251 // the default behavior.
2252 if (WhereFoundClauseKind != OMPC_map &&
2253 WhereFoundClauseKind != OMPC_has_device_addr)
2254 return false;
2255
2256 auto EI = MapExprComponents.rbegin();
2257 auto EE = MapExprComponents.rend();
2258
2259 assert(EI != EE && "Invalid map expression!");
2260
2261 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2262 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2263
2264 ++EI;
2265 if (EI == EE)
2266 return false;
2267 auto Last = std::prev(EE);
2268 const auto *UO =
2269 dyn_cast<UnaryOperator>(Last->getAssociatedExpression());
2270 if ((UO && UO->getOpcode() == UO_Deref) ||
2271 isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) ||
2272 isa<ArraySectionExpr>(Last->getAssociatedExpression()) ||
2273 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2274 isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) {
2275 IsVariableAssociatedWithSection = true;
2276 // There is nothing more we need to know about this variable.
2277 return true;
2278 }
2279
2280 // Keep looking for more map info.
2281 return false;
2282 });
2283
2284 if (IsVariableUsedInMapClause) {
2285 // If variable is identified in a map clause it is always captured by
2286 // reference except if it is a pointer that is dereferenced somehow.
2287 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2288 } else {
2289 // By default, all the data that has a scalar type is mapped by copy
2290 // (except for reduction variables).
2291 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2292 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2293 !Ty->isAnyPointerType()) ||
2294 !Ty->isScalarType() ||
2295 DSAStack->isDefaultmapCapturedByRef(
2297 DSAStack->hasExplicitDSA(
2298 D,
2299 [](OpenMPClauseKind K, bool AppliedToPointee) {
2300 return K == OMPC_reduction && !AppliedToPointee;
2301 },
2302 Level);
2303 }
2304 }
2305
2306 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2307 IsByRef =
2308 ((IsVariableUsedInMapClause &&
2309 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2310 OMPD_target) ||
2311 !(DSAStack->hasExplicitDSA(
2312 D,
2313 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2314 return K == OMPC_firstprivate ||
2315 (K == OMPC_reduction && AppliedToPointee);
2316 },
2317 Level, /*NotLastprivate=*/true) ||
2318 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2319 // If the variable is artificial and must be captured by value - try to
2320 // capture by value.
2321 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2322 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2323 // If the variable is implicitly firstprivate and scalar - capture by
2324 // copy
2325 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2326 DSAStack->getDefaultDSA() == DSA_private) &&
2327 !DSAStack->hasExplicitDSA(
2328 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2329 Level) &&
2330 !DSAStack->isLoopControlVariable(D, Level).first);
2331 }
2332
2333 // When passing data by copy, we need to make sure it fits the uintptr size
2334 // and alignment, because the runtime library only deals with uintptr types.
2335 // If it does not fit the uintptr size, we need to pass the data by reference
2336 // instead.
2337 if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) >
2339 Ctx.getAlignOfGlobalVarInChars(Ty, dyn_cast<VarDecl>(D)) >
2340 Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2341 IsByRef = true;
2342 }
2343
2344 return IsByRef;
2345}
2346
2347unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2348 assert(getLangOpts().OpenMP);
2349 return DSAStack->getNestingLevel();
2350}
2351
2353 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2354 DSAStack->isUntiedRegion();
2355}
2356
2358 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2359 !DSAStack->isClauseParsingMode()) ||
2360 DSAStack->hasDirective(
2362 SourceLocation) -> bool {
2364 },
2365 false);
2366}
2367
2369 // Only rebuild for Field.
2370 if (!isa<FieldDecl>(D))
2371 return false;
2372 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2373 D,
2374 [](OpenMPClauseKind C, bool AppliedToPointee,
2375 DefaultDataSharingAttributes DefaultAttr) {
2376 return isOpenMPPrivate(C) && !AppliedToPointee &&
2377 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2378 },
2379 [](OpenMPDirectiveKind) { return true; },
2380 DSAStack->isClauseParsingMode());
2381 if (DVarPrivate.CKind != OMPC_unknown)
2382 return true;
2383 return false;
2384}
2385
2387 Expr *CaptureExpr, bool WithInit,
2388 DeclContext *CurContext,
2389 bool AsExpression);
2390
2392 unsigned StopAt) {
2393 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2394 D = getCanonicalDecl(D);
2395
2396 auto *VD = dyn_cast<VarDecl>(D);
2397 // Do not capture constexpr variables.
2398 if (VD && VD->isConstexpr())
2399 return nullptr;
2400
2401 // If we want to determine whether the variable should be captured from the
2402 // perspective of the current capturing scope, and we've already left all the
2403 // capturing scopes of the top directive on the stack, check from the
2404 // perspective of its parent directive (if any) instead.
2405 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2406 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2407
2408 // If we are attempting to capture a global variable in a directive with
2409 // 'target' we return true so that this global is also mapped to the device.
2410 //
2411 if (VD && !VD->hasLocalStorage() &&
2412 (SemaRef.getCurCapturedRegion() || SemaRef.getCurBlock() ||
2413 SemaRef.getCurLambda())) {
2415 DSAStackTy::DSAVarData DVarTop =
2416 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2417 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2418 return VD;
2419 // If the declaration is enclosed in a 'declare target' directive,
2420 // then it should not be captured.
2421 //
2422 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2423 return nullptr;
2424 CapturedRegionScopeInfo *CSI = nullptr;
2425 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2426 llvm::reverse(SemaRef.FunctionScopes),
2427 CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2428 : 0)) {
2429 if (!isa<CapturingScopeInfo>(FSI))
2430 return nullptr;
2431 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2432 if (RSI->CapRegionKind == CR_OpenMP) {
2433 CSI = RSI;
2434 break;
2435 }
2436 }
2437 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2440 DSAStack->getDirective(CSI->OpenMPLevel));
2441 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2442 return VD;
2443 }
2445 // Try to mark variable as declare target if it is used in capturing
2446 // regions.
2447 if (getLangOpts().OpenMP <= 45 &&
2448 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2450 return nullptr;
2451 }
2452 }
2453
2454 if (CheckScopeInfo) {
2455 bool OpenMPFound = false;
2456 for (unsigned I = StopAt + 1; I > 0; --I) {
2457 FunctionScopeInfo *FSI = SemaRef.FunctionScopes[I - 1];
2458 if (!isa<CapturingScopeInfo>(FSI))
2459 return nullptr;
2460 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2461 if (RSI->CapRegionKind == CR_OpenMP) {
2462 OpenMPFound = true;
2463 break;
2464 }
2465 }
2466 if (!OpenMPFound)
2467 return nullptr;
2468 }
2469
2470 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2471 (!DSAStack->isClauseParsingMode() ||
2472 DSAStack->getParentDirective() != OMPD_unknown)) {
2473 auto &&Info = DSAStack->isLoopControlVariable(D);
2474 if (Info.first ||
2475 (VD && VD->hasLocalStorage() &&
2476 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2477 (VD && DSAStack->isForceVarCapturing()))
2478 return VD ? VD : Info.second;
2479 DSAStackTy::DSAVarData DVarTop =
2480 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2481 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2482 (!VD || VD->hasLocalStorage() ||
2483 !(DVarTop.AppliedToPointee && DVarTop.CKind != OMPC_reduction)))
2484 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2485 // Threadprivate variables must not be captured.
2486 if (isOpenMPThreadPrivate(DVarTop.CKind))
2487 return nullptr;
2488 // The variable is not private or it is the variable in the directive with
2489 // default(none) clause and not used in any clause.
2490 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2491 D,
2492 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2493 return isOpenMPPrivate(C) && !AppliedToPointee;
2494 },
2495 [](OpenMPDirectiveKind) { return true; },
2496 DSAStack->isClauseParsingMode());
2497 // Global shared must not be captured.
2498 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2499 ((DSAStack->getDefaultDSA() != DSA_none &&
2500 DSAStack->getDefaultDSA() != DSA_private &&
2501 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2502 DVarTop.CKind == OMPC_shared))
2503 return nullptr;
2504 auto *FD = dyn_cast<FieldDecl>(D);
2505 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2506 !DVarPrivate.PrivateCopy) {
2507 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2508 D,
2509 [](OpenMPClauseKind C, bool AppliedToPointee,
2510 DefaultDataSharingAttributes DefaultAttr) {
2511 return isOpenMPPrivate(C) && !AppliedToPointee &&
2512 (DefaultAttr == DSA_firstprivate ||
2513 DefaultAttr == DSA_private);
2514 },
2515 [](OpenMPDirectiveKind) { return true; },
2516 DSAStack->isClauseParsingMode());
2517 if (DVarPrivate.CKind == OMPC_unknown)
2518 return nullptr;
2519
2520 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2521 if (VD)
2522 return VD;
2523 if (SemaRef.getCurrentThisType().isNull())
2524 return nullptr;
2525 Expr *ThisExpr = SemaRef.BuildCXXThisExpr(SourceLocation(),
2526 SemaRef.getCurrentThisType(),
2527 /*IsImplicit=*/true);
2528 const CXXScopeSpec CS = CXXScopeSpec();
2529 Expr *ME = SemaRef.BuildMemberExpr(
2530 ThisExpr, /*IsArrow=*/true, SourceLocation(),
2533 /*HadMultipleCandidates=*/false, DeclarationNameInfo(), FD->getType(),
2536 SemaRef, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2537 SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2538 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2540 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2541 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2542 return VD;
2543 }
2544 if (DVarPrivate.CKind != OMPC_unknown ||
2545 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2546 DSAStack->getDefaultDSA() == DSA_private ||
2547 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2548 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2549 }
2550 return nullptr;
2551}
2552
2553void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2554 unsigned Level) const {
2555 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2556}
2557
2559 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2560 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2561 DSAStack->loopInit();
2562}
2563
2565 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2566 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2567 DSAStack->resetPossibleLoopCounter();
2568 DSAStack->loopStart();
2569 }
2570}
2571
2573 unsigned CapLevel) const {
2574 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2575 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2576 (!DSAStack->isClauseParsingMode() ||
2577 DSAStack->getParentDirective() != OMPD_unknown)) {
2578 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2579 D,
2580 [](OpenMPClauseKind C, bool AppliedToPointee,
2581 DefaultDataSharingAttributes DefaultAttr) {
2582 return isOpenMPPrivate(C) && !AppliedToPointee &&
2583 DefaultAttr == DSA_private;
2584 },
2585 [](OpenMPDirectiveKind) { return true; },
2586 DSAStack->isClauseParsingMode());
2587 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2588 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2589 !DSAStack->isLoopControlVariable(D).first)
2590 return OMPC_private;
2591 }
2592 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2593 bool IsTriviallyCopyable =
2595 getASTContext()) &&
2596 !D->getType()
2600 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2602 getOpenMPCaptureRegions(CaptureRegions, DKind);
2603 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2604 (IsTriviallyCopyable ||
2605 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2606 if (DSAStack->hasExplicitDSA(
2607 D,
2608 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2609 Level, /*NotLastprivate=*/true))
2610 return OMPC_firstprivate;
2611 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2612 if (DVar.CKind != OMPC_shared &&
2613 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2614 DSAStack->addImplicitTaskFirstprivate(Level, D);
2615 return OMPC_firstprivate;
2616 }
2617 }
2618 }
2619 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2620 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2621 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2622 DSAStack->resetPossibleLoopCounter(D);
2623 DSAStack->loopStart();
2624 return OMPC_private;
2625 }
2626 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2627 DSAStack->isLoopControlVariable(D).first) &&
2628 !DSAStack->hasExplicitDSA(
2629 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2630 Level) &&
2631 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2632 return OMPC_private;
2633 }
2634 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2635 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2636 DSAStack->isForceVarCapturing() &&
2637 !DSAStack->hasExplicitDSA(
2638 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2639 Level))
2640 return OMPC_private;
2641 }
2642 // User-defined allocators are private since they must be defined in the
2643 // context of target region.
2644 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2645 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2646 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2647 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2648 return OMPC_private;
2649 return (DSAStack->hasExplicitDSA(
2650 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2651 Level) ||
2652 (DSAStack->isClauseParsingMode() &&
2653 DSAStack->getClauseParsingMode() == OMPC_private) ||
2654 // Consider taskgroup reduction descriptor variable a private
2655 // to avoid possible capture in the region.
2656 (DSAStack->hasExplicitDirective(
2657 [](OpenMPDirectiveKind K) {
2658 return K == OMPD_taskgroup ||
2659 ((isOpenMPParallelDirective(K) ||
2660 isOpenMPWorksharingDirective(K)) &&
2661 !isOpenMPSimdDirective(K));
2662 },
2663 Level) &&
2664 DSAStack->isTaskgroupReductionRef(D, Level)))
2665 ? OMPC_private
2666 : OMPC_unknown;
2667}
2668
2670 unsigned Level) {
2671 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2672 D = getCanonicalDecl(D);
2673 OpenMPClauseKind OMPC = OMPC_unknown;
2674 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2675 const unsigned NewLevel = I - 1;
2676 if (DSAStack->hasExplicitDSA(
2677 D,
2678 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2679 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2680 OMPC = K;
2681 return true;
2682 }
2683 return false;
2684 },
2685 NewLevel))
2686 break;
2687 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2688 D, NewLevel,
2690 OpenMPClauseKind) { return true; })) {
2691 OMPC = OMPC_map;
2692 break;
2693 }
2694 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2695 NewLevel)) {
2696 OMPC = OMPC_map;
2697 if (DSAStack->mustBeFirstprivateAtLevel(
2699 OMPC = OMPC_firstprivate;
2700 break;
2701 }
2702 }
2703 if (OMPC != OMPC_unknown)
2704 FD->addAttr(
2705 OMPCaptureKindAttr::CreateImplicit(getASTContext(), unsigned(OMPC)));
2706}
2707
2709 unsigned CaptureLevel) const {
2710 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2711 // Return true if the current level is no longer enclosed in a target region.
2712
2714 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2715 const auto *VD = dyn_cast<VarDecl>(D);
2716 return VD && !VD->hasLocalStorage() &&
2717 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2718 Level) &&
2719 Regions[CaptureLevel] != OMPD_task;
2720}
2721
2723 unsigned CaptureLevel) const {
2724 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2725 // Return true if the current level is no longer enclosed in a target region.
2726
2727 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2728 if (!VD->hasLocalStorage()) {
2730 return true;
2731 DSAStackTy::DSAVarData TopDVar =
2732 DSAStack->getTopDSA(D, /*FromParent=*/false);
2733 unsigned NumLevels =
2734 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2735 if (Level == 0)
2736 // non-file scope static variable with default(firstprivate)
2737 // should be global captured.
2738 return (NumLevels == CaptureLevel + 1 &&
2739 (TopDVar.CKind != OMPC_shared ||
2740 DSAStack->getDefaultDSA() == DSA_firstprivate));
2741 do {
2742 --Level;
2743 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2744 if (DVar.CKind != OMPC_shared)
2745 return true;
2746 } while (Level > 0);
2747 }
2748 }
2749 return true;
2750}
2751
2752void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2753
2755 OMPTraitInfo &TI) {
2756 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2757}
2758
2761 "Not in OpenMP declare variant scope!");
2762
2763 OMPDeclareVariantScopes.pop_back();
2764}
2765
2767 const FunctionDecl *Callee,
2768 SourceLocation Loc) {
2769 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2770 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2771 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2772 // Ignore host functions during device analysis.
2773 if (getLangOpts().OpenMPIsTargetDevice &&
2774 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2775 return;
2776 // Ignore nohost functions during host analysis.
2777 if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2778 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2779 return;
2780 const FunctionDecl *FD = Callee->getMostRecentDecl();
2781 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2782 if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2783 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2784 // Diagnose host function called during device codegen.
2785 StringRef HostDevTy =
2786 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2787 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2788 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2789 diag::note_omp_marked_device_type_here)
2790 << HostDevTy;
2791 return;
2792 }
2793 if (!getLangOpts().OpenMPIsTargetDevice &&
2794 !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2795 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2796 // In OpenMP 5.2 or later, if the function has a host variant then allow
2797 // that to be called instead
2798 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2799 for (OMPDeclareVariantAttr *A :
2800 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2801 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2802 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2803 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2804 OMPDeclareTargetDeclAttr::getDeviceType(
2805 VariantFD->getMostRecentDecl());
2806 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2807 return true;
2808 }
2809 return false;
2810 };
2811 if (getLangOpts().OpenMP >= 52 &&
2812 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2813 return;
2814 // Diagnose nohost function called during host codegen.
2815 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2816 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2817 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2818 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2819 diag::note_omp_marked_device_type_here)
2820 << NoHostDevTy;
2821 }
2822}
2823
2825 const DeclarationNameInfo &DirName,
2826 Scope *CurScope, SourceLocation Loc) {
2827 DSAStack->push(DKind, DirName, CurScope, Loc);
2828 SemaRef.PushExpressionEvaluationContext(
2830}
2831
2833 DSAStack->setClauseParsingMode(K);
2834}
2835
2837 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2838 SemaRef.CleanupVarDeclMarking();
2839}
2840
2841static std::pair<ValueDecl *, bool>
2842getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2843 SourceRange &ERange, bool AllowArraySection = false,
2844 bool AllowAssumedSizeArray = false, StringRef DiagType = "");
2845
2846/// Check consistency of the reduction clauses.
2847static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2848 ArrayRef<OMPClause *> Clauses) {
2849 bool InscanFound = false;
2850 SourceLocation InscanLoc;
2851 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2852 // A reduction clause without the inscan reduction-modifier may not appear on
2853 // a construct on which a reduction clause with the inscan reduction-modifier
2854 // appears.
2855 for (OMPClause *C : Clauses) {
2856 if (C->getClauseKind() != OMPC_reduction)
2857 continue;
2858 auto *RC = cast<OMPReductionClause>(C);
2859 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2860 InscanFound = true;
2861 InscanLoc = RC->getModifierLoc();
2862 continue;
2863 }
2864 if (RC->getModifier() == OMPC_REDUCTION_task) {
2865 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2866 // A reduction clause with the task reduction-modifier may only appear on
2867 // a parallel construct, a worksharing construct or a combined or
2868 // composite construct for which any of the aforementioned constructs is a
2869 // constituent construct and simd or loop are not constituent constructs.
2870 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2871 if (!(isOpenMPParallelDirective(CurDir) ||
2873 isOpenMPSimdDirective(CurDir))
2874 S.Diag(RC->getModifierLoc(),
2875 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2876 continue;
2877 }
2878 }
2879 if (InscanFound) {
2880 for (OMPClause *C : Clauses) {
2881 if (C->getClauseKind() != OMPC_reduction)
2882 continue;
2883 auto *RC = cast<OMPReductionClause>(C);
2884 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2885 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2886 ? RC->getBeginLoc()
2887 : RC->getModifierLoc(),
2888 diag::err_omp_inscan_reduction_expected);
2889 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2890 continue;
2891 }
2892 for (Expr *Ref : RC->varlist()) {
2893 assert(Ref && "NULL expr in OpenMP reduction clause.");
2894 SourceLocation ELoc;
2895 SourceRange ERange;
2896 Expr *SimpleRefExpr = Ref;
2897 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2898 /*AllowArraySection=*/true);
2899 ValueDecl *D = Res.first;
2900 if (!D)
2901 continue;
2902 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2903 S.Diag(Ref->getExprLoc(),
2904 diag::err_omp_reduction_not_inclusive_exclusive)
2905 << Ref->getSourceRange();
2906 }
2907 }
2908 }
2909 }
2910}
2911
2912static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2913 ArrayRef<OMPClause *> Clauses);
2914static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2915 bool WithInit);
2916
2917static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2918 const ValueDecl *D,
2919 const DSAStackTy::DSAVarData &DVar,
2920 bool IsLoopIterVar = false);
2921
2923 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2924 // A variable of class type (or array thereof) that appears in a lastprivate
2925 // clause requires an accessible, unambiguous default constructor for the
2926 // class type, unless the list item is also specified in a firstprivate
2927 // clause.
2928
2929 auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) {
2930 SmallVector<Expr *, 8> PrivateCopies;
2931 for (Expr *DE : Clause->varlist()) {
2932 if (DE->isValueDependent() || DE->isTypeDependent()) {
2933 PrivateCopies.push_back(nullptr);
2934 continue;
2935 }
2936 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2937 auto *VD = cast<VarDecl>(DRE->getDecl());
2939 const DSAStackTy::DSAVarData DVar =
2940 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2941 if (DVar.CKind != OMPC_lastprivate) {
2942 // The variable is also a firstprivate, so initialization sequence
2943 // for private copy is generated already.
2944 PrivateCopies.push_back(nullptr);
2945 continue;
2946 }
2947 // Generate helper private variable and initialize it with the
2948 // default value. The address of the original variable is replaced
2949 // by the address of the new private variable in CodeGen. This new
2950 // variable is not added to IdResolver, so the code in the OpenMP
2951 // region uses original variable for proper diagnostics.
2952 VarDecl *VDPrivate = buildVarDecl(
2953 SemaRef, DE->getExprLoc(), Type.getUnqualifiedType(), VD->getName(),
2954 VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2955 SemaRef.ActOnUninitializedDecl(VDPrivate);
2956 if (VDPrivate->isInvalidDecl()) {
2957 PrivateCopies.push_back(nullptr);
2958 continue;
2959 }
2960 PrivateCopies.push_back(buildDeclRefExpr(
2961 SemaRef, VDPrivate, DE->getType(), DE->getExprLoc()));
2962 }
2963 Clause->setPrivateCopies(PrivateCopies);
2964 };
2965
2966 auto FinalizeNontemporal = [&](OMPNontemporalClause *Clause) {
2967 // Finalize nontemporal clause by handling private copies, if any.
2968 SmallVector<Expr *, 8> PrivateRefs;
2969 for (Expr *RefExpr : Clause->varlist()) {
2970 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2971 SourceLocation ELoc;
2972 SourceRange ERange;
2973 Expr *SimpleRefExpr = RefExpr;
2974 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
2975 if (Res.second)
2976 // It will be analyzed later.
2977 PrivateRefs.push_back(RefExpr);
2978 ValueDecl *D = Res.first;
2979 if (!D)
2980 continue;
2981
2982 const DSAStackTy::DSAVarData DVar =
2983 DSAStack->getTopDSA(D, /*FromParent=*/false);
2984 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2985 : SimpleRefExpr);
2986 }
2987 Clause->setPrivateRefs(PrivateRefs);
2988 };
2989
2990 auto FinalizeAllocators = [&](OMPUsesAllocatorsClause *Clause) {
2991 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2992 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2993 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
2994 if (!DRE)
2995 continue;
2996 ValueDecl *VD = DRE->getDecl();
2997 if (!VD || !isa<VarDecl>(VD))
2998 continue;
2999 DSAStackTy::DSAVarData DVar =
3000 DSAStack->getTopDSA(VD, /*FromParent=*/false);
3001 // OpenMP [2.12.5, target Construct]
3002 // Memory allocators that appear in a uses_allocators clause cannot
3003 // appear in other data-sharing attribute clauses or data-mapping
3004 // attribute clauses in the same construct.
3005 Expr *MapExpr = nullptr;
3006 if (DVar.RefExpr ||
3007 DSAStack->checkMappableExprComponentListsForDecl(
3008 VD, /*CurrentRegionOnly=*/true,
3009 [VD, &MapExpr](
3011 MapExprComponents,
3013 auto MI = MapExprComponents.rbegin();
3014 auto ME = MapExprComponents.rend();
3015 if (MI != ME &&
3016 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
3017 VD->getCanonicalDecl()) {
3018 MapExpr = MI->getAssociatedExpression();
3019 return true;
3020 }
3021 return false;
3022 })) {
3023 Diag(D.Allocator->getExprLoc(), diag::err_omp_allocator_used_in_clauses)
3024 << D.Allocator->getSourceRange();
3025 if (DVar.RefExpr)
3027 else
3028 Diag(MapExpr->getExprLoc(), diag::note_used_here)
3029 << MapExpr->getSourceRange();
3030 }
3031 }
3032 };
3033
3034 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
3035 for (OMPClause *C : D->clauses()) {
3036 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
3037 FinalizeLastprivate(Clause);
3038 } else if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
3039 FinalizeNontemporal(Clause);
3040 } else if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
3041 FinalizeAllocators(Clause);
3042 }
3043 }
3044 // Check allocate clauses.
3045 if (!SemaRef.CurContext->isDependentContext())
3046 checkAllocateClauses(SemaRef, DSAStack, D->clauses());
3047 checkReductionClauses(SemaRef, DSAStack, D->clauses());
3048 }
3049
3050 DSAStack->pop();
3053}
3054
3055static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
3056 Expr *NumIterations, Sema &SemaRef,
3057 Scope *S, DSAStackTy *Stack);
3058
3059static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
3060 OMPLoopBasedDirective::HelperExprs &B,
3061 DSAStackTy *Stack) {
3062 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
3063 "loop exprs were not built");
3064
3065 if (SemaRef.CurContext->isDependentContext())
3066 return false;
3067
3068 // Finalize the clauses that need pre-built expressions for CodeGen.
3069 for (OMPClause *C : Clauses) {
3070 auto *LC = dyn_cast<OMPLinearClause>(C);
3071 if (!LC)
3072 continue;
3073 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
3074 B.NumIterations, SemaRef,
3075 SemaRef.getCurScope(), Stack))
3076 return true;
3077 }
3078
3079 return false;
3080}
3081
3082namespace {
3083
3084class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3085private:
3086 Sema &SemaRef;
3087
3088public:
3089 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3090 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3091 NamedDecl *ND = Candidate.getCorrectionDecl();
3092 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3093 return VD->hasGlobalStorage() &&
3094 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3095 SemaRef.getCurScope());
3096 }
3097 return false;
3098 }
3099
3100 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3101 return std::make_unique<VarDeclFilterCCC>(*this);
3102 }
3103};
3104
3105class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3106private:
3107 Sema &SemaRef;
3108
3109public:
3110 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3111 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3112 NamedDecl *ND = Candidate.getCorrectionDecl();
3113 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3114 isa<FunctionDecl>(ND))) {
3115 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3116 SemaRef.getCurScope());
3117 }
3118 return false;
3119 }
3120
3121 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3122 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3123 }
3124};
3125
3126} // namespace
3127
3129 CXXScopeSpec &ScopeSpec,
3130 const DeclarationNameInfo &Id,
3131 OpenMPDirectiveKind Kind) {
3132 ASTContext &Context = getASTContext();
3133 unsigned OMPVersion = getLangOpts().OpenMP;
3135 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
3136 /*ObjectType=*/QualType(),
3137 /*AllowBuiltinCreation=*/true);
3138
3139 if (Lookup.isAmbiguous())
3140 return ExprError();
3141
3142 VarDecl *VD;
3143 if (!Lookup.isSingleResult()) {
3144 VarDeclFilterCCC CCC(SemaRef);
3145 if (TypoCorrection Corrected =
3146 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
3148 SemaRef.diagnoseTypo(
3149 Corrected,
3150 SemaRef.PDiag(Lookup.empty() ? diag::err_undeclared_var_use_suggest
3151 : diag::err_omp_expected_var_arg_suggest)
3152 << Id.getName());
3153 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3154 } else {
3155 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3156 : diag::err_omp_expected_var_arg)
3157 << Id.getName();
3158 return ExprError();
3159 }
3160 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3161 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3162 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3163 return ExprError();
3164 }
3165 Lookup.suppressDiagnostics();
3166
3167 // OpenMP [2.9.2, Syntax, C/C++]
3168 // Variables must be file-scope, namespace-scope, or static block-scope.
3169 if ((Kind == OMPD_threadprivate || Kind == OMPD_groupprivate) &&
3170 !VD->hasGlobalStorage()) {
3171 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3172 << getOpenMPDirectiveName(Kind, OMPVersion) << !VD->isStaticLocal();
3173 bool IsDecl =
3175 Diag(VD->getLocation(),
3176 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3177 << VD;
3178 return ExprError();
3179 }
3180
3181 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3182 NamedDecl *ND = CanonicalVD;
3183 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3184 // A threadprivate or groupprivate directive for file-scope variables must
3185 // appear outside any definition or declaration.
3186 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3187 !SemaRef.getCurLexicalContext()->isTranslationUnit()) {
3188 Diag(Id.getLoc(), diag::err_omp_var_scope)
3189 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3190 bool IsDecl =
3192 Diag(VD->getLocation(),
3193 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3194 << VD;
3195 return ExprError();
3196 }
3197 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3198 // A threadprivate or groupprivate directive for static class member
3199 // variables must appear in the class definition, in the same scope in which
3200 // the member variables are declared.
3201 if (CanonicalVD->isStaticDataMember() &&
3202 !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) {
3203 Diag(Id.getLoc(), diag::err_omp_var_scope)
3204 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3205 bool IsDecl =
3207 Diag(VD->getLocation(),
3208 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3209 << VD;
3210 return ExprError();
3211 }
3212 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3213 // A threadprivate or groupprivate directive for namespace-scope variables
3214 // must appear outside any definition or declaration other than the
3215 // namespace definition itself.
3216 if (CanonicalVD->getDeclContext()->isNamespace() &&
3217 (!SemaRef.getCurLexicalContext()->isFileContext() ||
3218 !SemaRef.getCurLexicalContext()->Encloses(
3219 CanonicalVD->getDeclContext()))) {
3220 Diag(Id.getLoc(), diag::err_omp_var_scope)
3221 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3222 bool IsDecl =
3224 Diag(VD->getLocation(),
3225 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3226 << VD;
3227 return ExprError();
3228 }
3229 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3230 // A threadprivate or groupprivate directive for static block-scope
3231 // variables must appear in the scope of the variable and not in a nested
3232 // scope.
3233 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3234 !SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(), CurScope)) {
3235 Diag(Id.getLoc(), diag::err_omp_var_scope)
3236 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3237 bool IsDecl =
3239 Diag(VD->getLocation(),
3240 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3241 << VD;
3242 return ExprError();
3243 }
3244
3245 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3246 // A threadprivate or groupprivate directive must lexically precede all
3247 // references to any of the variables in its list.
3248 if ((Kind == OMPD_threadprivate && VD->isUsed() &&
3249 !DSAStack->isThreadPrivate(VD)) ||
3250 (Kind == OMPD_groupprivate && VD->isUsed())) {
3251 Diag(Id.getLoc(), diag::err_omp_var_used)
3252 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3253 return ExprError();
3254 }
3255
3256 QualType ExprType = VD->getType().getNonReferenceType();
3258 SourceLocation(), VD,
3259 /*RefersToEnclosingVariableOrCapture=*/false,
3260 Id.getLoc(), ExprType, VK_LValue);
3261}
3262
3265 ArrayRef<Expr *> VarList) {
3266 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3267 SemaRef.CurContext->addDecl(D);
3269 }
3270 return nullptr;
3271}
3272
3275 ArrayRef<Expr *> VarList) {
3276 if (!getLangOpts().OpenMP || getLangOpts().OpenMP < 60) {
3277 Diag(Loc, diag::err_omp_unexpected_directive)
3278 << getOpenMPDirectiveName(OMPD_groupprivate, getLangOpts().OpenMP);
3279 return nullptr;
3280 }
3281 if (OMPGroupPrivateDecl *D = CheckOMPGroupPrivateDecl(Loc, VarList)) {
3282 SemaRef.CurContext->addDecl(D);
3284 }
3285 return nullptr;
3286}
3287
3288namespace {
3289class LocalVarRefChecker final
3290 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3291 Sema &SemaRef;
3292
3293public:
3294 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3295 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3296 if (VD->hasLocalStorage()) {
3297 SemaRef.Diag(E->getBeginLoc(),
3298 diag::err_omp_local_var_in_threadprivate_init)
3299 << E->getSourceRange();
3300 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3301 << VD << VD->getSourceRange();
3302 return true;
3303 }
3304 }
3305 return false;
3306 }
3307 bool VisitStmt(const Stmt *S) {
3308 for (const Stmt *Child : S->children()) {
3309 if (Child && Visit(Child))
3310 return true;
3311 }
3312 return false;
3313 }
3314 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3315};
3316} // namespace
3317
3318OMPThreadPrivateDecl *
3320 ArrayRef<Expr *> VarList) {
3321 ASTContext &Context = getASTContext();
3323 for (Expr *RefExpr : VarList) {
3324 auto *DE = cast<DeclRefExpr>(RefExpr);
3325 auto *VD = cast<VarDecl>(DE->getDecl());
3326 SourceLocation ILoc = DE->getExprLoc();
3327
3328 // Mark variable as used.
3329 VD->setReferenced();
3330 VD->markUsed(Context);
3331
3332 QualType QType = VD->getType();
3333 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3334 // It will be analyzed later.
3335 Vars.push_back(DE);
3336 continue;
3337 }
3338
3339 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3340 // A threadprivate variable must not have an incomplete type.
3341 if (SemaRef.RequireCompleteType(
3342 ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) {
3343 continue;
3344 }
3345
3346 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3347 // A threadprivate variable must not have a reference type.
3348 if (VD->getType()->isReferenceType()) {
3349 unsigned OMPVersion = getLangOpts().OpenMP;
3350 Diag(ILoc, diag::err_omp_ref_type_arg)
3351 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion)
3352 << VD->getType();
3353 bool IsDecl =
3355 Diag(VD->getLocation(),
3356 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3357 << VD;
3358 continue;
3359 }
3360
3361 // Check if this is a TLS variable. If TLS is not being supported, produce
3362 // the corresponding diagnostic.
3363 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3364 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3365 getLangOpts().OpenMPUseTLS &&
3366 getASTContext().getTargetInfo().isTLSSupported())) ||
3367 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3368 !VD->isLocalVarDecl())) {
3369 Diag(ILoc, diag::err_omp_var_thread_local)
3370 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3371 bool IsDecl =
3373 Diag(VD->getLocation(),
3374 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3375 << VD;
3376 continue;
3377 }
3378
3379 // Check if initial value of threadprivate variable reference variable with
3380 // local storage (it is not supported by runtime).
3381 if (const Expr *Init = VD->getAnyInitializer()) {
3382 LocalVarRefChecker Checker(SemaRef);
3383 if (Checker.Visit(Init))
3384 continue;
3385 }
3386
3387 Vars.push_back(RefExpr);
3388 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3389 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3390 Context, SourceRange(Loc, Loc)));
3391 if (ASTMutationListener *ML = Context.getASTMutationListener())
3392 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3393 }
3394 OMPThreadPrivateDecl *D = nullptr;
3395 if (!Vars.empty()) {
3396 D = OMPThreadPrivateDecl::Create(Context, SemaRef.getCurLexicalContext(),
3397 Loc, Vars);
3398 D->setAccess(AS_public);
3399 }
3400 return D;
3401}
3402
3405 ArrayRef<Expr *> VarList) {
3406 ASTContext &Context = getASTContext();
3408 for (Expr *RefExpr : VarList) {
3409 auto *DE = cast<DeclRefExpr>(RefExpr);
3410 auto *VD = cast<VarDecl>(DE->getDecl());
3411 SourceLocation ILoc = DE->getExprLoc();
3412
3413 // Mark variable as used.
3414 VD->setReferenced();
3415 VD->markUsed(Context);
3416
3417 QualType QType = VD->getType();
3418 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3419 // It will be analyzed later.
3420 Vars.push_back(DE);
3421 continue;
3422 }
3423
3424 // OpenMP groupprivate restrictions:
3425 // A groupprivate variable must not have an incomplete type.
3426 if (SemaRef.RequireCompleteType(
3427 ILoc, VD->getType(), diag::err_omp_groupprivate_incomplete_type)) {
3428 continue;
3429 }
3430
3431 // A groupprivate variable must not have a reference type.
3432 if (VD->getType()->isReferenceType()) {
3433 Diag(ILoc, diag::err_omp_ref_type_arg)
3434 << getOpenMPDirectiveName(OMPD_groupprivate) << VD->getType();
3435 bool IsDecl =
3437 Diag(VD->getLocation(),
3438 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3439 << VD;
3440 continue;
3441 }
3442
3443 // A variable that is declared with an initializer must not appear in a
3444 // groupprivate directive.
3445 if (VD->getAnyInitializer()) {
3446 Diag(ILoc, diag::err_omp_groupprivate_with_initializer)
3447 << VD->getDeclName();
3448 bool IsDecl =
3450 Diag(VD->getLocation(),
3451 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3452 << VD;
3453 continue;
3454 }
3455
3456 Vars.push_back(RefExpr);
3457 DSAStack->addDSA(VD, DE, OMPC_groupprivate);
3458 VD->addAttr(OMPGroupPrivateDeclAttr::CreateImplicit(Context,
3459 SourceRange(Loc, Loc)));
3460 if (ASTMutationListener *ML = Context.getASTMutationListener())
3461 ML->DeclarationMarkedOpenMPGroupPrivate(VD);
3462 }
3463 OMPGroupPrivateDecl *D = nullptr;
3464 if (!Vars.empty()) {
3465 D = OMPGroupPrivateDecl::Create(Context, SemaRef.getCurLexicalContext(),
3466 Loc, Vars);
3467 D->setAccess(AS_public);
3468 }
3469 return D;
3470}
3471
3472static OMPAllocateDeclAttr::AllocatorTypeTy
3473getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3474 if (!Allocator)
3475 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3476 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3477 Allocator->isInstantiationDependent() ||
3479 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3480 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3481 llvm::FoldingSetNodeID AEId;
3482 const Expr *AE = Allocator->IgnoreParenImpCasts();
3483 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3484 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3485 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3486 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3487 llvm::FoldingSetNodeID DAEId;
3488 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3489 /*Canonical=*/true);
3490 if (AEId == DAEId) {
3491 AllocatorKindRes = AllocatorKind;
3492 break;
3493 }
3494 }
3495 return AllocatorKindRes;
3496}
3497
3499 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3500 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3501 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3502 return false;
3503 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3504 Expr *PrevAllocator = A->getAllocator();
3505 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3506 getAllocatorKind(S, Stack, PrevAllocator);
3507 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3508 if (AllocatorsMatch &&
3509 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3510 Allocator && PrevAllocator) {
3511 const Expr *AE = Allocator->IgnoreParenImpCasts();
3512 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3513 llvm::FoldingSetNodeID AEId, PAEId;
3514 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3515 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3516 AllocatorsMatch = AEId == PAEId;
3517 }
3518 if (!AllocatorsMatch) {
3519 SmallString<256> AllocatorBuffer;
3520 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3521 if (Allocator)
3522 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3523 SmallString<256> PrevAllocatorBuffer;
3524 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3525 if (PrevAllocator)
3526 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3527 S.getPrintingPolicy());
3528
3529 SourceLocation AllocatorLoc =
3530 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3531 SourceRange AllocatorRange =
3532 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3533 SourceLocation PrevAllocatorLoc =
3534 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3535 SourceRange PrevAllocatorRange =
3536 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3537 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3538 << (Allocator ? 1 : 0) << AllocatorStream.str()
3539 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3540 << AllocatorRange;
3541 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3542 << PrevAllocatorRange;
3543 return true;
3544 }
3545 return false;
3546}
3547
3548static void
3550 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3551 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3552 if (VD->hasAttr<OMPAllocateDeclAttr>())
3553 return;
3554 if (Alignment &&
3555 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3556 Alignment->isInstantiationDependent() ||
3557 Alignment->containsUnexpandedParameterPack()))
3558 // Apply later when we have a usable value.
3559 return;
3560 if (Allocator &&
3561 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3562 Allocator->isInstantiationDependent() ||
3563 Allocator->containsUnexpandedParameterPack()))
3564 return;
3565 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3566 Allocator, Alignment, SR);
3567 VD->addAttr(A);
3569 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3570}
3571
3574 DeclContext *Owner) {
3575 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3576 Expr *Alignment = nullptr;
3577 Expr *Allocator = nullptr;
3578 if (Clauses.empty()) {
3579 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3580 // allocate directives that appear in a target region must specify an
3581 // allocator clause unless a requires directive with the dynamic_allocators
3582 // clause is present in the same compilation unit.
3583 if (getLangOpts().OpenMPIsTargetDevice &&
3584 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3585 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3586 } else {
3587 for (const OMPClause *C : Clauses)
3588 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3589 Allocator = AC->getAllocator();
3590 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3591 Alignment = AC->getAlignment();
3592 else
3593 llvm_unreachable("Unexpected clause on allocate directive");
3594 }
3595 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3596 getAllocatorKind(SemaRef, DSAStack, Allocator);
3598 for (Expr *RefExpr : VarList) {
3599 auto *DE = cast<DeclRefExpr>(RefExpr);
3600 auto *VD = cast<VarDecl>(DE->getDecl());
3601
3602 // Check if this is a TLS variable or global register.
3603 if (VD->getTLSKind() != VarDecl::TLS_None ||
3604 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3605 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3606 !VD->isLocalVarDecl()))
3607 continue;
3608
3609 // If the used several times in the allocate directive, the same allocator
3610 // must be used.
3612 AllocatorKind, Allocator))
3613 continue;
3614
3615 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3616 // If a list item has a static storage type, the allocator expression in the
3617 // allocator clause must be a constant expression that evaluates to one of
3618 // the predefined memory allocator values.
3619 if (Allocator && VD->hasGlobalStorage()) {
3620 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3621 Diag(Allocator->getExprLoc(),
3622 diag::err_omp_expected_predefined_allocator)
3623 << Allocator->getSourceRange();
3624 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3626 Diag(VD->getLocation(),
3627 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3628 << VD;
3629 continue;
3630 }
3631 }
3632
3633 Vars.push_back(RefExpr);
3634 applyOMPAllocateAttribute(SemaRef, VD, AllocatorKind, Allocator, Alignment,
3635 DE->getSourceRange());
3636 }
3637 if (Vars.empty())
3638 return nullptr;
3639 if (!Owner)
3640 Owner = SemaRef.getCurLexicalContext();
3641 auto *D = OMPAllocateDecl::Create(getASTContext(), Owner, Loc, Vars, Clauses);
3642 D->setAccess(AS_public);
3643 Owner->addDecl(D);
3645}
3646
3649 ArrayRef<OMPClause *> ClauseList) {
3650 OMPRequiresDecl *D = nullptr;
3651 if (!SemaRef.CurContext->isFileContext()) {
3652 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3653 } else {
3654 D = CheckOMPRequiresDecl(Loc, ClauseList);
3655 if (D) {
3656 SemaRef.CurContext->addDecl(D);
3657 DSAStack->addRequiresDecl(D);
3658 }
3659 }
3661}
3662
3664 OpenMPDirectiveKind DKind,
3665 ArrayRef<std::string> Assumptions,
3666 bool SkippedClauses) {
3667 if (!SkippedClauses && Assumptions.empty()) {
3668 unsigned OMPVersion = getLangOpts().OpenMP;
3669 Diag(Loc, diag::err_omp_no_clause_for_directive)
3670 << llvm::omp::getAllAssumeClauseOptions()
3671 << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion);
3672 }
3673
3674 auto *AA =
3675 OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc);
3676 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3677 OMPAssumeScoped.push_back(AA);
3678 return;
3679 }
3680
3681 // Global assumes without assumption clauses are ignored.
3682 if (Assumptions.empty())
3683 return;
3684
3685 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3686 "Unexpected omp assumption directive!");
3687 OMPAssumeGlobal.push_back(AA);
3688
3689 // The OMPAssumeGlobal scope above will take care of new declarations but
3690 // we also want to apply the assumption to existing ones, e.g., to
3691 // declarations in included headers. To this end, we traverse all existing
3692 // declaration contexts and annotate function declarations here.
3693 SmallVector<DeclContext *, 8> DeclContexts;
3694 auto *Ctx = SemaRef.CurContext;
3695 while (Ctx->getLexicalParent())
3696 Ctx = Ctx->getLexicalParent();
3697 DeclContexts.push_back(Ctx);
3698 while (!DeclContexts.empty()) {
3699 DeclContext *DC = DeclContexts.pop_back_val();
3700 for (auto *SubDC : DC->decls()) {
3701 if (SubDC->isInvalidDecl())
3702 continue;
3703 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3704 DeclContexts.push_back(CTD->getTemplatedDecl());
3705 llvm::append_range(DeclContexts, CTD->specializations());
3706 continue;
3707 }
3708 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3709 DeclContexts.push_back(DC);
3710 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3711 F->addAttr(AA);
3712 continue;
3713 }
3714 }
3715 }
3716}
3717
3719 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3720 OMPAssumeScoped.pop_back();
3721}
3722
3724 Stmt *AStmt,
3725 SourceLocation StartLoc,
3726 SourceLocation EndLoc) {
3727 if (!AStmt)
3728 return StmtError();
3729
3730 return OMPAssumeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
3731 AStmt);
3732}
3733
3736 ArrayRef<OMPClause *> ClauseList) {
3737 /// For target specific clauses, the requires directive cannot be
3738 /// specified after the handling of any of the target regions in the
3739 /// current compilation unit.
3740 ArrayRef<SourceLocation> TargetLocations =
3741 DSAStack->getEncounteredTargetLocs();
3742 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3743 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3744 for (const OMPClause *CNew : ClauseList) {
3745 // Check if any of the requires clauses affect target regions.
3750 Diag(Loc, diag::err_omp_directive_before_requires)
3751 << "target" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3752 for (SourceLocation TargetLoc : TargetLocations) {
3753 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3754 << "target";
3755 }
3756 } else if (!AtomicLoc.isInvalid() &&
3758 Diag(Loc, diag::err_omp_directive_before_requires)
3759 << "atomic" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3760 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3761 << "atomic";
3762 }
3763 }
3764 }
3765
3766 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3768 getASTContext(), SemaRef.getCurLexicalContext(), Loc, ClauseList);
3769 return nullptr;
3770}
3771
3772static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3773 const ValueDecl *D,
3774 const DSAStackTy::DSAVarData &DVar,
3775 bool IsLoopIterVar) {
3776 if (DVar.RefExpr) {
3777 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3778 << getOpenMPClauseNameForDiag(DVar.CKind);
3779 return;
3780 }
3781 enum {
3782 PDSA_StaticMemberShared,
3783 PDSA_StaticLocalVarShared,
3784 PDSA_LoopIterVarPrivate,
3785 PDSA_LoopIterVarLinear,
3786 PDSA_LoopIterVarLastprivate,
3787 PDSA_ConstVarShared,
3788 PDSA_GlobalVarShared,
3789 PDSA_TaskVarFirstprivate,
3790 PDSA_LocalVarPrivate,
3791 PDSA_Implicit
3792 } Reason = PDSA_Implicit;
3793 bool ReportHint = false;
3794 auto ReportLoc = D->getLocation();
3795 auto *VD = dyn_cast<VarDecl>(D);
3796 if (IsLoopIterVar) {
3797 if (DVar.CKind == OMPC_private)
3798 Reason = PDSA_LoopIterVarPrivate;
3799 else if (DVar.CKind == OMPC_lastprivate)
3800 Reason = PDSA_LoopIterVarLastprivate;
3801 else
3802 Reason = PDSA_LoopIterVarLinear;
3803 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3804 DVar.CKind == OMPC_firstprivate) {
3805 Reason = PDSA_TaskVarFirstprivate;
3806 ReportLoc = DVar.ImplicitDSALoc;
3807 } else if (VD && VD->isStaticLocal())
3808 Reason = PDSA_StaticLocalVarShared;
3809 else if (VD && VD->isStaticDataMember())
3810 Reason = PDSA_StaticMemberShared;
3811 else if (VD && VD->isFileVarDecl())
3812 Reason = PDSA_GlobalVarShared;
3813 else if (D->getType().isConstant(SemaRef.getASTContext()))
3814 Reason = PDSA_ConstVarShared;
3815 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3816 ReportHint = true;
3817 Reason = PDSA_LocalVarPrivate;
3818 }
3819 if (Reason != PDSA_Implicit) {
3820 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
3821 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3822 << Reason << ReportHint
3823 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
3824 } else if (DVar.ImplicitDSALoc.isValid()) {
3825 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3826 << getOpenMPClauseNameForDiag(DVar.CKind);
3827 }
3828}
3829
3832 bool IsAggregateOrDeclareTarget) {
3834 switch (M) {
3835 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3836 case OMPC_DEFAULTMAP_MODIFIER_storage:
3837 Kind = OMPC_MAP_alloc;
3838 break;
3839 case OMPC_DEFAULTMAP_MODIFIER_to:
3840 Kind = OMPC_MAP_to;
3841 break;
3842 case OMPC_DEFAULTMAP_MODIFIER_from:
3843 Kind = OMPC_MAP_from;
3844 break;
3845 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3846 Kind = OMPC_MAP_tofrom;
3847 break;
3848 case OMPC_DEFAULTMAP_MODIFIER_present:
3849 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3850 // If implicit-behavior is present, each variable referenced in the
3851 // construct in the category specified by variable-category is treated as if
3852 // it had been listed in a map clause with the map-type of alloc and
3853 // map-type-modifier of present.
3854 Kind = OMPC_MAP_alloc;
3855 break;
3856 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3857 case OMPC_DEFAULTMAP_MODIFIER_private:
3859 llvm_unreachable("Unexpected defaultmap implicit behavior");
3860 case OMPC_DEFAULTMAP_MODIFIER_none:
3861 case OMPC_DEFAULTMAP_MODIFIER_default:
3863 // IsAggregateOrDeclareTarget could be true if:
3864 // 1. the implicit behavior for aggregate is tofrom
3865 // 2. it's a declare target link
3866 if (IsAggregateOrDeclareTarget) {
3867 Kind = OMPC_MAP_tofrom;
3868 break;
3869 }
3870 llvm_unreachable("Unexpected defaultmap implicit behavior");
3871 }
3872 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3873 return Kind;
3874}
3875
3876namespace {
3877struct VariableImplicitInfo {
3878 static const unsigned MapKindNum = OMPC_MAP_unknown;
3879 static const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3880
3881 llvm::SetVector<Expr *> Privates;
3882 llvm::SetVector<Expr *> Firstprivates;
3883 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3884 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3885 MapModifiers[DefaultmapKindNum];
3886};
3887
3888class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3889 DSAStackTy *Stack;
3890 Sema &SemaRef;
3891 OpenMPDirectiveKind DKind = OMPD_unknown;
3892 bool ErrorFound = false;
3893 bool TryCaptureCXXThisMembers = false;
3894 CapturedStmt *CS = nullptr;
3895
3896 VariableImplicitInfo ImpInfo;
3897 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3898 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3899
3900 void VisitSubCaptures(OMPExecutableDirective *S) {
3901 // Check implicitly captured variables.
3902 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3903 return;
3904 if (S->getDirectiveKind() == OMPD_atomic ||
3905 S->getDirectiveKind() == OMPD_critical ||
3906 S->getDirectiveKind() == OMPD_section ||
3907 S->getDirectiveKind() == OMPD_master ||
3908 S->getDirectiveKind() == OMPD_masked ||
3909 S->getDirectiveKind() == OMPD_scope ||
3910 S->getDirectiveKind() == OMPD_assume ||
3911 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3912 Visit(S->getAssociatedStmt());
3913 return;
3914 }
3915 visitSubCaptures(S->getInnermostCapturedStmt());
3916 // Try to capture inner this->member references to generate correct mappings
3917 // and diagnostics.
3918 if (TryCaptureCXXThisMembers ||
3920 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3921 [](const CapturedStmt::Capture &C) {
3922 return C.capturesThis();
3923 }))) {
3924 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3925 TryCaptureCXXThisMembers = true;
3926 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3927 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3928 }
3929 // In tasks firstprivates are not captured anymore, need to analyze them
3930 // explicitly.
3931 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3932 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3933 for (OMPClause *C : S->clauses())
3934 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3935 for (Expr *Ref : FC->varlist())
3936 Visit(Ref);
3937 }
3938 }
3939 }
3940
3941public:
3942 void VisitDeclRefExpr(DeclRefExpr *E) {
3943 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3947 return;
3948 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3949 // Check the datasharing rules for the expressions in the clauses.
3950 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3951 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3952 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3953 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3954 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3955 Visit(CED->getInit());
3956 return;
3957 }
3958 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3959 // Do not analyze internal variables and do not enclose them into
3960 // implicit clauses.
3961 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3962 return;
3963 VD = VD->getCanonicalDecl();
3964 // Skip internally declared variables.
3965 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3966 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3967 !Stack->isImplicitTaskFirstprivate(VD))
3968 return;
3969 // Skip allocators in uses_allocators clauses.
3970 if (Stack->isUsesAllocatorsDecl(VD))
3971 return;
3972
3973 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3974 // Check if the variable has explicit DSA set and stop analysis if it so.
3975 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3976 return;
3977
3978 // Skip internally declared static variables.
3979 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3980 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3981 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3982 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3983 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3984 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3985 !Stack->isImplicitTaskFirstprivate(VD))
3986 return;
3987
3988 SourceLocation ELoc = E->getExprLoc();
3989 // The default(none) clause requires that each variable that is referenced
3990 // in the construct, and does not have a predetermined data-sharing
3991 // attribute, must have its data-sharing attribute explicitly determined
3992 // by being listed in a data-sharing attribute clause.
3993 if (DVar.CKind == OMPC_unknown &&
3994 (Stack->getDefaultDSA() == DSA_none ||
3995 Stack->getDefaultDSA() == DSA_private ||
3996 Stack->getDefaultDSA() == DSA_firstprivate) &&
3997 isImplicitOrExplicitTaskingRegion(DKind) &&
3998 VarsWithInheritedDSA.count(VD) == 0) {
3999 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
4000 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
4001 Stack->getDefaultDSA() == DSA_private)) {
4002 DSAStackTy::DSAVarData DVar =
4003 Stack->getImplicitDSA(VD, /*FromParent=*/false);
4004 InheritedDSA = DVar.CKind == OMPC_unknown;
4005 }
4006 if (InheritedDSA)
4007 VarsWithInheritedDSA[VD] = E;
4008 if (Stack->getDefaultDSA() == DSA_none)
4009 return;
4010 }
4011
4012 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
4013 // If implicit-behavior is none, each variable referenced in the
4014 // construct that does not have a predetermined data-sharing attribute
4015 // and does not appear in a to or link clause on a declare target
4016 // directive must be listed in a data-mapping attribute clause, a
4017 // data-sharing attribute clause (including a data-sharing attribute
4018 // clause on a combined construct where target. is one of the
4019 // constituent constructs), or an is_device_ptr clause.
4020 OpenMPDefaultmapClauseKind ClauseKind =
4022 if (SemaRef.getLangOpts().OpenMP >= 50) {
4023 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
4024 OMPC_DEFAULTMAP_MODIFIER_none;
4025 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
4026 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
4027 // Only check for data-mapping attribute and is_device_ptr here
4028 // since we have already make sure that the declaration does not
4029 // have a data-sharing attribute above
4030 if (!Stack->checkMappableExprComponentListsForDecl(
4031 VD, /*CurrentRegionOnly=*/true,
4033 MapExprComponents,
4035 auto MI = MapExprComponents.rbegin();
4036 auto ME = MapExprComponents.rend();
4037 return MI != ME && MI->getAssociatedDeclaration() == VD;
4038 })) {
4039 VarsWithInheritedDSA[VD] = E;
4040 return;
4041 }
4042 }
4043 }
4044 if (SemaRef.getLangOpts().OpenMP > 50) {
4045 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
4046 OMPC_DEFAULTMAP_MODIFIER_present;
4047 if (IsModifierPresent) {
4048 if (!llvm::is_contained(ImpInfo.MapModifiers[ClauseKind],
4049 OMPC_MAP_MODIFIER_present)) {
4050 ImpInfo.MapModifiers[ClauseKind].push_back(
4051 OMPC_MAP_MODIFIER_present);
4052 }
4053 }
4054 }
4055
4057 !Stack->isLoopControlVariable(VD).first) {
4058 if (!Stack->checkMappableExprComponentListsForDecl(
4059 VD, /*CurrentRegionOnly=*/true,
4061 StackComponents,
4063 if (SemaRef.LangOpts.OpenMP >= 50)
4064 return !StackComponents.empty();
4065 // Variable is used if it has been marked as an array, array
4066 // section, array shaping or the variable itself.
4067 return StackComponents.size() == 1 ||
4068 llvm::all_of(
4069 llvm::drop_begin(llvm::reverse(StackComponents)),
4070 [](const OMPClauseMappableExprCommon::
4071 MappableComponent &MC) {
4072 return MC.getAssociatedDeclaration() ==
4073 nullptr &&
4074 (isa<ArraySectionExpr>(
4075 MC.getAssociatedExpression()) ||
4076 isa<OMPArrayShapingExpr>(
4077 MC.getAssociatedExpression()) ||
4078 isa<ArraySubscriptExpr>(
4079 MC.getAssociatedExpression()));
4080 });
4081 })) {
4082 bool IsFirstprivate = false;
4083 // By default lambdas are captured as firstprivates.
4084 if (const auto *RD =
4086 IsFirstprivate = RD->isLambda();
4087 IsFirstprivate =
4088 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
4089 if (IsFirstprivate) {
4090 ImpInfo.Firstprivates.insert(E);
4091 } else {
4093 Stack->getDefaultmapModifier(ClauseKind);
4094 if (M == OMPC_DEFAULTMAP_MODIFIER_private) {
4095 ImpInfo.Privates.insert(E);
4096 } else {
4098 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
4099 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
4100 }
4101 }
4102 return;
4103 }
4104 }
4105
4106 // OpenMP [2.9.3.6, Restrictions, p.2]
4107 // A list item that appears in a reduction clause of the innermost
4108 // enclosing worksharing or parallel construct may not be accessed in an
4109 // explicit task.
4110 DVar = Stack->hasInnermostDSA(
4111 VD,
4112 [](OpenMPClauseKind C, bool AppliedToPointee) {
4113 return C == OMPC_reduction && !AppliedToPointee;
4114 },
4115 [](OpenMPDirectiveKind K) {
4116 return isOpenMPParallelDirective(K) ||
4118 },
4119 /*FromParent=*/true);
4120 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4121 ErrorFound = true;
4122 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4123 reportOriginalDsa(SemaRef, Stack, VD, DVar);
4124 return;
4125 }
4126
4127 // Define implicit data-sharing attributes for task.
4128 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
4129 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
4130 (((Stack->getDefaultDSA() == DSA_firstprivate &&
4131 DVar.CKind == OMPC_firstprivate) ||
4132 (Stack->getDefaultDSA() == DSA_private &&
4133 DVar.CKind == OMPC_private)) &&
4134 !DVar.RefExpr)) &&
4135 !Stack->isLoopControlVariable(VD).first) {
4136 if (Stack->getDefaultDSA() == DSA_private)
4137 ImpInfo.Privates.insert(E);
4138 else
4139 ImpInfo.Firstprivates.insert(E);
4140 return;
4141 }
4142
4143 // Store implicitly used globals with declare target link for parent
4144 // target.
4145 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
4146 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
4147 Stack->addToParentTargetRegionLinkGlobals(E);
4148 return;
4149 }
4150 }
4151 }
4152 void VisitMemberExpr(MemberExpr *E) {
4153 if (E->isTypeDependent() || E->isValueDependent() ||
4155 return;
4156 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
4157 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
4158 if (!FD)
4159 return;
4160 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
4161 // Check if the variable has explicit DSA set and stop analysis if it
4162 // so.
4163 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
4164 return;
4165
4167 !Stack->isLoopControlVariable(FD).first &&
4168 !Stack->checkMappableExprComponentListsForDecl(
4169 FD, /*CurrentRegionOnly=*/true,
4171 StackComponents,
4173 return isa<CXXThisExpr>(
4174 cast<MemberExpr>(
4175 StackComponents.back().getAssociatedExpression())
4176 ->getBase()
4177 ->IgnoreParens());
4178 })) {
4179 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
4180 // A bit-field cannot appear in a map clause.
4181 //
4182 if (FD->isBitField())
4183 return;
4184
4185 // Check to see if the member expression is referencing a class that
4186 // has already been explicitly mapped
4187 if (Stack->isClassPreviouslyMapped(TE->getType()))
4188 return;
4189
4191 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4192 OpenMPDefaultmapClauseKind ClauseKind =
4195 Modifier, /*IsAggregateOrDeclareTarget=*/true);
4196 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
4197 return;
4198 }
4199
4200 SourceLocation ELoc = E->getExprLoc();
4201 // OpenMP [2.9.3.6, Restrictions, p.2]
4202 // A list item that appears in a reduction clause of the innermost
4203 // enclosing worksharing or parallel construct may not be accessed in
4204 // an explicit task.
4205 DVar = Stack->hasInnermostDSA(
4206 FD,
4207 [](OpenMPClauseKind C, bool AppliedToPointee) {
4208 return C == OMPC_reduction && !AppliedToPointee;
4209 },
4210 [](OpenMPDirectiveKind K) {
4211 return isOpenMPParallelDirective(K) ||
4213 },
4214 /*FromParent=*/true);
4215 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4216 ErrorFound = true;
4217 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4218 reportOriginalDsa(SemaRef, Stack, FD, DVar);
4219 return;
4220 }
4221
4222 // Define implicit data-sharing attributes for task.
4223 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4224 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4225 !Stack->isLoopControlVariable(FD).first) {
4226 // Check if there is a captured expression for the current field in the
4227 // region. Do not mark it as firstprivate unless there is no captured
4228 // expression.
4229 // TODO: try to make it firstprivate.
4230 if (DVar.CKind != OMPC_unknown)
4231 ImpInfo.Firstprivates.insert(E);
4232 }
4233 return;
4234 }
4237 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4238 DKind, /*NoDiagnose=*/true))
4239 return;
4240 const auto *VD = cast<ValueDecl>(
4241 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4242 if (!Stack->checkMappableExprComponentListsForDecl(
4243 VD, /*CurrentRegionOnly=*/true,
4244 [&CurComponents](
4246 StackComponents,
4248 auto CCI = CurComponents.rbegin();
4249 auto CCE = CurComponents.rend();
4250 for (const auto &SC : llvm::reverse(StackComponents)) {
4251 // Do both expressions have the same kind?
4252 if (CCI->getAssociatedExpression()->getStmtClass() !=
4253 SC.getAssociatedExpression()->getStmtClass())
4254 if (!((isa<ArraySectionExpr>(
4255 SC.getAssociatedExpression()) ||
4256 isa<OMPArrayShapingExpr>(
4257 SC.getAssociatedExpression())) &&
4258 isa<ArraySubscriptExpr>(
4259 CCI->getAssociatedExpression())))
4260 return false;
4261
4262 const Decl *CCD = CCI->getAssociatedDeclaration();
4263 const Decl *SCD = SC.getAssociatedDeclaration();
4264 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4265 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4266 if (SCD != CCD)
4267 return false;
4268 std::advance(CCI, 1);
4269 if (CCI == CCE)
4270 break;
4271 }
4272 return true;
4273 })) {
4274 Visit(E->getBase());
4275 }
4276 } else if (!TryCaptureCXXThisMembers) {
4277 Visit(E->getBase());
4278 }
4279 }
4280 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4281 for (OMPClause *C : S->clauses()) {
4282 // Skip analysis of arguments of private clauses for task|target
4283 // directives.
4284 if (isa_and_nonnull<OMPPrivateClause>(C))
4285 continue;
4286 // Skip analysis of arguments of implicitly defined firstprivate clause
4287 // for task|target directives.
4288 // Skip analysis of arguments of implicitly defined map clause for target
4289 // directives.
4291 C->isImplicit() && !isOpenMPTaskingDirective(DKind))) {
4292 for (Stmt *CC : C->children()) {
4293 if (CC)
4294 Visit(CC);
4295 }
4296 }
4297 }
4298 // Check implicitly captured variables.
4299 VisitSubCaptures(S);
4300 }
4301
4302 void VisitOMPCanonicalLoopNestTransformationDirective(
4303 OMPCanonicalLoopNestTransformationDirective *S) {
4304 // Loop transformation directives do not introduce data sharing
4305 VisitStmt(S);
4306 }
4307
4308 void VisitCallExpr(CallExpr *S) {
4309 for (Stmt *C : S->arguments()) {
4310 if (C) {
4311 // Check implicitly captured variables in the task-based directives to
4312 // check if they must be firstprivatized.
4313 Visit(C);
4314 }
4315 }
4316 if (Expr *Callee = S->getCallee()) {
4317 auto *CI = Callee->IgnoreParenImpCasts();
4318 if (auto *CE = dyn_cast<MemberExpr>(CI))
4319 Visit(CE->getBase());
4320 else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4321 Visit(CE);
4322 }
4323 }
4324 void VisitStmt(Stmt *S) {
4325 for (Stmt *C : S->children()) {
4326 if (C) {
4327 // Check implicitly captured variables in the task-based directives to
4328 // check if they must be firstprivatized.
4329 Visit(C);
4330 }
4331 }
4332 }
4333
4334 void visitSubCaptures(CapturedStmt *S) {
4335 for (const CapturedStmt::Capture &Cap : S->captures()) {
4336 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4337 continue;
4338 VarDecl *VD = Cap.getCapturedVar();
4339 // Do not try to map the variable if it or its sub-component was mapped
4340 // already.
4342 Stack->checkMappableExprComponentListsForDecl(
4343 VD, /*CurrentRegionOnly=*/true,
4345 OpenMPClauseKind) { return true; }))
4346 continue;
4347 DeclRefExpr *DRE = buildDeclRefExpr(
4348 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4349 Cap.getLocation(), /*RefersToCapture=*/true);
4350 Visit(DRE);
4351 }
4352 }
4353 bool isErrorFound() const { return ErrorFound; }
4354 const VariableImplicitInfo &getImplicitInfo() const { return ImpInfo; }
4355 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4356 return VarsWithInheritedDSA;
4357 }
4358
4359 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4360 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4361 DKind = S->getCurrentDirective();
4362 // Process declare target link variables for the target directives.
4364 for (DeclRefExpr *E : Stack->getLinkGlobals())
4365 Visit(E);
4366 }
4367 }
4368};
4369} // namespace
4370
4371static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4372 OpenMPDirectiveKind DKind,
4373 bool ScopeEntry) {
4376 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4377 if (isOpenMPTeamsDirective(DKind))
4378 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4379 if (isOpenMPParallelDirective(DKind))
4380 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4382 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4383 if (isOpenMPSimdDirective(DKind))
4384 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4385 Stack->handleConstructTrait(Traits, ScopeEntry);
4386}
4387
4388static SmallVector<SemaOpenMP::CapturedParamNameType>
4389getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4390 ASTContext &Context = SemaRef.getASTContext();
4391 QualType KmpInt32Ty =
4392 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4393 QualType KmpInt32PtrTy =
4394 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4396 std::make_pair(".global_tid.", KmpInt32PtrTy),
4397 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4398 };
4399 if (LoopBoundSharing) {
4400 QualType KmpSizeTy = Context.getSizeType().withConst();
4401 Params.push_back(std::make_pair(".previous.lb.", KmpSizeTy));
4402 Params.push_back(std::make_pair(".previous.ub.", KmpSizeTy));
4403 }
4404
4405 // __context with shared vars
4406 Params.push_back(std::make_pair(StringRef(), QualType()));
4407 return Params;
4408}
4409
4410static SmallVector<SemaOpenMP::CapturedParamNameType>
4412 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4413}
4414
4415static SmallVector<SemaOpenMP::CapturedParamNameType>
4417 ASTContext &Context = SemaRef.getASTContext();
4418 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4419 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4420 QualType KmpInt32PtrTy =
4421 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4422 QualType Args[] = {VoidPtrTy};
4424 EPI.Variadic = true;
4425 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4427 std::make_pair(".global_tid.", KmpInt32Ty),
4428 std::make_pair(".part_id.", KmpInt32PtrTy),
4429 std::make_pair(".privates.", VoidPtrTy),
4430 std::make_pair(
4431 ".copy_fn.",
4432 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4433 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4434 std::make_pair(StringRef(), QualType()) // __context with shared vars
4435 };
4436 return Params;
4437}
4438
4439static SmallVector<SemaOpenMP::CapturedParamNameType>
4441 ASTContext &Context = SemaRef.getASTContext();
4443 if (SemaRef.getLangOpts().OpenMPIsTargetDevice) {
4444 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4445 Params.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4446 }
4447 // __context with shared vars
4448 Params.push_back(std::make_pair(StringRef(), QualType()));
4449 return Params;
4450}
4451
4452static SmallVector<SemaOpenMP::CapturedParamNameType>
4455 std::make_pair(StringRef(), QualType()) // __context with shared vars
4456 };
4457 return Params;
4458}
4459
4460static SmallVector<SemaOpenMP::CapturedParamNameType>
4462 ASTContext &Context = SemaRef.getASTContext();
4463 QualType KmpInt32Ty =
4464 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4465 QualType KmpUInt64Ty =
4466 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4467 QualType KmpInt64Ty =
4468 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4469 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4470 QualType KmpInt32PtrTy =
4471 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4472 QualType Args[] = {VoidPtrTy};
4474 EPI.Variadic = true;
4475 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4477 std::make_pair(".global_tid.", KmpInt32Ty),
4478 std::make_pair(".part_id.", KmpInt32PtrTy),
4479 std::make_pair(".privates.", VoidPtrTy),
4480 std::make_pair(
4481 ".copy_fn.",
4482 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4483 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4484 std::make_pair(".lb.", KmpUInt64Ty),
4485 std::make_pair(".ub.", KmpUInt64Ty),
4486 std::make_pair(".st.", KmpInt64Ty),
4487 std::make_pair(".liter.", KmpInt32Ty),
4488 std::make_pair(".reductions.", VoidPtrTy),
4489 std::make_pair(StringRef(), QualType()) // __context with shared vars
4490 };
4491 return Params;
4492}
4493
4495 Scope *CurScope, SourceLocation Loc) {
4497 getOpenMPCaptureRegions(Regions, DKind);
4498
4499 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(DKind);
4500
4501 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4502 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4503 SemaRef.getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4504 };
4505
4506 for (auto [Level, RKind] : llvm::enumerate(Regions)) {
4507 switch (RKind) {
4508 // All region kinds that can be returned from `getOpenMPCaptureRegions`
4509 // are listed here.
4510 case OMPD_parallel:
4512 Loc, CurScope, CR_OpenMP,
4513 getParallelRegionParams(SemaRef, LoopBoundSharing), Level);
4514 break;
4515 case OMPD_teams:
4516 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4517 getTeamsRegionParams(SemaRef), Level);
4518 break;
4519 case OMPD_task:
4520 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4521 getTaskRegionParams(SemaRef), Level);
4522 // Mark this captured region as inlined, because we don't use outlined
4523 // function directly.
4524 MarkAsInlined(SemaRef.getCurCapturedRegion());
4525 break;
4526 case OMPD_taskloop:
4527 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4528 getTaskloopRegionParams(SemaRef), Level);
4529 // Mark this captured region as inlined, because we don't use outlined
4530 // function directly.
4531 MarkAsInlined(SemaRef.getCurCapturedRegion());
4532 break;
4533 case OMPD_target:
4534 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4535 getTargetRegionParams(SemaRef), Level);
4536 break;
4537 case OMPD_unknown:
4538 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4539 getUnknownRegionParams(SemaRef));
4540 break;
4541 case OMPD_metadirective:
4542 case OMPD_nothing:
4543 default:
4544 llvm_unreachable("Unexpected capture region");
4545 }
4546 }
4547}
4548
4550 Scope *CurScope) {
4551 switch (DKind) {
4552 case OMPD_atomic:
4553 case OMPD_critical:
4554 case OMPD_masked:
4555 case OMPD_master:
4556 case OMPD_section:
4557 case OMPD_tile:
4558 case OMPD_stripe:
4559 case OMPD_unroll:
4560 case OMPD_reverse:
4561 case OMPD_interchange:
4562 case OMPD_fuse:
4563 case OMPD_assume:
4564 break;
4565 default:
4566 processCapturedRegions(SemaRef, DKind, CurScope,
4567 DSAStack->getConstructLoc());
4568 break;
4569 }
4570
4571 DSAStack->setContext(SemaRef.CurContext);
4572 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
4573}
4574
4575int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4576 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4577}
4578
4581 getOpenMPCaptureRegions(CaptureRegions, DKind);
4582 return CaptureRegions.size();
4583}
4584
4586 Expr *CaptureExpr, bool WithInit,
4587 DeclContext *CurContext,
4588 bool AsExpression) {
4589 assert(CaptureExpr);
4590 ASTContext &C = S.getASTContext();
4591 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4592 QualType Ty = Init->getType();
4593 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4594 if (S.getLangOpts().CPlusPlus) {
4595 Ty = C.getLValueReferenceType(Ty);
4596 } else {
4597 Ty = C.getPointerType(Ty);
4598 ExprResult Res =
4599 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4600 if (!Res.isUsable())
4601 return nullptr;
4602 Init = Res.get();
4603 }
4604 WithInit = true;
4605 }
4606 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4607 CaptureExpr->getBeginLoc());
4608 if (!WithInit)
4609 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4610 CurContext->addHiddenDecl(CED);
4612 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4613 return CED;
4614}
4615
4616static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4617 bool WithInit) {
4619 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4621 else
4622 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4623 S.CurContext,
4624 /*AsExpression=*/false);
4625 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4626 CaptureExpr->getExprLoc());
4627}
4628
4629static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4630 StringRef Name) {
4631 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4632 if (!Ref) {
4634 S, &S.getASTContext().Idents.get(Name), CaptureExpr,
4635 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4636 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4637 CaptureExpr->getExprLoc());
4638 }
4639 ExprResult Res = Ref;
4640 if (!S.getLangOpts().CPlusPlus &&
4641 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4642 Ref->getType()->isPointerType()) {
4643 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4644 if (!Res.isUsable())
4645 return ExprError();
4646 }
4647 return S.DefaultLvalueConversion(Res.get());
4648}
4649
4650namespace {
4651// OpenMP directives parsed in this section are represented as a
4652// CapturedStatement with an associated statement. If a syntax error
4653// is detected during the parsing of the associated statement, the
4654// compiler must abort processing and close the CapturedStatement.
4655//
4656// Combined directives such as 'target parallel' have more than one
4657// nested CapturedStatements. This RAII ensures that we unwind out
4658// of all the nested CapturedStatements when an error is found.
4659class CaptureRegionUnwinderRAII {
4660private:
4661 Sema &S;
4662 bool &ErrorFound;
4663 OpenMPDirectiveKind DKind = OMPD_unknown;
4664
4665public:
4666 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4667 OpenMPDirectiveKind DKind)
4668 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4669 ~CaptureRegionUnwinderRAII() {
4670 if (ErrorFound) {
4671 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4672 while (--ThisCaptureLevel >= 0)
4674 }
4675 }
4676};
4677} // namespace
4678
4680 // Capture variables captured by reference in lambdas for target-based
4681 // directives.
4682 if (!SemaRef.CurContext->isDependentContext() &&
4683 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4685 DSAStack->getCurrentDirective()))) {
4686 QualType Type = V->getType();
4687 if (const auto *RD = Type.getCanonicalType()
4688 .getNonReferenceType()
4689 ->getAsCXXRecordDecl()) {
4690 bool SavedForceCaptureByReferenceInTargetExecutable =
4691 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4692 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4693 /*V=*/true);
4694 if (RD->isLambda()) {
4695 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4696 FieldDecl *ThisCapture;
4697 RD->getCaptureFields(Captures, ThisCapture);
4698 for (const LambdaCapture &LC : RD->captures()) {
4699 if (LC.getCaptureKind() == LCK_ByRef) {
4700 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4701 DeclContext *VDC = VD->getDeclContext();
4702 if (!VDC->Encloses(SemaRef.CurContext))
4703 continue;
4704 SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
4705 } else if (LC.getCaptureKind() == LCK_This) {
4706 QualType ThisTy = SemaRef.getCurrentThisType();
4707 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4708 ThisTy, ThisCapture->getType()))
4709 SemaRef.CheckCXXThisCapture(LC.getLocation());
4710 }
4711 }
4712 }
4713 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4714 SavedForceCaptureByReferenceInTargetExecutable);
4715 }
4716 }
4717}
4718
4720 const ArrayRef<OMPClause *> Clauses) {
4721 const OMPOrderedClause *Ordered = nullptr;
4722 const OMPOrderClause *Order = nullptr;
4723
4724 for (const OMPClause *Clause : Clauses) {
4725 if (Clause->getClauseKind() == OMPC_ordered)
4726 Ordered = cast<OMPOrderedClause>(Clause);
4727 else if (Clause->getClauseKind() == OMPC_order) {
4728 Order = cast<OMPOrderClause>(Clause);
4729 if (Order->getKind() != OMPC_ORDER_concurrent)
4730 Order = nullptr;
4731 }
4732 if (Ordered && Order)
4733 break;
4734 }
4735
4736 if (Ordered && Order) {
4737 S.Diag(Order->getKindKwLoc(),
4738 diag::err_omp_simple_clause_incompatible_with_ordered)
4739 << getOpenMPClauseNameForDiag(OMPC_order)
4740 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4741 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4742 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4743 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4744 return true;
4745 }
4746 return false;
4747}
4748
4750 ArrayRef<OMPClause *> Clauses) {
4752 /*ScopeEntry=*/false);
4753 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
4754 return S;
4755
4756 bool ErrorFound = false;
4757 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4758 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4759 if (!S.isUsable()) {
4760 ErrorFound = true;
4761 return StmtError();
4762 }
4763
4765 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4766 OMPOrderedClause *OC = nullptr;
4767 OMPScheduleClause *SC = nullptr;
4770 // This is required for proper codegen.
4771 for (OMPClause *Clause : Clauses) {
4772 if (!getLangOpts().OpenMPSimd &&
4773 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4774 DSAStack->getCurrentDirective() == OMPD_target) &&
4775 Clause->getClauseKind() == OMPC_in_reduction) {
4776 // Capture taskgroup task_reduction descriptors inside the tasking regions
4777 // with the corresponding in_reduction items.
4778 auto *IRC = cast<OMPInReductionClause>(Clause);
4779 for (Expr *E : IRC->taskgroup_descriptors())
4780 if (E)
4781 SemaRef.MarkDeclarationsReferencedInExpr(E);
4782 }
4783 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4784 Clause->getClauseKind() == OMPC_copyprivate ||
4785 (getLangOpts().OpenMPUseTLS &&
4786 getASTContext().getTargetInfo().isTLSSupported() &&
4787 Clause->getClauseKind() == OMPC_copyin)) {
4788 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4789 // Mark all variables in private list clauses as used in inner region.
4790 for (Stmt *VarRef : Clause->children()) {
4791 if (auto *E = cast_or_null<Expr>(VarRef)) {
4792 SemaRef.MarkDeclarationsReferencedInExpr(E);
4793 }
4794 }
4795 DSAStack->setForceVarCapturing(/*V=*/false);
4796 } else if (CaptureRegions.size() > 1 ||
4797 CaptureRegions.back() != OMPD_unknown) {
4798 if (auto *C = OMPClauseWithPreInit::get(Clause))
4799 PICs.push_back(C);
4800 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4801 if (Expr *E = C->getPostUpdateExpr())
4802 SemaRef.MarkDeclarationsReferencedInExpr(E);
4803 }
4804 }
4805 if (Clause->getClauseKind() == OMPC_schedule)
4806 SC = cast<OMPScheduleClause>(Clause);
4807 else if (Clause->getClauseKind() == OMPC_ordered)
4808 OC = cast<OMPOrderedClause>(Clause);
4809 else if (Clause->getClauseKind() == OMPC_linear)
4810 LCs.push_back(cast<OMPLinearClause>(Clause));
4811 }
4812 // Capture allocator expressions if used.
4813 for (Expr *E : DSAStack->getInnerAllocators())
4814 SemaRef.MarkDeclarationsReferencedInExpr(E);
4815 // OpenMP, 2.7.1 Loop Construct, Restrictions
4816 // The nonmonotonic modifier cannot be specified if an ordered clause is
4817 // specified.
4818 if (SC &&
4819 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4821 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4822 OC) {
4823 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4826 diag::err_omp_simple_clause_incompatible_with_ordered)
4827 << getOpenMPClauseNameForDiag(OMPC_schedule)
4828 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4829 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4830 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4831 ErrorFound = true;
4832 }
4833 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4834 // If an order(concurrent) clause is present, an ordered clause may not appear
4835 // on the same directive.
4836 if (checkOrderedOrderSpecified(SemaRef, Clauses))
4837 ErrorFound = true;
4838 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4839 for (const OMPLinearClause *C : LCs) {
4840 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4841 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4842 }
4843 ErrorFound = true;
4844 }
4845 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4846 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4847 OC->getNumForLoops()) {
4848 unsigned OMPVersion = getLangOpts().OpenMP;
4849 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4850 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(), OMPVersion);
4851 ErrorFound = true;
4852 }
4853 if (ErrorFound) {
4854 return StmtError();
4855 }
4856 StmtResult SR = S;
4857 unsigned CompletedRegions = 0;
4858 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4859 // Mark all variables in private list clauses as used in inner region.
4860 // Required for proper codegen of combined directives.
4861 // TODO: add processing for other clauses.
4862 if (ThisCaptureRegion != OMPD_unknown) {
4863 for (const clang::OMPClauseWithPreInit *C : PICs) {
4864 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4865 // Find the particular capture region for the clause if the
4866 // directive is a combined one with multiple capture regions.
4867 // If the directive is not a combined one, the capture region
4868 // associated with the clause is OMPD_unknown and is generated
4869 // only once.
4870 if (CaptureRegion == ThisCaptureRegion ||
4871 CaptureRegion == OMPD_unknown) {
4872 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4873 for (Decl *D : DS->decls())
4874 SemaRef.MarkVariableReferenced(D->getLocation(),
4875 cast<VarDecl>(D));
4876 }
4877 }
4878 }
4879 }
4880 if (ThisCaptureRegion == OMPD_target) {
4881 // Capture allocator traits in the target region. They are used implicitly
4882 // and, thus, are not captured by default.
4883 for (OMPClause *C : Clauses) {
4884 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4885 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4886 ++I) {
4887 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4888 if (Expr *E = D.AllocatorTraits)
4889 SemaRef.MarkDeclarationsReferencedInExpr(E);
4890 }
4891 continue;
4892 }
4893 }
4894 }
4895 if (ThisCaptureRegion == OMPD_parallel) {
4896 // Capture temp arrays for inscan reductions and locals in aligned
4897 // clauses.
4898 for (OMPClause *C : Clauses) {
4899 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4900 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4901 continue;
4902 for (Expr *E : RC->copy_array_temps())
4903 if (E)
4904 SemaRef.MarkDeclarationsReferencedInExpr(E);
4905 }
4906 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4907 for (Expr *E : AC->varlist())
4908 SemaRef.MarkDeclarationsReferencedInExpr(E);
4909 }
4910 }
4911 }
4912 if (++CompletedRegions == CaptureRegions.size())
4913 DSAStack->setBodyComplete();
4914 SR = SemaRef.ActOnCapturedRegionEnd(SR.get());
4915 }
4916 return SR;
4917}
4918
4919static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4920 OpenMPDirectiveKind CancelRegion,
4921 SourceLocation StartLoc) {
4922 // CancelRegion is only needed for cancel and cancellation_point.
4923 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4924 return false;
4925
4926 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4927 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4928 return false;
4929
4930 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
4931 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4932 << getOpenMPDirectiveName(CancelRegion, OMPVersion);
4933 return true;
4934}
4935
4936static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4937 OpenMPDirectiveKind CurrentRegion,
4938 const DeclarationNameInfo &CurrentName,
4939 OpenMPDirectiveKind CancelRegion,
4940 OpenMPBindClauseKind BindKind,
4941 SourceLocation StartLoc) {
4942 if (!Stack->getCurScope())
4943 return false;
4944
4945 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4946 OpenMPDirectiveKind OffendingRegion = ParentRegion;
4947 bool NestingProhibited = false;
4948 bool CloseNesting = true;
4949 bool OrphanSeen = false;
4950 enum {
4951 NoRecommend,
4952 ShouldBeInParallelRegion,
4953 ShouldBeInOrderedRegion,
4954 ShouldBeInTargetRegion,
4955 ShouldBeInTeamsRegion,
4956 ShouldBeInLoopSimdRegion,
4957 } Recommend = NoRecommend;
4958
4961 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4962 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
4963 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
4964
4965 if (OMPVersion >= 50 && Stack->isParentOrderConcurrent() &&
4967 SemaRef.LangOpts)) {
4968 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
4969 << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
4970 return true;
4971 }
4972 if (isOpenMPSimdDirective(ParentRegion) &&
4973 ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered) ||
4974 (OMPVersion >= 50 && CurrentRegion != OMPD_ordered &&
4975 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4976 CurrentRegion != OMPD_scan))) {
4977 // OpenMP [2.16, Nesting of Regions]
4978 // OpenMP constructs may not be nested inside a simd region.
4979 // OpenMP [2.8.1,simd Construct, Restrictions]
4980 // An ordered construct with the simd clause is the only OpenMP
4981 // construct that can appear in the simd region.
4982 // Allowing a SIMD construct nested in another SIMD construct is an
4983 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
4984 // message.
4985 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
4986 // The only OpenMP constructs that can be encountered during execution of
4987 // a simd region are the atomic construct, the loop construct, the simd
4988 // construct and the ordered construct with the simd clause.
4989 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
4990 ? diag::err_omp_prohibited_region_simd
4991 : diag::warn_omp_nesting_simd)
4992 << (OMPVersion >= 50 ? 1 : 0);
4993 return CurrentRegion != OMPD_simd;
4994 }
4995 if (EnclosingConstruct == OMPD_atomic) {
4996 // OpenMP [2.16, Nesting of Regions]
4997 // OpenMP constructs may not be nested inside an atomic region.
4998 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
4999 return true;
5000 }
5001 if (CurrentRegion == OMPD_section) {
5002 // OpenMP [2.7.2, sections Construct, Restrictions]
5003 // Orphaned section directives are prohibited. That is, the section
5004 // directives must appear within the sections construct and must not be
5005 // encountered elsewhere in the sections region.
5006 if (EnclosingConstruct != OMPD_sections) {
5007 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
5008 << (ParentRegion != OMPD_unknown)
5009 << getOpenMPDirectiveName(ParentRegion, OMPVersion);
5010 return true;
5011 }
5012 return false;
5013 }
5014 // Allow some constructs (except teams and cancellation constructs) to be
5015 // orphaned (they could be used in functions, called from OpenMP regions
5016 // with the required preconditions).
5017 if (ParentRegion == OMPD_unknown &&
5018 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
5019 CurrentRegion != OMPD_cancellation_point &&
5020 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5021 return false;
5022 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
5023 // for a detailed explanation
5024 if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
5025 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
5026 (isOpenMPWorksharingDirective(ParentRegion) ||
5027 EnclosingConstruct == OMPD_loop)) {
5028 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
5029 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5030 << true << getOpenMPDirectiveName(ParentRegion, OMPVersion)
5031 << ErrorMsgNumber << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5032 return true;
5033 }
5034 if (CurrentRegion == OMPD_cancellation_point ||
5035 CurrentRegion == OMPD_cancel) {
5036 // OpenMP [2.16, Nesting of Regions]
5037 // A cancellation point construct for which construct-type-clause is
5038 // taskgroup must be nested inside a task construct. A cancellation
5039 // point construct for which construct-type-clause is not taskgroup must
5040 // be closely nested inside an OpenMP construct that matches the type
5041 // specified in construct-type-clause.
5042 // A cancel construct for which construct-type-clause is taskgroup must be
5043 // nested inside a task construct. A cancel construct for which
5044 // construct-type-clause is not taskgroup must be closely nested inside an
5045 // OpenMP construct that matches the type specified in
5046 // construct-type-clause.
5047 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(ParentRegion);
5048 if (CancelRegion == OMPD_taskgroup) {
5049 NestingProhibited =
5050 EnclosingConstruct != OMPD_task &&
5051 (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
5052 } else if (CancelRegion == OMPD_sections) {
5053 NestingProhibited = EnclosingConstruct != OMPD_section &&
5054 EnclosingConstruct != OMPD_sections;
5055 } else {
5056 NestingProhibited = CancelRegion != Leafs.back();
5057 }
5058 OrphanSeen = ParentRegion == OMPD_unknown;
5059 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5060 // OpenMP 5.1 [2.22, Nesting of Regions]
5061 // A masked region may not be closely nested inside a worksharing, loop,
5062 // atomic, task, or taskloop region.
5063 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5064 isOpenMPGenericLoopDirective(ParentRegion) ||
5065 isOpenMPTaskingDirective(ParentRegion);
5066 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5067 // OpenMP [2.16, Nesting of Regions]
5068 // A critical region may not be nested (closely or otherwise) inside a
5069 // critical region with the same name. Note that this restriction is not
5070 // sufficient to prevent deadlock.
5071 SourceLocation PreviousCriticalLoc;
5072 bool DeadLock = Stack->hasDirective(
5073 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5074 const DeclarationNameInfo &DNI,
5075 SourceLocation Loc) {
5076 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5077 PreviousCriticalLoc = Loc;
5078 return true;
5079 }
5080 return false;
5081 },
5082 false /* skip top directive */);
5083 if (DeadLock) {
5084 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
5085 << CurrentName.getName();
5086 if (PreviousCriticalLoc.isValid())
5087 SemaRef.Diag(PreviousCriticalLoc,
5088 diag::note_omp_previous_critical_region);
5089 return true;
5090 }
5091 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5092 // OpenMP 5.1 [2.22, Nesting of Regions]
5093 // A scope region may not be closely nested inside a worksharing, loop,
5094 // task, taskloop, critical, ordered, atomic, or masked region.
5095 // OpenMP 5.1 [2.22, Nesting of Regions]
5096 // A barrier region may not be closely nested inside a worksharing, loop,
5097 // task, taskloop, critical, ordered, atomic, or masked region.
5098 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5099 isOpenMPGenericLoopDirective(ParentRegion) ||
5100 isOpenMPTaskingDirective(ParentRegion) ||
5101 llvm::is_contained({OMPD_masked, OMPD_master,
5102 OMPD_critical, OMPD_ordered},
5103 EnclosingConstruct);
5104 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
5105 !isOpenMPParallelDirective(CurrentRegion) &&
5106 !isOpenMPTeamsDirective(CurrentRegion)) {
5107 // OpenMP 5.1 [2.22, Nesting of Regions]
5108 // A loop region that binds to a parallel region or a worksharing region
5109 // may not be closely nested inside a worksharing, loop, task, taskloop,
5110 // critical, ordered, atomic, or masked region.
5111 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5112 isOpenMPGenericLoopDirective(ParentRegion) ||
5113 isOpenMPTaskingDirective(ParentRegion) ||
5114 llvm::is_contained({OMPD_masked, OMPD_master,
5115 OMPD_critical, OMPD_ordered},
5116 EnclosingConstruct);
5117 Recommend = ShouldBeInParallelRegion;
5118 } else if (CurrentRegion == OMPD_ordered) {
5119 // OpenMP [2.16, Nesting of Regions]
5120 // An ordered region may not be closely nested inside a critical,
5121 // atomic, or explicit task region.
5122 // An ordered region must be closely nested inside a loop region (or
5123 // parallel loop region) with an ordered clause.
5124 // OpenMP [2.8.1,simd Construct, Restrictions]
5125 // An ordered construct with the simd clause is the only OpenMP construct
5126 // that can appear in the simd region.
5127 NestingProhibited = EnclosingConstruct == OMPD_critical ||
5128 isOpenMPTaskingDirective(ParentRegion) ||
5129 !(isOpenMPSimdDirective(ParentRegion) ||
5130 Stack->isParentOrderedRegion());
5131 Recommend = ShouldBeInOrderedRegion;
5132 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
5133 // OpenMP [2.16, Nesting of Regions]
5134 // If specified, a teams construct must be contained within a target
5135 // construct.
5136 NestingProhibited =
5137 (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
5138 (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
5139 EnclosingConstruct != OMPD_target);
5140 OrphanSeen = ParentRegion == OMPD_unknown;
5141 Recommend = ShouldBeInTargetRegion;
5142 } else if (CurrentRegion == OMPD_scan) {
5143 if (OMPVersion >= 50) {
5144 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
5145 // simd, or for simd. This has to take into account combined directives.
5146 // In 5.2 this seems to be implied by the fact that the specified
5147 // separated constructs are do, for, and simd.
5148 NestingProhibited = !llvm::is_contained(
5149 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
5150 } else {
5151 NestingProhibited = true;
5152 }
5153 OrphanSeen = ParentRegion == OMPD_unknown;
5154 Recommend = ShouldBeInLoopSimdRegion;
5155 }
5156 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5157 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5158 EnclosingConstruct == OMPD_teams) {
5159 // OpenMP [5.1, 2.22, Nesting of Regions]
5160 // distribute, distribute simd, distribute parallel worksharing-loop,
5161 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5162 // including any parallel regions arising from combined constructs,
5163 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5164 // only OpenMP regions that may be strictly nested inside the teams
5165 // region.
5166 //
5167 // As an extension, we permit atomic within teams as well.
5168 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5169 !isOpenMPDistributeDirective(CurrentRegion) &&
5170 CurrentRegion != OMPD_loop &&
5171 !(SemaRef.getLangOpts().OpenMPExtensions &&
5172 CurrentRegion == OMPD_atomic);
5173 Recommend = ShouldBeInParallelRegion;
5174 }
5175 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5176 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5177 // If the bind clause is present on the loop construct and binding is
5178 // teams then the corresponding loop region must be strictly nested inside
5179 // a teams region.
5180 NestingProhibited =
5181 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5182 Recommend = ShouldBeInTeamsRegion;
5183 }
5184 if (!NestingProhibited && isOpenMPNestingDistributeDirective(CurrentRegion)) {
5185 // OpenMP 4.5 [2.17 Nesting of Regions]
5186 // The region associated with the distribute construct must be strictly
5187 // nested inside a teams region
5188 NestingProhibited = EnclosingConstruct != OMPD_teams;
5189 Recommend = ShouldBeInTeamsRegion;
5190 }
5191 if (!NestingProhibited &&
5192 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5193 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5194 // OpenMP 4.5 [2.17 Nesting of Regions]
5195 // If a target, target update, target data, target enter data, or
5196 // target exit data construct is encountered during execution of a
5197 // target region, the behavior is unspecified.
5198 NestingProhibited = Stack->hasDirective(
5199 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5202 OffendingRegion = K;
5203 return true;
5204 }
5205 return false;
5206 },
5207 false /* don't skip top directive */);
5208 CloseNesting = false;
5209 }
5210 if (NestingProhibited) {
5211 if (OrphanSeen) {
5212 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5213 << getOpenMPDirectiveName(CurrentRegion, OMPVersion) << Recommend;
5214 } else {
5215 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5216 << CloseNesting << getOpenMPDirectiveName(OffendingRegion, OMPVersion)
5217 << Recommend << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5218 }
5219 return true;
5220 }
5221 return false;
5222}
5223
5229 ArrayRef<OMPClause *> Clauses,
5230 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5231 bool ErrorFound = false;
5232 unsigned NamedModifiersNumber = 0;
5233 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5234 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5235 SmallVector<SourceLocation, 4> NameModifierLoc;
5236 unsigned OMPVersion = S.getLangOpts().OpenMP;
5237 for (const OMPClause *C : Clauses) {
5238 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5239 // At most one if clause without a directive-name-modifier can appear on
5240 // the directive.
5241 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5242 auto &FNM = FoundNameModifiers[CurNM];
5243 if (FNM) {
5244 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5245 << getOpenMPDirectiveName(Kind, OMPVersion)
5246 << getOpenMPClauseNameForDiag(OMPC_if) << (CurNM != OMPD_unknown)
5247 << getOpenMPDirectiveName(CurNM, OMPVersion);
5248 ErrorFound = true;
5249 } else if (CurNM != OMPD_unknown) {
5250 NameModifierLoc.push_back(IC->getNameModifierLoc());
5251 ++NamedModifiersNumber;
5252 }
5253 FNM = IC;
5254 if (CurNM == OMPD_unknown)
5255 continue;
5256 // Check if the specified name modifier is allowed for the current
5257 // directive.
5258 // At most one if clause with the particular directive-name-modifier can
5259 // appear on the directive.
5260 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5261 S.Diag(IC->getNameModifierLoc(),
5262 diag::err_omp_wrong_if_directive_name_modifier)
5263 << getOpenMPDirectiveName(CurNM, OMPVersion)
5264 << getOpenMPDirectiveName(Kind, OMPVersion);
5265 ErrorFound = true;
5266 }
5267 }
5268 }
5269 // If any if clause on the directive includes a directive-name-modifier then
5270 // all if clauses on the directive must include a directive-name-modifier.
5271 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5272 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5273 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5274 diag::err_omp_no_more_if_clause);
5275 } else {
5276 std::string Values;
5277 std::string Sep(", ");
5278 unsigned AllowedCnt = 0;
5279 unsigned TotalAllowedNum =
5280 AllowedNameModifiers.size() - NamedModifiersNumber;
5281 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5282 ++Cnt) {
5283 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5284 if (!FoundNameModifiers[NM]) {
5285 Values += "'";
5286 Values += getOpenMPDirectiveName(NM, OMPVersion);
5287 Values += "'";
5288 if (AllowedCnt + 2 == TotalAllowedNum)
5289 Values += " or ";
5290 else if (AllowedCnt + 1 != TotalAllowedNum)
5291 Values += Sep;
5292 ++AllowedCnt;
5293 }
5294 }
5295 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5296 diag::err_omp_unnamed_if_clause)
5297 << (TotalAllowedNum > 1) << Values;
5298 }
5299 for (SourceLocation Loc : NameModifierLoc) {
5300 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5301 }
5302 ErrorFound = true;
5303 }
5304 return ErrorFound;
5305}
5306
5307static std::pair<ValueDecl *, bool>
5309 SourceRange &ERange, bool AllowArraySection,
5310 bool AllowAssumedSizeArray, StringRef DiagType) {
5311 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5313 return std::make_pair(nullptr, true);
5314
5315 // OpenMP [3.1, C/C++]
5316 // A list item is a variable name.
5317 // OpenMP [2.9.3.3, Restrictions, p.1]
5318 // A variable that is part of another variable (as an array or
5319 // structure element) cannot appear in a private clause.
5320 //
5321 // OpenMP [6.0]
5322 // 5.2.5 Array Sections, p. 166, L28-29
5323 // When the length is absent and the size of the dimension is not known,
5324 // the array section is an assumed-size array.
5325 // 2 Glossary, p. 23, L4-6
5326 // assumed-size array
5327 // For C/C++, an array section for which the length is absent and the
5328 // size of the dimensions is not known.
5329 // 5.2.5 Array Sections, p. 168, L11
5330 // An assumed-size array can appear only in clauses for which it is
5331 // explicitly allowed.
5332 // 7.4 List Item Privatization, Restrictions, p. 222, L15
5333 // Assumed-size arrays must not be privatized.
5334 RefExpr = RefExpr->IgnoreParens();
5335 enum {
5336 NoArrayExpr = -1,
5337 ArraySubscript = 0,
5338 OMPArraySection = 1
5339 } IsArrayExpr = NoArrayExpr;
5340 if (AllowArraySection) {
5341 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5342 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5343 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5344 Base = TempASE->getBase()->IgnoreParenImpCasts();
5345 RefExpr = Base;
5346 IsArrayExpr = ArraySubscript;
5347 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5348 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5349 if (S.getLangOpts().OpenMP >= 60 && !AllowAssumedSizeArray &&
5350 OASE->getColonLocFirst().isValid() && !OASE->getLength()) {
5352 if (BaseType.isNull() || (!BaseType->isConstantArrayType() &&
5353 !BaseType->isVariableArrayType())) {
5354 S.Diag(OASE->getColonLocFirst(),
5355 diag::err_omp_section_length_undefined)
5356 << (!BaseType.isNull() && BaseType->isArrayType());
5357 return std::make_pair(nullptr, false);
5358 }
5359 }
5360 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Base))
5361 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5362 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5363 Base = TempASE->getBase()->IgnoreParenImpCasts();
5364 RefExpr = Base;
5365 IsArrayExpr = OMPArraySection;
5366 }
5367 }
5368 ELoc = RefExpr->getExprLoc();
5369 ERange = RefExpr->getSourceRange();
5370 RefExpr = RefExpr->IgnoreParenImpCasts();
5371 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5372 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5373 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5374 (S.getCurrentThisType().isNull() || !ME ||
5375 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5376 !isa<FieldDecl>(ME->getMemberDecl()))) {
5377 if (IsArrayExpr != NoArrayExpr) {
5378 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5379 << IsArrayExpr << ERange;
5380 } else if (!DiagType.empty()) {
5381 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5382 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5383 : 0;
5384 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5385 << DiagSelect << DiagType << ERange;
5386 } else {
5387 S.Diag(ELoc,
5388 AllowArraySection
5389 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5390 : diag::err_omp_expected_var_name_member_expr)
5391 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5392 }
5393 return std::make_pair(nullptr, false);
5394 }
5395 return std::make_pair(
5396 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5397}
5398
5399namespace {
5400/// Checks if the allocator is used in uses_allocators clause to be allowed in
5401/// target regions.
5402class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5403 DSAStackTy *S = nullptr;
5404
5405public:
5406 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5407 return S->isUsesAllocatorsDecl(E->getDecl())
5408 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5409 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5410 }
5411 bool VisitStmt(const Stmt *S) {
5412 for (const Stmt *Child : S->children()) {
5413 if (Child && Visit(Child))
5414 return true;
5415 }
5416 return false;
5417 }
5418 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5419};
5420} // namespace
5421
5422static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5423 ArrayRef<OMPClause *> Clauses) {
5424 assert(!S.CurContext->isDependentContext() &&
5425 "Expected non-dependent context.");
5426 auto AllocateRange =
5427 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5428 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5429 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5430 return isOpenMPPrivate(C->getClauseKind());
5431 });
5432 for (OMPClause *Cl : PrivateRange) {
5434 if (Cl->getClauseKind() == OMPC_private) {
5435 auto *PC = cast<OMPPrivateClause>(Cl);
5436 I = PC->private_copies().begin();
5437 It = PC->varlist_begin();
5438 Et = PC->varlist_end();
5439 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5440 auto *PC = cast<OMPFirstprivateClause>(Cl);
5441 I = PC->private_copies().begin();
5442 It = PC->varlist_begin();
5443 Et = PC->varlist_end();
5444 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5445 auto *PC = cast<OMPLastprivateClause>(Cl);
5446 I = PC->private_copies().begin();
5447 It = PC->varlist_begin();
5448 Et = PC->varlist_end();
5449 } else if (Cl->getClauseKind() == OMPC_linear) {
5450 auto *PC = cast<OMPLinearClause>(Cl);
5451 I = PC->privates().begin();
5452 It = PC->varlist_begin();
5453 Et = PC->varlist_end();
5454 } else if (Cl->getClauseKind() == OMPC_reduction) {
5455 auto *PC = cast<OMPReductionClause>(Cl);
5456 I = PC->privates().begin();
5457 It = PC->varlist_begin();
5458 Et = PC->varlist_end();
5459 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5460 auto *PC = cast<OMPTaskReductionClause>(Cl);
5461 I = PC->privates().begin();
5462 It = PC->varlist_begin();
5463 Et = PC->varlist_end();
5464 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5465 auto *PC = cast<OMPInReductionClause>(Cl);
5466 I = PC->privates().begin();
5467 It = PC->varlist_begin();
5468 Et = PC->varlist_end();
5469 } else {
5470 llvm_unreachable("Expected private clause.");
5471 }
5472 for (Expr *E : llvm::make_range(It, Et)) {
5473 if (!*I) {
5474 ++I;
5475 continue;
5476 }
5477 SourceLocation ELoc;
5478 SourceRange ERange;
5479 Expr *SimpleRefExpr = E;
5480 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5481 /*AllowArraySection=*/true);
5482 DeclToCopy.try_emplace(Res.first,
5483 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5484 ++I;
5485 }
5486 }
5487 for (OMPClause *C : AllocateRange) {
5488 auto *AC = cast<OMPAllocateClause>(C);
5489 if (S.getLangOpts().OpenMP >= 50 &&
5490 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5491 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5492 AC->getAllocator()) {
5493 Expr *Allocator = AC->getAllocator();
5494 // OpenMP, 2.12.5 target Construct
5495 // Memory allocators that do not appear in a uses_allocators clause cannot
5496 // appear as an allocator in an allocate clause or be used in the target
5497 // region unless a requires directive with the dynamic_allocators clause
5498 // is present in the same compilation unit.
5499 AllocatorChecker Checker(Stack);
5500 if (Checker.Visit(Allocator))
5501 S.Diag(Allocator->getExprLoc(),
5502 diag::err_omp_allocator_not_in_uses_allocators)
5503 << Allocator->getSourceRange();
5504 }
5505 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5506 getAllocatorKind(S, Stack, AC->getAllocator());
5507 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5508 // For task, taskloop or target directives, allocation requests to memory
5509 // allocators with the trait access set to thread result in unspecified
5510 // behavior.
5511 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5512 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5513 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5514 unsigned OMPVersion = S.getLangOpts().OpenMP;
5515 S.Diag(AC->getAllocator()->getExprLoc(),
5516 diag::warn_omp_allocate_thread_on_task_target_directive)
5517 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
5518 }
5519 for (Expr *E : AC->varlist()) {
5520 SourceLocation ELoc;
5521 SourceRange ERange;
5522 Expr *SimpleRefExpr = E;
5523 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5524 ValueDecl *VD = Res.first;
5525 if (!VD)
5526 continue;
5527 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5528 if (!isOpenMPPrivate(Data.CKind)) {
5529 S.Diag(E->getExprLoc(),
5530 diag::err_omp_expected_private_copy_for_allocate);
5531 continue;
5532 }
5533 VarDecl *PrivateVD = DeclToCopy[VD];
5534 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5535 AllocatorKind, AC->getAllocator()))
5536 continue;
5537 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5538 AC->getAlignment(), E->getSourceRange());
5539 }
5540 }
5541}
5542
5543namespace {
5544/// Rewrite statements and expressions for Sema \p Actions CurContext.
5545///
5546/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5547/// context. DeclRefExpr used inside the new context are changed to refer to the
5548/// captured variable instead.
5549class CaptureVars : public TreeTransform<CaptureVars> {
5550 using BaseTransform = TreeTransform<CaptureVars>;
5551
5552public:
5553 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5554
5555 bool AlwaysRebuild() { return true; }
5556};
5557} // namespace
5558
5559static VarDecl *precomputeExpr(Sema &Actions,
5560 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5561 StringRef Name) {
5562 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5563 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5564 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5565 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5566 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5567 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5568 BodyStmts.push_back(NewDeclStmt);
5569 return NewVar;
5570}
5571
5572/// Create a closure that computes the number of iterations of a loop.
5573///
5574/// \param Actions The Sema object.
5575/// \param LogicalTy Type for the logical iteration number.
5576/// \param Rel Comparison operator of the loop condition.
5577/// \param StartExpr Value of the loop counter at the first iteration.
5578/// \param StopExpr Expression the loop counter is compared against in the loop
5579/// condition. \param StepExpr Amount of increment after each iteration.
5580///
5581/// \return Closure (CapturedStmt) of the distance calculation.
5582static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5584 Expr *StartExpr, Expr *StopExpr,
5585 Expr *StepExpr) {
5586 ASTContext &Ctx = Actions.getASTContext();
5587 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5588
5589 // Captured regions currently don't support return values, we use an
5590 // out-parameter instead. All inputs are implicit captures.
5591 // TODO: Instead of capturing each DeclRefExpr occurring in
5592 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5593 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5594 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5595 {StringRef(), QualType()}};
5596 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5597
5598 Stmt *Body;
5599 {
5600 Sema::CompoundScopeRAII CompoundScope(Actions);
5602
5603 // Get the LValue expression for the result.
5604 ImplicitParamDecl *DistParam = CS->getParam(0);
5605 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5606 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5607
5608 SmallVector<Stmt *, 4> BodyStmts;
5609
5610 // Capture all referenced variable references.
5611 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5612 // CapturedStmt, we could compute them before and capture the result, to be
5613 // used jointly with the LoopVar function.
5614 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5615 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5616 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5617 auto BuildVarRef = [&](VarDecl *VD) {
5618 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5619 };
5620
5622 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5624 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5625 Expr *Dist;
5626 if (Rel == BO_NE) {
5627 // When using a != comparison, the increment can be +1 or -1. This can be
5628 // dynamic at runtime, so we need to check for the direction.
5629 Expr *IsNegStep = AssertSuccess(
5630 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5631
5632 // Positive increment.
5633 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5634 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5635 ForwardRange = AssertSuccess(
5636 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5637 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5638 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5639
5640 // Negative increment.
5641 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5642 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5643 BackwardRange = AssertSuccess(
5644 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5645 Expr *NegIncAmount = AssertSuccess(
5646 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5647 Expr *BackwardDist = AssertSuccess(
5648 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5649
5650 // Use the appropriate case.
5651 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5652 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5653 } else {
5654 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5655 "Expected one of these relational operators");
5656
5657 // We can derive the direction from any other comparison operator. It is
5658 // non well-formed OpenMP if Step increments/decrements in the other
5659 // directions. Whether at least the first iteration passes the loop
5660 // condition.
5661 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5662 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5663
5664 // Compute the range between first and last counter value.
5665 Expr *Range;
5666 if (Rel == BO_GE || Rel == BO_GT)
5667 Range = AssertSuccess(Actions.BuildBinOp(
5668 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5669 else
5670 Range = AssertSuccess(Actions.BuildBinOp(
5671 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5672
5673 // Ensure unsigned range space.
5674 Range =
5675 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5676
5677 if (Rel == BO_LE || Rel == BO_GE) {
5678 // Add one to the range if the relational operator is inclusive.
5679 Range =
5680 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5681 }
5682
5683 // Divide by the absolute step amount. If the range is not a multiple of
5684 // the step size, rounding-up the effective upper bound ensures that the
5685 // last iteration is included.
5686 // Note that the rounding-up may cause an overflow in a temporary that
5687 // could be avoided, but would have occurred in a C-style for-loop as
5688 // well.
5689 Expr *Divisor = BuildVarRef(NewStep);
5690 if (Rel == BO_GE || Rel == BO_GT)
5691 Divisor =
5692 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5693 Expr *DivisorMinusOne =
5694 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5695 Expr *RangeRoundUp = AssertSuccess(
5696 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5697 Dist = AssertSuccess(
5698 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5699
5700 // If there is not at least one iteration, the range contains garbage. Fix
5701 // to zero in this case.
5702 Dist = AssertSuccess(
5703 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5704 }
5705
5706 // Assign the result to the out-parameter.
5707 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5708 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5709 BodyStmts.push_back(ResultAssign);
5710
5711 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5712 }
5713
5714 return cast<CapturedStmt>(
5715 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5716}
5717
5718/// Create a closure that computes the loop variable from the logical iteration
5719/// number.
5720///
5721/// \param Actions The Sema object.
5722/// \param LoopVarTy Type for the loop variable used for result value.
5723/// \param LogicalTy Type for the logical iteration number.
5724/// \param StartExpr Value of the loop counter at the first iteration.
5725/// \param Step Amount of increment after each iteration.
5726/// \param Deref Whether the loop variable is a dereference of the loop
5727/// counter variable.
5728///
5729/// \return Closure (CapturedStmt) of the loop value calculation.
5730static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5731 QualType LogicalTy,
5732 DeclRefExpr *StartExpr, Expr *Step,
5733 bool Deref) {
5734 ASTContext &Ctx = Actions.getASTContext();
5735
5736 // Pass the result as an out-parameter. Passing as return value would require
5737 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5738 // invoke a copy constructor.
5739 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5740 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5741 {"Logical", LogicalTy},
5742 {StringRef(), QualType()}};
5743 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5744
5745 // Capture the initial iterator which represents the LoopVar value at the
5746 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5747 // it in every iteration, capture it by value before it is modified.
5748 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5749 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5751 (void)Invalid;
5752 assert(!Invalid && "Expecting capture-by-value to work.");
5753
5754 Expr *Body;
5755 {
5756 Sema::CompoundScopeRAII CompoundScope(Actions);
5757 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5758
5759 ImplicitParamDecl *TargetParam = CS->getParam(0);
5760 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5761 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5762 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5763 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5764 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5765
5766 // Capture the Start expression.
5767 CaptureVars Recap(Actions);
5768 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5769 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5770
5772 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5773 // TODO: Explicitly cast to the iterator's difference_type instead of
5774 // relying on implicit conversion.
5775 Expr *Advanced =
5776 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5777
5778 if (Deref) {
5779 // For range-based for-loops convert the loop counter value to a concrete
5780 // loop variable value by dereferencing the iterator.
5781 Advanced =
5782 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5783 }
5784
5785 // Assign the result to the output parameter.
5786 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5787 BO_Assign, TargetRef, Advanced));
5788 }
5789 return cast<CapturedStmt>(
5790 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5791}
5792
5794 ASTContext &Ctx = getASTContext();
5795
5796 // Extract the common elements of ForStmt and CXXForRangeStmt:
5797 // Loop variable, repeat condition, increment
5798 Expr *Cond, *Inc;
5799 VarDecl *LIVDecl, *LUVDecl;
5800 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5801 Stmt *Init = For->getInit();
5802 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5803 // For statement declares loop variable.
5804 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5805 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5806 // For statement reuses variable.
5807 assert(LCAssign->getOpcode() == BO_Assign &&
5808 "init part must be a loop variable assignment");
5809 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5810 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5811 } else
5812 llvm_unreachable("Cannot determine loop variable");
5813 LUVDecl = LIVDecl;
5814
5815 Cond = For->getCond();
5816 Inc = For->getInc();
5817 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5818 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5819 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5820 LUVDecl = RangeFor->getLoopVariable();
5821
5822 Cond = RangeFor->getCond();
5823 Inc = RangeFor->getInc();
5824 } else
5825 llvm_unreachable("unhandled kind of loop");
5826
5827 QualType CounterTy = LIVDecl->getType();
5828 QualType LVTy = LUVDecl->getType();
5829
5830 // Analyze the loop condition.
5831 Expr *LHS, *RHS;
5832 BinaryOperator::Opcode CondRel;
5833 Cond = Cond->IgnoreImplicit();
5834 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5835 LHS = CondBinExpr->getLHS();
5836 RHS = CondBinExpr->getRHS();
5837 CondRel = CondBinExpr->getOpcode();
5838 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5839 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5840 LHS = CondCXXOp->getArg(0);
5841 RHS = CondCXXOp->getArg(1);
5842 switch (CondCXXOp->getOperator()) {
5843 case OO_ExclaimEqual:
5844 CondRel = BO_NE;
5845 break;
5846 case OO_Less:
5847 CondRel = BO_LT;
5848 break;
5849 case OO_LessEqual:
5850 CondRel = BO_LE;
5851 break;
5852 case OO_Greater:
5853 CondRel = BO_GT;
5854 break;
5855 case OO_GreaterEqual:
5856 CondRel = BO_GE;
5857 break;
5858 default:
5859 llvm_unreachable("unexpected iterator operator");
5860 }
5861 } else
5862 llvm_unreachable("unexpected loop condition");
5863
5864 // Normalize such that the loop counter is on the LHS.
5865 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5866 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5867 std::swap(LHS, RHS);
5868 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5869 }
5870 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5871
5872 // Decide the bit width for the logical iteration counter. By default use the
5873 // unsigned ptrdiff_t integer size (for iterators and pointers).
5874 // TODO: For iterators, use iterator::difference_type,
5875 // std::iterator_traits<>::difference_type or decltype(it - end).
5876 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5877 if (CounterTy->isIntegerType()) {
5878 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5879 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5880 }
5881
5882 // Analyze the loop increment.
5883 Expr *Step;
5884 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5885 int Direction;
5886 switch (IncUn->getOpcode()) {
5887 case UO_PreInc:
5888 case UO_PostInc:
5889 Direction = 1;
5890 break;
5891 case UO_PreDec:
5892 case UO_PostDec:
5893 Direction = -1;
5894 break;
5895 default:
5896 llvm_unreachable("unhandled unary increment operator");
5897 }
5899 Ctx,
5900 llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction, /*isSigned=*/true),
5901 LogicalTy, {});
5902 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5903 if (IncBin->getOpcode() == BO_AddAssign) {
5904 Step = IncBin->getRHS();
5905 } else if (IncBin->getOpcode() == BO_SubAssign) {
5906 Step = AssertSuccess(
5907 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5908 } else
5909 llvm_unreachable("unhandled binary increment operator");
5910 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5911 switch (CondCXXOp->getOperator()) {
5912 case OO_PlusPlus:
5914 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5915 break;
5916 case OO_MinusMinus:
5918 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5919 break;
5920 case OO_PlusEqual:
5921 Step = CondCXXOp->getArg(1);
5922 break;
5923 case OO_MinusEqual:
5924 Step = AssertSuccess(
5925 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5926 break;
5927 default:
5928 llvm_unreachable("unhandled overloaded increment operator");
5929 }
5930 } else
5931 llvm_unreachable("unknown increment expression");
5932
5933 CapturedStmt *DistanceFunc =
5934 buildDistanceFunc(SemaRef, LogicalTy, CondRel, LHS, RHS, Step);
5935 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5936 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5937 DeclRefExpr *LVRef =
5938 SemaRef.BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue, {},
5939 nullptr, nullptr, {}, nullptr);
5940 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
5941 LoopVarFunc, LVRef);
5942}
5943
5945 // Handle a literal loop.
5946 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5947 return ActOnOpenMPCanonicalLoop(AStmt);
5948
5949 // If not a literal loop, it must be the result of a loop transformation.
5951 assert(
5952 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
5953 "Loop transformation directive expected");
5954 return LoopTransform;
5955}
5956
5958 CXXScopeSpec &MapperIdScopeSpec,
5959 const DeclarationNameInfo &MapperId,
5960 QualType Type,
5961 Expr *UnresolvedMapper);
5962
5963/// Perform DFS through the structure/class data members trying to find
5964/// member(s) with user-defined 'default' mapper and generate implicit map
5965/// clauses for such members with the found 'default' mapper.
5966static void
5969 // Check for the default mapper for data members.
5970 if (S.getLangOpts().OpenMP < 50)
5971 return;
5972 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5973 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5974 if (!C)
5975 continue;
5976 SmallVector<Expr *, 4> SubExprs;
5977 auto *MI = C->mapperlist_begin();
5978 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
5979 ++I, ++MI) {
5980 // Expression is mapped using mapper - skip it.
5981 if (*MI)
5982 continue;
5983 Expr *E = *I;
5984 // Expression is dependent - skip it, build the mapper when it gets
5985 // instantiated.
5986 if (E->isTypeDependent() || E->isValueDependent() ||
5988 continue;
5989 // Array section - need to check for the mapping of the array section
5990 // element.
5991 QualType CanonType = E->getType().getCanonicalType();
5992 if (CanonType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
5993 const auto *OASE = cast<ArraySectionExpr>(E->IgnoreParenImpCasts());
5994 QualType BaseType =
5996 QualType ElemType;
5997 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
5998 ElemType = ATy->getElementType();
5999 else
6000 ElemType = BaseType->getPointeeType();
6001 CanonType = ElemType;
6002 }
6003
6004 // DFS over data members in structures/classes.
6006 1, {CanonType, nullptr});
6007 llvm::DenseMap<const Type *, Expr *> Visited;
6009 1, {nullptr, 1});
6010 while (!Types.empty()) {
6011 QualType BaseType;
6012 FieldDecl *CurFD;
6013 std::tie(BaseType, CurFD) = Types.pop_back_val();
6014 while (ParentChain.back().second == 0)
6015 ParentChain.pop_back();
6016 --ParentChain.back().second;
6017 if (BaseType.isNull())
6018 continue;
6019 // Only structs/classes are allowed to have mappers.
6020 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6021 if (!RD)
6022 continue;
6023 auto It = Visited.find(BaseType.getTypePtr());
6024 if (It == Visited.end()) {
6025 // Try to find the associated user-defined mapper.
6026 CXXScopeSpec MapperIdScopeSpec;
6027 DeclarationNameInfo DefaultMapperId;
6029 &S.Context.Idents.get("default")));
6030 DefaultMapperId.setLoc(E->getExprLoc());
6032 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
6033 BaseType, /*UnresolvedMapper=*/nullptr);
6034 if (ER.isInvalid())
6035 continue;
6036 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
6037 }
6038 // Found default mapper.
6039 if (It->second) {
6040 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
6042 OE->setIsUnique(/*V=*/true);
6043 Expr *BaseExpr = OE;
6044 for (const auto &P : ParentChain) {
6045 if (P.first) {
6046 BaseExpr = S.BuildMemberExpr(
6047 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6049 DeclAccessPair::make(P.first, P.first->getAccess()),
6050 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6051 P.first->getType(), VK_LValue, OK_Ordinary);
6052 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
6053 }
6054 }
6055 if (CurFD)
6056 BaseExpr = S.BuildMemberExpr(
6057 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6059 DeclAccessPair::make(CurFD, CurFD->getAccess()),
6060 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6061 CurFD->getType(), VK_LValue, OK_Ordinary);
6062 SubExprs.push_back(BaseExpr);
6063 continue;
6064 }
6065 // Check for the "default" mapper for data members.
6066 bool FirstIter = true;
6067 for (FieldDecl *FD : RD->fields()) {
6068 if (!FD)
6069 continue;
6070 QualType FieldTy = FD->getType();
6071 if (FieldTy.isNull() ||
6072 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6073 continue;
6074 if (FirstIter) {
6075 FirstIter = false;
6076 ParentChain.emplace_back(CurFD, 1);
6077 } else {
6078 ++ParentChain.back().second;
6079 }
6080 Types.emplace_back(FieldTy, FD);
6081 }
6082 }
6083 }
6084 if (SubExprs.empty())
6085 continue;
6086 CXXScopeSpec MapperIdScopeSpec;
6087 DeclarationNameInfo MapperId;
6088 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
6089 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
6090 MapperIdScopeSpec, MapperId, C->getMapType(),
6091 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6092 SubExprs, OMPVarListLocTy()))
6093 Clauses.push_back(NewClause);
6094 }
6095}
6096
6097namespace {
6098/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
6099/// call in the associated loop-nest cannot be a 'parallel for'.
6100class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
6101 Sema &SemaRef;
6102
6103public:
6104 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
6105
6106 // Is there a nested OpenMP loop bind(parallel)
6107 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
6108 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
6109 if (const auto *C = D->getSingleClause<OMPBindClause>())
6110 if (C->getBindKind() == OMPC_BIND_parallel) {
6111 TeamsLoopCanBeParallelFor = false;
6112 // No need to continue visiting any more
6113 return;
6114 }
6115 }
6116 for (const Stmt *Child : D->children())
6117 if (Child)
6118 Visit(Child);
6119 }
6120
6121 void VisitCallExpr(const CallExpr *C) {
6122 // Function calls inhibit parallel loop translation of 'target teams loop'
6123 // unless the assume-no-nested-parallelism flag has been specified.
6124 // OpenMP API runtime library calls do not inhibit parallel loop
6125 // translation, regardless of the assume-no-nested-parallelism.
6126 bool IsOpenMPAPI = false;
6127 auto *FD = dyn_cast_or_null<FunctionDecl>(C->getCalleeDecl());
6128 if (FD) {
6129 std::string Name = FD->getNameInfo().getAsString();
6130 IsOpenMPAPI = Name.find("omp_") == 0;
6131 }
6132 TeamsLoopCanBeParallelFor =
6133 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
6134 if (!TeamsLoopCanBeParallelFor)
6135 return;
6136
6137 for (const Stmt *Child : C->children())
6138 if (Child)
6139 Visit(Child);
6140 }
6141
6142 void VisitCapturedStmt(const CapturedStmt *S) {
6143 if (!S)
6144 return;
6145 Visit(S->getCapturedDecl()->getBody());
6146 }
6147
6148 void VisitStmt(const Stmt *S) {
6149 if (!S)
6150 return;
6151 for (const Stmt *Child : S->children())
6152 if (Child)
6153 Visit(Child);
6154 }
6155 explicit TeamsLoopChecker(Sema &SemaRef)
6156 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
6157
6158private:
6159 bool TeamsLoopCanBeParallelFor;
6160};
6161} // namespace
6162
6163static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
6164 TeamsLoopChecker Checker(SemaRef);
6165 Checker.Visit(AStmt);
6166 return Checker.teamsLoopCanBeParallelFor();
6167}
6168
6170 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6171 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6172 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
6173 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
6174
6175 StmtResult Res = StmtError();
6177 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6178
6179 if (const OMPBindClause *BC =
6180 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6181 BindKind = BC->getBindKind();
6182
6183 if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
6184 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
6185
6186 // Setting the enclosing teams or parallel construct for the loop
6187 // directive without bind clause.
6188 // [5.0:129:25-28] If the bind clause is not present on the construct and
6189 // the loop construct is closely nested inside a teams or parallel
6190 // construct, the binding region is the corresponding teams or parallel
6191 // region. If none of those conditions hold, the binding region is not
6192 // defined.
6193 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6194 ArrayRef<OpenMPDirectiveKind> ParentLeafs =
6195 getLeafConstructsOrSelf(ParentDirective);
6196
6197 if (ParentDirective == OMPD_unknown) {
6198 Diag(DSAStack->getDefaultDSALocation(),
6199 diag::err_omp_bind_required_on_loop);
6200 } else if (ParentLeafs.back() == OMPD_parallel) {
6201 BindKind = OMPC_BIND_parallel;
6202 } else if (ParentLeafs.back() == OMPD_teams) {
6203 BindKind = OMPC_BIND_teams;
6204 }
6205
6206 assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind");
6207
6208 OMPClause *C =
6211 ClausesWithImplicit.push_back(C);
6212 }
6213
6214 // Diagnose "loop bind(teams)" with "reduction".
6215 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6216 for (OMPClause *C : Clauses) {
6217 if (C->getClauseKind() == OMPC_reduction)
6218 Diag(DSAStack->getDefaultDSALocation(),
6219 diag::err_omp_loop_reduction_clause);
6220 }
6221 }
6222
6223 // First check CancelRegion which is then used in checkNestingOfRegions.
6224 if (checkCancelRegion(SemaRef, Kind, CancelRegion, StartLoc) ||
6225 checkNestingOfRegions(SemaRef, DSAStack, Kind, DirName, CancelRegion,
6226 BindKind, StartLoc)) {
6227 return StmtError();
6228 }
6229
6230 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6233 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6234
6235 VarsWithInheritedDSAType VarsWithInheritedDSA;
6236 bool ErrorFound = false;
6237 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6238
6239 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6241 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6242
6243 // Check default data sharing attributes for referenced variables.
6244 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(AStmt));
6245 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6246 Stmt *S = AStmt;
6247 while (--ThisCaptureLevel >= 0)
6248 S = cast<CapturedStmt>(S)->getCapturedStmt();
6249 DSAChecker.Visit(S);
6251 !isOpenMPTaskingDirective(Kind)) {
6252 // Visit subcaptures to generate implicit clauses for captured vars.
6253 auto *CS = cast<CapturedStmt>(AStmt);
6255 getOpenMPCaptureRegions(CaptureRegions, Kind);
6256 // Ignore outer tasking regions for target directives.
6257 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6259 DSAChecker.visitSubCaptures(CS);
6260 }
6261 if (DSAChecker.isErrorFound())
6262 return StmtError();
6263 // Generate list of implicitly defined firstprivate variables.
6264 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6265 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6266
6268 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6269 // Get the original location of present modifier from Defaultmap clause.
6270 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6271 for (OMPClause *C : Clauses) {
6272 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6273 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6274 PresentModifierLocs[DMC->getDefaultmapKind()] =
6275 DMC->getDefaultmapModifierLoc();
6276 }
6277
6279 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6281 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[K]),
6282 ImpInfo.MapModifiers[K].size(), PresentModifierLocs[K]);
6283 }
6284 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6285 for (OMPClause *C : Clauses) {
6286 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6287 for (Expr *E : IRC->taskgroup_descriptors())
6288 if (E)
6289 ImpInfo.Firstprivates.insert(E);
6290 }
6291 // OpenMP 5.0, 2.10.1 task Construct
6292 // [detach clause]... The event-handle will be considered as if it was
6293 // specified on a firstprivate clause.
6294 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6295 ImpInfo.Firstprivates.insert(DC->getEventHandler());
6296 }
6297 if (!ImpInfo.Firstprivates.empty()) {
6299 ImpInfo.Firstprivates.getArrayRef(), SourceLocation(),
6301 ClausesWithImplicit.push_back(Implicit);
6302 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6303 ImpInfo.Firstprivates.size();
6304 } else {
6305 ErrorFound = true;
6306 }
6307 }
6308 if (!ImpInfo.Privates.empty()) {
6310 ImpInfo.Privates.getArrayRef(), SourceLocation(),
6312 ClausesWithImplicit.push_back(Implicit);
6313 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6314 ImpInfo.Privates.size();
6315 } else {
6316 ErrorFound = true;
6317 }
6318 }
6319 // OpenMP 5.0 [2.19.7]
6320 // If a list item appears in a reduction, lastprivate or linear
6321 // clause on a combined target construct then it is treated as
6322 // if it also appears in a map clause with a map-type of tofrom
6323 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6325 SmallVector<Expr *, 4> ImplicitExprs;
6326 for (OMPClause *C : Clauses) {
6327 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6328 for (Expr *E : RC->varlist())
6330 ImplicitExprs.emplace_back(E);
6331 }
6332 if (!ImplicitExprs.empty()) {
6333 ArrayRef<Expr *> Exprs = ImplicitExprs;
6334 CXXScopeSpec MapperIdScopeSpec;
6335 DeclarationNameInfo MapperId;
6338 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6339 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6340 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6341 ClausesWithImplicit.emplace_back(Implicit);
6342 }
6343 }
6344 for (unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6345 int ClauseKindCnt = -1;
6346 for (unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6347 ArrayRef<Expr *> ImplicitMap = ImpInfo.Mappings[I][J].getArrayRef();
6348 ++ClauseKindCnt;
6349 if (ImplicitMap.empty())
6350 continue;
6351 CXXScopeSpec MapperIdScopeSpec;
6352 DeclarationNameInfo MapperId;
6353 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6355 nullptr, ImpInfo.MapModifiers[I], ImplicitMapModifiersLoc[I],
6356 MapperIdScopeSpec, MapperId, K, /*IsMapTypeImplicit=*/true,
6357 SourceLocation(), SourceLocation(), ImplicitMap,
6358 OMPVarListLocTy())) {
6359 ClausesWithImplicit.emplace_back(Implicit);
6360 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6361 ImplicitMap.size();
6362 } else {
6363 ErrorFound = true;
6364 }
6365 }
6366 }
6367 // Build expressions for implicit maps of data members with 'default'
6368 // mappers.
6369 if (getLangOpts().OpenMP >= 50)
6371 ClausesWithImplicit);
6372 }
6373
6374 switch (Kind) {
6375 case OMPD_parallel:
6376 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6377 EndLoc);
6378 break;
6379 case OMPD_simd:
6380 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6381 VarsWithInheritedDSA);
6382 break;
6383 case OMPD_tile:
6384 Res =
6385 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6386 break;
6387 case OMPD_stripe:
6388 Res = ActOnOpenMPStripeDirective(ClausesWithImplicit, AStmt, StartLoc,
6389 EndLoc);
6390 break;
6391 case OMPD_unroll:
6392 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6393 EndLoc);
6394 break;
6395 case OMPD_reverse:
6396 assert(ClausesWithImplicit.empty() &&
6397 "reverse directive does not support any clauses");
6398 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6399 break;
6400 case OMPD_interchange:
6401 Res = ActOnOpenMPInterchangeDirective(ClausesWithImplicit, AStmt, StartLoc,
6402 EndLoc);
6403 break;
6404 case OMPD_fuse:
6405 Res =
6406 ActOnOpenMPFuseDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6407 break;
6408 case OMPD_for:
6409 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6410 VarsWithInheritedDSA);
6411 break;
6412 case OMPD_for_simd:
6413 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6414 EndLoc, VarsWithInheritedDSA);
6415 break;
6416 case OMPD_sections:
6417 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6418 EndLoc);
6419 break;
6420 case OMPD_section:
6421 assert(ClausesWithImplicit.empty() &&
6422 "No clauses are allowed for 'omp section' directive");
6423 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6424 break;
6425 case OMPD_single:
6426 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6427 EndLoc);
6428 break;
6429 case OMPD_master:
6430 assert(ClausesWithImplicit.empty() &&
6431 "No clauses are allowed for 'omp master' directive");
6432 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6433 break;
6434 case OMPD_masked:
6435 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6436 EndLoc);
6437 break;
6438 case OMPD_critical:
6439 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6440 StartLoc, EndLoc);
6441 break;
6442 case OMPD_parallel_for:
6443 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6444 EndLoc, VarsWithInheritedDSA);
6445 break;
6446 case OMPD_parallel_for_simd:
6448 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6449 break;
6450 case OMPD_scope:
6451 Res =
6452 ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6453 break;
6454 case OMPD_parallel_master:
6455 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6456 StartLoc, EndLoc);
6457 break;
6458 case OMPD_parallel_masked:
6459 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6460 StartLoc, EndLoc);
6461 break;
6462 case OMPD_parallel_sections:
6463 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6464 StartLoc, EndLoc);
6465 break;
6466 case OMPD_task:
6467 Res =
6468 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6469 break;
6470 case OMPD_taskyield:
6471 assert(ClausesWithImplicit.empty() &&
6472 "No clauses are allowed for 'omp taskyield' directive");
6473 assert(AStmt == nullptr &&
6474 "No associated statement allowed for 'omp taskyield' directive");
6475 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6476 break;
6477 case OMPD_error:
6478 assert(AStmt == nullptr &&
6479 "No associated statement allowed for 'omp error' directive");
6480 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6481 break;
6482 case OMPD_barrier:
6483 assert(ClausesWithImplicit.empty() &&
6484 "No clauses are allowed for 'omp barrier' directive");
6485 assert(AStmt == nullptr &&
6486 "No associated statement allowed for 'omp barrier' directive");
6487 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6488 break;
6489 case OMPD_taskwait:
6490 assert(AStmt == nullptr &&
6491 "No associated statement allowed for 'omp taskwait' directive");
6492 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6493 break;
6494 case OMPD_taskgroup:
6495 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6496 EndLoc);
6497 break;
6498 case OMPD_flush:
6499 assert(AStmt == nullptr &&
6500 "No associated statement allowed for 'omp flush' directive");
6501 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6502 break;
6503 case OMPD_depobj:
6504 assert(AStmt == nullptr &&
6505 "No associated statement allowed for 'omp depobj' directive");
6506 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6507 break;
6508 case OMPD_scan:
6509 assert(AStmt == nullptr &&
6510 "No associated statement allowed for 'omp scan' directive");
6511 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6512 break;
6513 case OMPD_ordered:
6514 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6515 EndLoc);
6516 break;
6517 case OMPD_atomic:
6518 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6519 EndLoc);
6520 break;
6521 case OMPD_teams:
6522 Res =
6523 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6524 break;
6525 case OMPD_target:
6526 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6527 EndLoc);
6528 break;
6529 case OMPD_target_parallel:
6530 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6531 StartLoc, EndLoc);
6532 break;
6533 case OMPD_target_parallel_for:
6535 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6536 break;
6537 case OMPD_cancellation_point:
6538 assert(ClausesWithImplicit.empty() &&
6539 "No clauses are allowed for 'omp cancellation point' directive");
6540 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6541 "cancellation point' directive");
6542 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6543 break;
6544 case OMPD_cancel:
6545 assert(AStmt == nullptr &&
6546 "No associated statement allowed for 'omp cancel' directive");
6547 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6548 CancelRegion);
6549 break;
6550 case OMPD_target_data:
6551 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6552 EndLoc);
6553 break;
6554 case OMPD_target_enter_data:
6555 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6556 EndLoc, AStmt);
6557 break;
6558 case OMPD_target_exit_data:
6559 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6560 EndLoc, AStmt);
6561 break;
6562 case OMPD_taskloop:
6563 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6564 EndLoc, VarsWithInheritedDSA);
6565 break;
6566 case OMPD_taskloop_simd:
6567 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6568 EndLoc, VarsWithInheritedDSA);
6569 break;
6570 case OMPD_master_taskloop:
6572 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6573 break;
6574 case OMPD_masked_taskloop:
6576 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6577 break;
6578 case OMPD_master_taskloop_simd:
6580 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6581 break;
6582 case OMPD_masked_taskloop_simd:
6584 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6585 break;
6586 case OMPD_parallel_master_taskloop:
6588 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6589 break;
6590 case OMPD_parallel_masked_taskloop:
6592 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6593 break;
6594 case OMPD_parallel_master_taskloop_simd:
6596 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6597 break;
6598 case OMPD_parallel_masked_taskloop_simd:
6600 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6601 break;
6602 case OMPD_distribute:
6603 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6604 EndLoc, VarsWithInheritedDSA);
6605 break;
6606 case OMPD_target_update:
6607 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6608 EndLoc, AStmt);
6609 break;
6610 case OMPD_distribute_parallel_for:
6612 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6613 break;
6614 case OMPD_distribute_parallel_for_simd:
6616 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6617 break;
6618 case OMPD_distribute_simd:
6620 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6621 break;
6622 case OMPD_target_parallel_for_simd:
6624 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6625 break;
6626 case OMPD_target_simd:
6627 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6628 EndLoc, VarsWithInheritedDSA);
6629 break;
6630 case OMPD_teams_distribute:
6632 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6633 break;
6634 case OMPD_teams_distribute_simd:
6636 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6637 break;
6638 case OMPD_teams_distribute_parallel_for_simd:
6640 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6641 break;
6642 case OMPD_teams_distribute_parallel_for:
6644 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6645 break;
6646 case OMPD_target_teams:
6647 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6648 EndLoc);
6649 break;
6650 case OMPD_target_teams_distribute:
6652 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6653 break;
6654 case OMPD_target_teams_distribute_parallel_for:
6656 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6657 break;
6658 case OMPD_target_teams_distribute_parallel_for_simd:
6660 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6661 break;
6662 case OMPD_target_teams_distribute_simd:
6664 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6665 break;
6666 case OMPD_interop:
6667 assert(AStmt == nullptr &&
6668 "No associated statement allowed for 'omp interop' directive");
6669 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6670 break;
6671 case OMPD_dispatch:
6672 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6673 EndLoc);
6674 break;
6675 case OMPD_loop:
6676 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6677 EndLoc, VarsWithInheritedDSA);
6678 break;
6679 case OMPD_teams_loop:
6681 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6682 break;
6683 case OMPD_target_teams_loop:
6685 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6686 break;
6687 case OMPD_parallel_loop:
6689 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6690 break;
6691 case OMPD_target_parallel_loop:
6693 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6694 break;
6695 case OMPD_declare_target:
6696 case OMPD_end_declare_target:
6697 case OMPD_threadprivate:
6698 case OMPD_allocate:
6699 case OMPD_declare_reduction:
6700 case OMPD_declare_mapper:
6701 case OMPD_declare_simd:
6702 case OMPD_requires:
6703 case OMPD_declare_variant:
6704 case OMPD_begin_declare_variant:
6705 case OMPD_end_declare_variant:
6706 llvm_unreachable("OpenMP Directive is not allowed");
6707 case OMPD_unknown:
6708 default:
6709 llvm_unreachable("Unknown OpenMP directive");
6710 }
6711
6712 ErrorFound = Res.isInvalid() || ErrorFound;
6713
6714 // Check variables in the clauses if default(none) or
6715 // default(firstprivate) was specified.
6716 if (DSAStack->getDefaultDSA() == DSA_none ||
6717 DSAStack->getDefaultDSA() == DSA_private ||
6718 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6719 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6720 for (OMPClause *C : Clauses) {
6721 switch (C->getClauseKind()) {
6722 case OMPC_num_threads:
6723 case OMPC_dist_schedule:
6724 // Do not analyze if no parent teams directive.
6725 if (isOpenMPTeamsDirective(Kind))
6726 break;
6727 continue;
6728 case OMPC_if:
6729 if (isOpenMPTeamsDirective(Kind) &&
6730 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6731 break;
6732 if (isOpenMPParallelDirective(Kind) &&
6734 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6735 break;
6736 continue;
6737 case OMPC_schedule:
6738 case OMPC_detach:
6739 break;
6740 case OMPC_grainsize:
6741 case OMPC_num_tasks:
6742 case OMPC_final:
6743 case OMPC_priority:
6744 case OMPC_novariants:
6745 case OMPC_nocontext:
6746 // Do not analyze if no parent parallel directive.
6747 if (isOpenMPParallelDirective(Kind))
6748 break;
6749 continue;
6750 case OMPC_ordered:
6751 case OMPC_device:
6752 case OMPC_num_teams:
6753 case OMPC_thread_limit:
6754 case OMPC_hint:
6755 case OMPC_collapse:
6756 case OMPC_safelen:
6757 case OMPC_simdlen:
6758 case OMPC_sizes:
6759 case OMPC_default:
6760 case OMPC_proc_bind:
6761 case OMPC_private:
6762 case OMPC_firstprivate:
6763 case OMPC_lastprivate:
6764 case OMPC_shared:
6765 case OMPC_reduction:
6766 case OMPC_task_reduction:
6767 case OMPC_in_reduction:
6768 case OMPC_linear:
6769 case OMPC_aligned:
6770 case OMPC_copyin:
6771 case OMPC_copyprivate:
6772 case OMPC_nowait:
6773 case OMPC_untied:
6774 case OMPC_mergeable:
6775 case OMPC_allocate:
6776 case OMPC_read:
6777 case OMPC_write:
6778 case OMPC_update:
6779 case OMPC_capture:
6780 case OMPC_compare:
6781 case OMPC_seq_cst:
6782 case OMPC_acq_rel:
6783 case OMPC_acquire:
6784 case OMPC_release:
6785 case OMPC_relaxed:
6786 case OMPC_depend:
6787 case OMPC_threads:
6788 case OMPC_simd:
6789 case OMPC_map:
6790 case OMPC_nogroup:
6791 case OMPC_defaultmap:
6792 case OMPC_to:
6793 case OMPC_from:
6794 case OMPC_use_device_ptr:
6795 case OMPC_use_device_addr:
6796 case OMPC_is_device_ptr:
6797 case OMPC_has_device_addr:
6798 case OMPC_nontemporal:
6799 case OMPC_order:
6800 case OMPC_destroy:
6801 case OMPC_inclusive:
6802 case OMPC_exclusive:
6803 case OMPC_uses_allocators:
6804 case OMPC_affinity:
6805 case OMPC_bind:
6806 case OMPC_filter:
6807 case OMPC_severity:
6808 case OMPC_message:
6809 continue;
6810 case OMPC_allocator:
6811 case OMPC_flush:
6812 case OMPC_depobj:
6813 case OMPC_threadprivate:
6814 case OMPC_groupprivate:
6815 case OMPC_uniform:
6816 case OMPC_unknown:
6817 case OMPC_unified_address:
6818 case OMPC_unified_shared_memory:
6819 case OMPC_reverse_offload:
6820 case OMPC_dynamic_allocators:
6821 case OMPC_atomic_default_mem_order:
6822 case OMPC_self_maps:
6823 case OMPC_device_type:
6824 case OMPC_match:
6825 case OMPC_when:
6826 case OMPC_at:
6827 default:
6828 llvm_unreachable("Unexpected clause");
6829 }
6830 for (Stmt *CC : C->children()) {
6831 if (CC)
6832 DSAChecker.Visit(CC);
6833 }
6834 }
6835 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6836 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6837 }
6838 for (const auto &P : VarsWithInheritedDSA) {
6839 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6840 continue;
6841 ErrorFound = true;
6842 if (DSAStack->getDefaultDSA() == DSA_none ||
6843 DSAStack->getDefaultDSA() == DSA_private ||
6844 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6845 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6846 << P.first << P.second->getSourceRange();
6847 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6848 } else if (getLangOpts().OpenMP >= 50) {
6849 Diag(P.second->getExprLoc(),
6850 diag::err_omp_defaultmap_no_attr_for_variable)
6851 << P.first << P.second->getSourceRange();
6852 Diag(DSAStack->getDefaultDSALocation(),
6853 diag::note_omp_defaultmap_attr_none);
6854 }
6855 }
6856
6857 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6858 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(Kind)) {
6859 if (isAllowedClauseForDirective(D, OMPC_if, getLangOpts().OpenMP))
6860 AllowedNameModifiers.push_back(D);
6861 }
6862 if (!AllowedNameModifiers.empty())
6863 ErrorFound = checkIfClauses(SemaRef, Kind, Clauses, AllowedNameModifiers) ||
6864 ErrorFound;
6865
6866 if (ErrorFound)
6867 return StmtError();
6868
6869 if (!SemaRef.CurContext->isDependentContext() &&
6871 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6872 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6873 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6874 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6875 // Register target to DSA Stack.
6876 DSAStack->addTargetDirLocation(StartLoc);
6877 }
6878
6879 return Res;
6880}
6881
6883 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6884 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6885 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6886 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6887 assert(Aligneds.size() == Alignments.size());
6888 assert(Linears.size() == LinModifiers.size());
6889 assert(Linears.size() == Steps.size());
6890 if (!DG || DG.get().isNull())
6891 return DeclGroupPtrTy();
6892
6893 const int SimdId = 0;
6894 if (!DG.get().isSingleDecl()) {
6895 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6896 << SimdId;
6897 return DG;
6898 }
6899 Decl *ADecl = DG.get().getSingleDecl();
6900 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6901 ADecl = FTD->getTemplatedDecl();
6902
6903 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6904 if (!FD) {
6905 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6906 return DeclGroupPtrTy();
6907 }
6908
6909 // OpenMP [2.8.2, declare simd construct, Description]
6910 // The parameter of the simdlen clause must be a constant positive integer
6911 // expression.
6912 ExprResult SL;
6913 if (Simdlen)
6914 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6915 // OpenMP [2.8.2, declare simd construct, Description]
6916 // The special this pointer can be used as if was one of the arguments to the
6917 // function in any of the linear, aligned, or uniform clauses.
6918 // The uniform clause declares one or more arguments to have an invariant
6919 // value for all concurrent invocations of the function in the execution of a
6920 // single SIMD loop.
6921 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6922 const Expr *UniformedLinearThis = nullptr;
6923 for (const Expr *E : Uniforms) {
6924 E = E->IgnoreParenImpCasts();
6925 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6926 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6927 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6928 FD->getParamDecl(PVD->getFunctionScopeIndex())
6929 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
6930 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6931 continue;
6932 }
6933 if (isa<CXXThisExpr>(E)) {
6934 UniformedLinearThis = E;
6935 continue;
6936 }
6937 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6938 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6939 }
6940 // OpenMP [2.8.2, declare simd construct, Description]
6941 // The aligned clause declares that the object to which each list item points
6942 // is aligned to the number of bytes expressed in the optional parameter of
6943 // the aligned clause.
6944 // The special this pointer can be used as if was one of the arguments to the
6945 // function in any of the linear, aligned, or uniform clauses.
6946 // The type of list items appearing in the aligned clause must be array,
6947 // pointer, reference to array, or reference to pointer.
6948 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6949 const Expr *AlignedThis = nullptr;
6950 for (const Expr *E : Aligneds) {
6951 E = E->IgnoreParenImpCasts();
6952 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6953 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6954 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6955 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6956 FD->getParamDecl(PVD->getFunctionScopeIndex())
6957 ->getCanonicalDecl() == CanonPVD) {
6958 // OpenMP [2.8.1, simd construct, Restrictions]
6959 // A list-item cannot appear in more than one aligned clause.
6960 auto [It, Inserted] = AlignedArgs.try_emplace(CanonPVD, E);
6961 if (!Inserted) {
6962 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6963 << 1 << getOpenMPClauseNameForDiag(OMPC_aligned)
6964 << E->getSourceRange();
6965 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
6966 << getOpenMPClauseNameForDiag(OMPC_aligned);
6967 continue;
6968 }
6969 QualType QTy = PVD->getType()
6970 .getNonReferenceType()
6971 .getUnqualifiedType()
6972 .getCanonicalType();
6973 const Type *Ty = QTy.getTypePtrOrNull();
6974 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
6975 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
6976 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
6977 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6978 }
6979 continue;
6980 }
6981 }
6982 if (isa<CXXThisExpr>(E)) {
6983 if (AlignedThis) {
6984 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6985 << 2 << getOpenMPClauseNameForDiag(OMPC_aligned)
6986 << E->getSourceRange();
6987 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
6988 << getOpenMPClauseNameForDiag(OMPC_aligned);
6989 }
6990 AlignedThis = E;
6991 continue;
6992 }
6993 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6994 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6995 }
6996 // The optional parameter of the aligned clause, alignment, must be a constant
6997 // positive integer expression. If no optional parameter is specified,
6998 // implementation-defined default alignments for SIMD instructions on the
6999 // target platforms are assumed.
7001 for (Expr *E : Alignments) {
7002 ExprResult Align;
7003 if (E)
7004 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
7005 NewAligns.push_back(Align.get());
7006 }
7007 // OpenMP [2.8.2, declare simd construct, Description]
7008 // The linear clause declares one or more list items to be private to a SIMD
7009 // lane and to have a linear relationship with respect to the iteration space
7010 // of a loop.
7011 // The special this pointer can be used as if was one of the arguments to the
7012 // function in any of the linear, aligned, or uniform clauses.
7013 // When a linear-step expression is specified in a linear clause it must be
7014 // either a constant integer expression or an integer-typed parameter that is
7015 // specified in a uniform clause on the directive.
7016 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7017 const bool IsUniformedThis = UniformedLinearThis != nullptr;
7018 auto MI = LinModifiers.begin();
7019 for (const Expr *E : Linears) {
7020 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
7021 ++MI;
7022 E = E->IgnoreParenImpCasts();
7023 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7024 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7025 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7026 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7027 FD->getParamDecl(PVD->getFunctionScopeIndex())
7028 ->getCanonicalDecl() == CanonPVD) {
7029 // OpenMP [2.15.3.7, linear Clause, Restrictions]
7030 // A list-item cannot appear in more than one linear clause.
7031 if (auto It = LinearArgs.find(CanonPVD); It != LinearArgs.end()) {
7032 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7033 << getOpenMPClauseNameForDiag(OMPC_linear)
7034 << getOpenMPClauseNameForDiag(OMPC_linear)
7035 << E->getSourceRange();
7036 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7037 << getOpenMPClauseNameForDiag(OMPC_linear);
7038 continue;
7039 }
7040 // Each argument can appear in at most one uniform or linear clause.
7041 if (auto It = UniformedArgs.find(CanonPVD);
7042 It != UniformedArgs.end()) {
7043 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7044 << getOpenMPClauseNameForDiag(OMPC_linear)
7045 << getOpenMPClauseNameForDiag(OMPC_uniform)
7046 << E->getSourceRange();
7047 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7048 << getOpenMPClauseNameForDiag(OMPC_uniform);
7049 continue;
7050 }
7051 LinearArgs[CanonPVD] = E;
7052 if (E->isValueDependent() || E->isTypeDependent() ||
7055 continue;
7056 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
7057 PVD->getOriginalType(),
7058 /*IsDeclareSimd=*/true);
7059 continue;
7060 }
7061 }
7062 if (isa<CXXThisExpr>(E)) {
7063 if (UniformedLinearThis) {
7064 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7065 << getOpenMPClauseNameForDiag(OMPC_linear)
7066 << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
7067 : OMPC_linear)
7068 << E->getSourceRange();
7069 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
7070 << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
7071 : OMPC_linear);
7072 continue;
7073 }
7074 UniformedLinearThis = E;
7075 if (E->isValueDependent() || E->isTypeDependent() ||
7077 continue;
7078 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
7079 E->getType(), /*IsDeclareSimd=*/true);
7080 continue;
7081 }
7082 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7083 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7084 }
7085 Expr *Step = nullptr;
7086 Expr *NewStep = nullptr;
7087 SmallVector<Expr *, 4> NewSteps;
7088 for (Expr *E : Steps) {
7089 // Skip the same step expression, it was checked already.
7090 if (Step == E || !E) {
7091 NewSteps.push_back(E ? NewStep : nullptr);
7092 continue;
7093 }
7094 Step = E;
7095 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
7096 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7097 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7098 if (UniformedArgs.count(CanonPVD) == 0) {
7099 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
7100 << Step->getSourceRange();
7101 } else if (E->isValueDependent() || E->isTypeDependent() ||
7104 CanonPVD->getType()->hasIntegerRepresentation()) {
7105 NewSteps.push_back(Step);
7106 } else {
7107 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
7108 << Step->getSourceRange();
7109 }
7110 continue;
7111 }
7112 NewStep = Step;
7113 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
7114 !Step->isInstantiationDependent() &&
7116 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
7117 .get();
7118 if (NewStep)
7119 NewStep = SemaRef
7120 .VerifyIntegerConstantExpression(
7121 NewStep, /*FIXME*/ AllowFoldKind::Allow)
7122 .get();
7123 }
7124 NewSteps.push_back(NewStep);
7125 }
7126 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7127 getASTContext(), BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
7128 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
7129 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
7130 const_cast<Expr **>(Linears.data()), Linears.size(),
7131 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
7132 NewSteps.data(), NewSteps.size(), SR);
7133 ADecl->addAttr(NewAttr);
7134 return DG;
7135}
7136
7138 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
7139 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
7140 SourceLocation EndLoc) {
7141 assert(isOpenMPInformationalDirective(Kind) &&
7142 "Unexpected directive category");
7143
7144 StmtResult Res = StmtError();
7145
7146 switch (Kind) {
7147 case OMPD_assume:
7148 Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc);
7149 break;
7150 default:
7151 llvm_unreachable("Unknown OpenMP directive");
7152 }
7153
7154 return Res;
7155}
7156
7157static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7158 QualType NewType) {
7159 assert(NewType->isFunctionProtoType() &&
7160 "Expected function type with prototype.");
7161 assert(FD->getType()->isFunctionNoProtoType() &&
7162 "Expected function with type with no prototype.");
7163 assert(FDWithProto->getType()->isFunctionProtoType() &&
7164 "Expected function with prototype.");
7165 // Synthesize parameters with the same types.
7166 FD->setType(NewType);
7168 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7169 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
7170 SourceLocation(), nullptr, P->getType(),
7171 /*TInfo=*/nullptr, SC_None, nullptr);
7172 Param->setScopeInfo(0, Params.size());
7173 Param->setImplicit();
7174 Params.push_back(Param);
7175 }
7176
7177 FD->setParams(Params);
7178}
7179
7181 if (D->isInvalidDecl())
7182 return;
7183 FunctionDecl *FD = nullptr;
7184 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7185 FD = UTemplDecl->getTemplatedDecl();
7186 else
7187 FD = cast<FunctionDecl>(D);
7188 assert(FD && "Expected a function declaration!");
7189
7190 // If we are instantiating templates we do *not* apply scoped assumptions but
7191 // only global ones. We apply scoped assumption to the template definition
7192 // though.
7193 if (!SemaRef.inTemplateInstantiation()) {
7194 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7195 FD->addAttr(AA);
7196 }
7197 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7198 FD->addAttr(AA);
7199}
7200
7201SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7202 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7203
7205 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7207 if (!D.getIdentifier())
7208 return;
7209
7210 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7211
7212 // Template specialization is an extension, check if we do it.
7213 bool IsTemplated = !TemplateParamLists.empty();
7214 if (IsTemplated &&
7215 !DVScope.TI->isExtensionActive(
7216 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7217 return;
7218
7219 const IdentifierInfo *BaseII = D.getIdentifier();
7222 SemaRef.LookupParsedName(Lookup, S, &D.getCXXScopeSpec(),
7223 /*ObjectType=*/QualType());
7224
7225 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
7226 QualType FType = TInfo->getType();
7227
7228 bool IsConstexpr =
7230 bool IsConsteval =
7232
7233 for (auto *Candidate : Lookup) {
7234 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7235 FunctionDecl *UDecl = nullptr;
7236 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7237 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7238 // FIXME: Should this compare the template parameter lists on all levels?
7239 if (SemaRef.Context.isSameTemplateParameterList(
7240 FTD->getTemplateParameters(), TemplateParamLists.back()))
7241 UDecl = FTD->getTemplatedDecl();
7242 } else if (!IsTemplated)
7243 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7244 if (!UDecl)
7245 continue;
7246
7247 // Don't specialize constexpr/consteval functions with
7248 // non-constexpr/consteval functions.
7249 if (UDecl->isConstexpr() && !IsConstexpr)
7250 continue;
7251 if (UDecl->isConsteval() && !IsConsteval)
7252 continue;
7253
7254 QualType UDeclTy = UDecl->getType();
7255 if (!UDeclTy->isDependentType()) {
7257 FType, UDeclTy, /*OfBlockPointer=*/false,
7258 /*Unqualified=*/false, /*AllowCXX=*/true);
7259 if (NewType.isNull())
7260 continue;
7261 }
7262
7263 // Found a base!
7264 Bases.push_back(UDecl);
7265 }
7266
7267 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7268 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7269 // If no base was found we create a declaration that we use as base.
7270 if (Bases.empty() && UseImplicitBase) {
7272 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7273 BaseD->setImplicit(true);
7274 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7275 Bases.push_back(BaseTemplD->getTemplatedDecl());
7276 else
7277 Bases.push_back(cast<FunctionDecl>(BaseD));
7278 }
7279
7280 std::string MangledName;
7281 MangledName += D.getIdentifier()->getName();
7282 MangledName += getOpenMPVariantManglingSeparatorStr();
7283 MangledName += DVScope.NameSuffix;
7284 IdentifierInfo &VariantII = getASTContext().Idents.get(MangledName);
7285
7286 VariantII.setMangledOpenMPVariantName(true);
7287 D.SetIdentifier(&VariantII, D.getBeginLoc());
7288}
7289
7292 // Do not mark function as is used to prevent its emission if this is the
7293 // only place where it is used.
7296
7297 FunctionDecl *FD = nullptr;
7298 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7299 FD = UTemplDecl->getTemplatedDecl();
7300 else
7301 FD = cast<FunctionDecl>(D);
7302 auto *VariantFuncRef = DeclRefExpr::Create(
7304 /*RefersToEnclosingVariableOrCapture=*/false,
7305 /*NameLoc=*/FD->getLocation(), FD->getType(), ExprValueKind::VK_PRValue);
7306
7307 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7308 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7309 getASTContext(), VariantFuncRef, DVScope.TI,
7310 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7311 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7312 /*NeedDeviceAddrArgs=*/nullptr, /*NeedDeviceAddrArgsSize=*/0,
7313 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7314 for (FunctionDecl *BaseFD : Bases)
7315 BaseFD->addAttr(OMPDeclareVariantA);
7316}
7317
7319 SourceLocation LParenLoc,
7320 MultiExprArg ArgExprs,
7321 SourceLocation RParenLoc,
7322 Expr *ExecConfig) {
7323 // The common case is a regular call we do not want to specialize at all. Try
7324 // to make that case fast by bailing early.
7325 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7326 if (!CE)
7327 return Call;
7328
7329 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7330 if (!CalleeFnDecl)
7331 return Call;
7332
7333 if (getLangOpts().OpenMP >= 50 && getLangOpts().OpenMP <= 60 &&
7334 CalleeFnDecl->getIdentifier() &&
7335 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7336 // checking for any calls inside an Order region
7338 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7339 }
7340
7341 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7342 return Call;
7343
7344 ASTContext &Context = getASTContext();
7345 std::function<void(StringRef)> DiagUnknownTrait = [this,
7346 CE](StringRef ISATrait) {
7347 // TODO Track the selector locations in a way that is accessible here to
7348 // improve the diagnostic location.
7349 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7350 << ISATrait;
7351 };
7352 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7353 SemaRef.getCurFunctionDecl(),
7354 DSAStack->getConstructTraits(), getOpenMPDeviceNum());
7355
7356 QualType CalleeFnType = CalleeFnDecl->getType();
7357
7360 while (CalleeFnDecl) {
7361 for (OMPDeclareVariantAttr *A :
7362 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7363 Expr *VariantRef = A->getVariantFuncRef();
7364
7365 VariantMatchInfo VMI;
7366 OMPTraitInfo &TI = A->getTraitInfo();
7367 TI.getAsVariantMatchInfo(Context, VMI);
7368 if (!isVariantApplicableInContext(VMI, OMPCtx,
7369 /*DeviceSetOnly=*/false))
7370 continue;
7371
7372 VMIs.push_back(VMI);
7373 Exprs.push_back(VariantRef);
7374 }
7375
7376 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7377 }
7378
7379 ExprResult NewCall;
7380 do {
7381 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7382 if (BestIdx < 0)
7383 return Call;
7384 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7385 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7386
7387 {
7388 // Try to build a (member) call expression for the current best applicable
7389 // variant expression. We allow this to fail in which case we continue
7390 // with the next best variant expression. The fail case is part of the
7391 // implementation defined behavior in the OpenMP standard when it talks
7392 // about what differences in the function prototypes: "Any differences
7393 // that the specific OpenMP context requires in the prototype of the
7394 // variant from the base function prototype are implementation defined."
7395 // This wording is there to allow the specialized variant to have a
7396 // different type than the base function. This is intended and OK but if
7397 // we cannot create a call the difference is not in the "implementation
7398 // defined range" we allow.
7400
7401 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7402 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7403 BestExpr = MemberExpr::CreateImplicit(
7404 Context, MemberCall->getImplicitObjectArgument(),
7405 /*IsArrow=*/false, SpecializedMethod, Context.BoundMemberTy,
7406 MemberCall->getValueKind(), MemberCall->getObjectKind());
7407 }
7408 NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs,
7409 RParenLoc, ExecConfig);
7410 if (NewCall.isUsable()) {
7411 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7412 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7414 CalleeFnType, NewCalleeFnDecl->getType(),
7415 /*OfBlockPointer=*/false,
7416 /*Unqualified=*/false, /*AllowCXX=*/true);
7417 if (!NewType.isNull())
7418 break;
7419 // Don't use the call if the function type was not compatible.
7420 NewCall = nullptr;
7421 }
7422 }
7423 }
7424
7425 VMIs.erase(VMIs.begin() + BestIdx);
7426 Exprs.erase(Exprs.begin() + BestIdx);
7427 } while (!VMIs.empty());
7428
7429 if (!NewCall.isUsable())
7430 return Call;
7431 return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
7432}
7433
7434std::optional<std::pair<FunctionDecl *, Expr *>>
7436 Expr *VariantRef,
7437 OMPTraitInfo &TI,
7438 unsigned NumAppendArgs,
7439 SourceRange SR) {
7440 ASTContext &Context = getASTContext();
7441 if (!DG || DG.get().isNull())
7442 return std::nullopt;
7443
7444 const int VariantId = 1;
7445 // Must be applied only to single decl.
7446 if (!DG.get().isSingleDecl()) {
7447 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7448 << VariantId << SR;
7449 return std::nullopt;
7450 }
7451 Decl *ADecl = DG.get().getSingleDecl();
7452 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7453 ADecl = FTD->getTemplatedDecl();
7454
7455 // Decl must be a function.
7456 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7457 if (!FD) {
7458 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7459 << VariantId << SR;
7460 return std::nullopt;
7461 }
7462
7463 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7464 // The 'target' attribute needs to be separately checked because it does
7465 // not always signify a multiversion function declaration.
7466 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7467 };
7468 // OpenMP is not compatible with multiversion function attributes.
7469 if (HasMultiVersionAttributes(FD)) {
7470 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7471 << SR;
7472 return std::nullopt;
7473 }
7474
7475 // Allow #pragma omp declare variant only if the function is not used.
7476 if (FD->isUsed(false))
7477 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7478 << FD->getLocation();
7479
7480 // Check if the function was emitted already.
7481 const FunctionDecl *Definition;
7482 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7483 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7484 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7485 << FD->getLocation();
7486
7487 // The VariantRef must point to function.
7488 if (!VariantRef) {
7489 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7490 return std::nullopt;
7491 }
7492
7493 auto ShouldDelayChecks = [](Expr *&E, bool) {
7494 return E && (E->isTypeDependent() || E->isValueDependent() ||
7497 };
7498 // Do not check templates, wait until instantiation.
7499 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7500 TI.anyScoreOrCondition(ShouldDelayChecks))
7501 return std::make_pair(FD, VariantRef);
7502
7503 // Deal with non-constant score and user condition expressions.
7504 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7505 bool IsScore) -> bool {
7506 if (!E || E->isIntegerConstantExpr(getASTContext()))
7507 return false;
7508
7509 if (IsScore) {
7510 // We warn on non-constant scores and pretend they were not present.
7511 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7512 << E;
7513 E = nullptr;
7514 } else {
7515 // We could replace a non-constant user condition with "false" but we
7516 // will soon need to handle these anyway for the dynamic version of
7517 // OpenMP context selectors.
7518 Diag(E->getExprLoc(),
7519 diag::err_omp_declare_variant_user_condition_not_constant)
7520 << E;
7521 }
7522 return true;
7523 };
7524 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7525 return std::nullopt;
7526
7527 QualType AdjustedFnType = FD->getType();
7528 if (NumAppendArgs) {
7529 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7530 if (!PTy) {
7531 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7532 << SR;
7533 return std::nullopt;
7534 }
7535 // Adjust the function type to account for an extra omp_interop_t for each
7536 // specified in the append_args clause.
7537 const TypeDecl *TD = nullptr;
7538 LookupResult Result(SemaRef, &Context.Idents.get("omp_interop_t"),
7540 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
7541 NamedDecl *ND = Result.getFoundDecl();
7542 TD = dyn_cast_or_null<TypeDecl>(ND);
7543 }
7544 if (!TD) {
7545 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7546 return std::nullopt;
7547 }
7548 QualType InteropType =
7549 Context.getTypeDeclType(ElaboratedTypeKeyword::None,
7550 /*Qualifier=*/std::nullopt, TD);
7551 if (PTy->isVariadic()) {
7552 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7553 return std::nullopt;
7554 }
7556 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7557 Params.insert(Params.end(), NumAppendArgs, InteropType);
7558 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7559 PTy->getExtProtoInfo());
7560 }
7561
7562 // Convert VariantRef expression to the type of the original function to
7563 // resolve possible conflicts.
7564 ExprResult VariantRefCast = VariantRef;
7565 if (getLangOpts().CPlusPlus) {
7566 QualType FnPtrType;
7567 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7568 if (Method && !Method->isStatic()) {
7569 FnPtrType = Context.getMemberPointerType(
7570 AdjustedFnType, /*Qualifier=*/std::nullopt, Method->getParent());
7571 ExprResult ER;
7572 {
7573 // Build addr_of unary op to correctly handle type checks for member
7574 // functions.
7576 ER = SemaRef.CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7577 VariantRef);
7578 }
7579 if (!ER.isUsable()) {
7580 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7581 << VariantId << VariantRef->getSourceRange();
7582 return std::nullopt;
7583 }
7584 VariantRef = ER.get();
7585 } else {
7586 FnPtrType = Context.getPointerType(AdjustedFnType);
7587 }
7588 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7589 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7590 ImplicitConversionSequence ICS = SemaRef.TryImplicitConversion(
7591 VariantRef, FnPtrType.getUnqualifiedType(),
7592 /*SuppressUserConversions=*/false, Sema::AllowedExplicit::None,
7593 /*InOverloadResolution=*/false,
7594 /*CStyle=*/false,
7595 /*AllowObjCWritebackConversion=*/false);
7596 if (ICS.isFailure()) {
7597 Diag(VariantRef->getExprLoc(),
7598 diag::err_omp_declare_variant_incompat_types)
7599 << VariantRef->getType()
7600 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7601 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7602 return std::nullopt;
7603 }
7604 VariantRefCast = SemaRef.PerformImplicitConversion(
7605 VariantRef, FnPtrType.getUnqualifiedType(),
7607 if (!VariantRefCast.isUsable())
7608 return std::nullopt;
7609 }
7610 // Drop previously built artificial addr_of unary op for member functions.
7611 if (Method && !Method->isStatic()) {
7612 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7613 if (auto *UO = dyn_cast<UnaryOperator>(
7614 PossibleAddrOfVariantRef->IgnoreImplicit()))
7615 VariantRefCast = UO->getSubExpr();
7616 }
7617 }
7618
7619 ExprResult ER = SemaRef.CheckPlaceholderExpr(VariantRefCast.get());
7620 if (!ER.isUsable() ||
7622 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7623 << VariantId << VariantRef->getSourceRange();
7624 return std::nullopt;
7625 }
7626
7627 // The VariantRef must point to function.
7628 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7629 if (!DRE) {
7630 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7631 << VariantId << VariantRef->getSourceRange();
7632 return std::nullopt;
7633 }
7634 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7635 if (!NewFD) {
7636 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7637 << VariantId << VariantRef->getSourceRange();
7638 return std::nullopt;
7639 }
7640
7641 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7642 Diag(VariantRef->getExprLoc(),
7643 diag::err_omp_declare_variant_same_base_function)
7644 << VariantRef->getSourceRange();
7645 return std::nullopt;
7646 }
7647
7648 // Check if function types are compatible in C.
7649 if (!getLangOpts().CPlusPlus) {
7650 QualType NewType =
7651 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7652 if (NewType.isNull()) {
7653 Diag(VariantRef->getExprLoc(),
7654 diag::err_omp_declare_variant_incompat_types)
7655 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7656 << VariantRef->getSourceRange();
7657 return std::nullopt;
7658 }
7659 if (NewType->isFunctionProtoType()) {
7660 if (FD->getType()->isFunctionNoProtoType())
7661 setPrototype(SemaRef, FD, NewFD, NewType);
7662 else if (NewFD->getType()->isFunctionNoProtoType())
7663 setPrototype(SemaRef, NewFD, FD, NewType);
7664 }
7665 }
7666
7667 // Check if variant function is not marked with declare variant directive.
7668 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7669 Diag(VariantRef->getExprLoc(),
7670 diag::warn_omp_declare_variant_marked_as_declare_variant)
7671 << VariantRef->getSourceRange();
7672 SourceRange SR =
7673 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7674 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7675 return std::nullopt;
7676 }
7677
7678 enum DoesntSupport {
7679 VirtFuncs = 1,
7680 Constructors = 3,
7681 Destructors = 4,
7682 DeletedFuncs = 5,
7683 DefaultedFuncs = 6,
7684 ConstexprFuncs = 7,
7685 ConstevalFuncs = 8,
7686 };
7687 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7688 if (CXXFD->isVirtual()) {
7689 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7690 << VirtFuncs;
7691 return std::nullopt;
7692 }
7693
7694 if (isa<CXXConstructorDecl>(FD)) {
7695 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7696 << Constructors;
7697 return std::nullopt;
7698 }
7699
7700 if (isa<CXXDestructorDecl>(FD)) {
7701 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7702 << Destructors;
7703 return std::nullopt;
7704 }
7705 }
7706
7707 if (FD->isDeleted()) {
7708 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7709 << DeletedFuncs;
7710 return std::nullopt;
7711 }
7712
7713 if (FD->isDefaulted()) {
7714 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7715 << DefaultedFuncs;
7716 return std::nullopt;
7717 }
7718
7719 if (FD->isConstexpr()) {
7720 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7721 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7722 return std::nullopt;
7723 }
7724
7725 // Check general compatibility.
7726 if (SemaRef.areMultiversionVariantFunctionsCompatible(
7731 VariantRef->getExprLoc(),
7732 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7733 PartialDiagnosticAt(VariantRef->getExprLoc(),
7734 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7735 << FD->getLocation()),
7736 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7737 /*CLinkageMayDiffer=*/true))
7738 return std::nullopt;
7739 return std::make_pair(FD, cast<Expr>(DRE));
7740}
7741
7743 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7744 ArrayRef<Expr *> AdjustArgsNothing,
7745 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7746 ArrayRef<Expr *> AdjustArgsNeedDeviceAddr,
7747 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7748 SourceLocation AppendArgsLoc, SourceRange SR) {
7749
7750 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7751 // An adjust_args clause or append_args clause can only be specified if the
7752 // dispatch selector of the construct selector set appears in the match
7753 // clause.
7754
7755 SmallVector<Expr *, 8> AllAdjustArgs;
7756 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7757 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7758 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDeviceAddr);
7759
7760 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7761 VariantMatchInfo VMI;
7763 if (!llvm::is_contained(
7764 VMI.ConstructTraits,
7765 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7766 if (!AllAdjustArgs.empty())
7767 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7768 << getOpenMPClauseNameForDiag(OMPC_adjust_args);
7769 if (!AppendArgs.empty())
7770 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7771 << getOpenMPClauseNameForDiag(OMPC_append_args);
7772 return;
7773 }
7774 }
7775
7776 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7777 // Each argument can only appear in a single adjust_args clause for each
7778 // declare variant directive.
7780
7781 for (Expr *E : AllAdjustArgs) {
7782 E = E->IgnoreParenImpCasts();
7783 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7784 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7785 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7786 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7787 FD->getParamDecl(PVD->getFunctionScopeIndex())
7788 ->getCanonicalDecl() == CanonPVD) {
7789 // It's a parameter of the function, check duplicates.
7790 if (!AdjustVars.insert(CanonPVD).second) {
7791 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7792 << PVD;
7793 return;
7794 }
7795 continue;
7796 }
7797 }
7798 }
7799 // Anything that is not a function parameter is an error.
7800 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7801 return;
7802 }
7803
7804 // OpenMP 6.0 [9.6.2 (page 332, line 31-33, adjust_args clause, Restrictions]
7805 // If the `need_device_addr` adjust-op modifier is present, each list item
7806 // that appears in the clause must refer to an argument in the declaration of
7807 // the function variant that has a reference type
7808 if (getLangOpts().OpenMP >= 60) {
7809 for (Expr *E : AdjustArgsNeedDeviceAddr) {
7810 E = E->IgnoreParenImpCasts();
7811 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7812 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
7813 if (!VD->getType()->isReferenceType())
7814 Diag(E->getExprLoc(),
7815 diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
7816 }
7817 }
7818 }
7819 }
7820
7821 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7822 getASTContext(), VariantRef, &TI,
7823 const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7824 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7825 AdjustArgsNeedDevicePtr.size(),
7826 const_cast<Expr **>(AdjustArgsNeedDeviceAddr.data()),
7827 AdjustArgsNeedDeviceAddr.size(),
7828 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7829 FD->addAttr(NewAttr);
7830}
7831
7832static CapturedStmt *
7834 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7835 assert(CS && "Captured statement expected");
7836 // 1.2.2 OpenMP Language Terminology
7837 // Structured block - An executable statement with a single entry at the
7838 // top and a single exit at the bottom.
7839 // The point of exit cannot be a branch out of the structured block.
7840 // longjmp() and throw() must not violate the entry/exit criteria.
7841 CS->getCapturedDecl()->setNothrow();
7842
7843 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
7844 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7846 // 1.2.2 OpenMP Language Terminology
7847 // Structured block - An executable statement with a single entry at the
7848 // top and a single exit at the bottom.
7849 // The point of exit cannot be a branch out of the structured block.
7850 // longjmp() and throw() must not violate the entry/exit criteria.
7851 CS->getCapturedDecl()->setNothrow();
7852 }
7854 return CS;
7855}
7856
7859 Stmt *AStmt, SourceLocation StartLoc,
7860 SourceLocation EndLoc) {
7861 if (!AStmt)
7862 return StmtError();
7863
7864 setBranchProtectedScope(SemaRef, OMPD_parallel, AStmt);
7865
7866 return OMPParallelDirective::Create(
7867 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
7868 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
7869}
7870
7871namespace {
7872/// Iteration space of a single for loop.
7873struct LoopIterationSpace final {
7874 /// True if the condition operator is the strict compare operator (<, > or
7875 /// !=).
7876 bool IsStrictCompare = false;
7877 /// Condition of the loop.
7878 Expr *PreCond = nullptr;
7879 /// This expression calculates the number of iterations in the loop.
7880 /// It is always possible to calculate it before starting the loop.
7881 Expr *NumIterations = nullptr;
7882 /// The loop counter variable.
7883 Expr *CounterVar = nullptr;
7884 /// Private loop counter variable.
7885 Expr *PrivateCounterVar = nullptr;
7886 /// This is initializer for the initial value of #CounterVar.
7887 Expr *CounterInit = nullptr;
7888 /// This is step for the #CounterVar used to generate its update:
7889 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7890 Expr *CounterStep = nullptr;
7891 /// Should step be subtracted?
7892 bool Subtract = false;
7893 /// Source range of the loop init.
7894 SourceRange InitSrcRange;
7895 /// Source range of the loop condition.
7896 SourceRange CondSrcRange;
7897 /// Source range of the loop increment.
7898 SourceRange IncSrcRange;
7899 /// Minimum value that can have the loop control variable. Used to support
7900 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7901 /// since only such variables can be used in non-loop invariant expressions.
7902 Expr *MinValue = nullptr;
7903 /// Maximum value that can have the loop control variable. Used to support
7904 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7905 /// since only such variables can be used in non-loop invariant expressions.
7906 Expr *MaxValue = nullptr;
7907 /// true, if the lower bound depends on the outer loop control var.
7908 bool IsNonRectangularLB = false;
7909 /// true, if the upper bound depends on the outer loop control var.
7910 bool IsNonRectangularUB = false;
7911 /// Index of the loop this loop depends on and forms non-rectangular loop
7912 /// nest.
7913 unsigned LoopDependentIdx = 0;
7914 /// Final condition for the non-rectangular loop nest support. It is used to
7915 /// check that the number of iterations for this particular counter must be
7916 /// finished.
7917 Expr *FinalCondition = nullptr;
7918};
7919
7920/// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls
7921/// set are referenced. Used for verifying loop nest structure before
7922/// performing a loop collapse operation.
7923class ForSubExprChecker : public DynamicRecursiveASTVisitor {
7924 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7925 VarDecl *ForbiddenVar = nullptr;
7926 SourceRange ErrLoc;
7927
7928public:
7929 explicit ForSubExprChecker(
7930 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7931 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
7932 // We want to visit implicit code, i.e. synthetic initialisation statements
7933 // created during range-for lowering.
7934 ShouldVisitImplicitCode = true;
7935 }
7936
7937 bool VisitDeclRefExpr(DeclRefExpr *E) override {
7938 ValueDecl *VD = E->getDecl();
7940 return true;
7941 VarDecl *V = VD->getPotentiallyDecomposedVarDecl();
7942 if (V->getType()->isReferenceType()) {
7943 VarDecl *VD = V->getDefinition();
7944 if (VD->hasInit()) {
7945 Expr *I = VD->getInit();
7946 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
7947 if (!DRE)
7948 return true;
7950 }
7951 }
7952 Decl *Canon = V->getCanonicalDecl();
7953 if (CollapsedLoopVarDecls.contains(Canon)) {
7954 ForbiddenVar = V;
7955 ErrLoc = E->getSourceRange();
7956 return false;
7957 }
7958
7959 return true;
7960 }
7961
7962 VarDecl *getForbiddenVar() const { return ForbiddenVar; }
7963 SourceRange getErrRange() const { return ErrLoc; }
7964};
7965
7966/// Helper class for checking canonical form of the OpenMP loops and
7967/// extracting iteration space of each loop in the loop nest, that will be used
7968/// for IR generation.
7969class OpenMPIterationSpaceChecker {
7970 /// Reference to Sema.
7971 Sema &SemaRef;
7972 /// Does the loop associated directive support non-rectangular loops?
7973 bool SupportsNonRectangular;
7974 /// Data-sharing stack.
7975 DSAStackTy &Stack;
7976 /// A location for diagnostics (when there is no some better location).
7977 SourceLocation DefaultLoc;
7978 /// A location for diagnostics (when increment is not compatible).
7979 SourceLocation ConditionLoc;
7980 /// The set of variables declared within the (to be collapsed) loop nest.
7981 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7982 /// A source location for referring to loop init later.
7983 SourceRange InitSrcRange;
7984 /// A source location for referring to condition later.
7985 SourceRange ConditionSrcRange;
7986 /// A source location for referring to increment later.
7987 SourceRange IncrementSrcRange;
7988 /// Loop variable.
7989 ValueDecl *LCDecl = nullptr;
7990 /// Reference to loop variable.
7991 Expr *LCRef = nullptr;
7992 /// Lower bound (initializer for the var).
7993 Expr *LB = nullptr;
7994 /// Upper bound.
7995 Expr *UB = nullptr;
7996 /// Loop step (increment).
7997 Expr *Step = nullptr;
7998 /// This flag is true when condition is one of:
7999 /// Var < UB
8000 /// Var <= UB
8001 /// UB > Var
8002 /// UB >= Var
8003 /// This will have no value when the condition is !=
8004 std::optional<bool> TestIsLessOp;
8005 /// This flag is true when condition is strict ( < or > ).
8006 bool TestIsStrictOp = false;
8007 /// This flag is true when step is subtracted on each iteration.
8008 bool SubtractStep = false;
8009 /// The outer loop counter this loop depends on (if any).
8010 const ValueDecl *DepDecl = nullptr;
8011 /// Contains number of loop (starts from 1) on which loop counter init
8012 /// expression of this loop depends on.
8013 std::optional<unsigned> InitDependOnLC;
8014 /// Contains number of loop (starts from 1) on which loop counter condition
8015 /// expression of this loop depends on.
8016 std::optional<unsigned> CondDependOnLC;
8017 /// Checks if the provide statement depends on the loop counter.
8018 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
8019 bool IsInitializer);
8020 /// Original condition required for checking of the exit condition for
8021 /// non-rectangular loop.
8022 Expr *Condition = nullptr;
8023
8024public:
8025 OpenMPIterationSpaceChecker(
8026 Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack,
8027 SourceLocation DefaultLoc,
8028 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
8029 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8030 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
8031 CollapsedLoopVarDecls(CollapsedLoopDecls) {}
8032 /// Check init-expr for canonical loop form and save loop counter
8033 /// variable - #Var and its initialization value - #LB.
8034 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
8035 /// Check test-expr for canonical form, save upper-bound (#UB), flags
8036 /// for less/greater and for strict/non-strict comparison.
8037 bool checkAndSetCond(Expr *S);
8038 /// Check incr-expr for canonical loop form and return true if it
8039 /// does not conform, otherwise save loop step (#Step).
8040 bool checkAndSetInc(Expr *S);
8041 /// Return the loop counter variable.
8042 ValueDecl *getLoopDecl() const { return LCDecl; }
8043 /// Return the reference expression to loop counter variable.
8044 Expr *getLoopDeclRefExpr() const { return LCRef; }
8045 /// Source range of the loop init.
8046 SourceRange getInitSrcRange() const { return InitSrcRange; }
8047 /// Source range of the loop condition.
8048 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
8049 /// Source range of the loop increment.
8050 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
8051 /// True if the step should be subtracted.
8052 bool shouldSubtractStep() const { return SubtractStep; }
8053 /// True, if the compare operator is strict (<, > or !=).
8054 bool isStrictTestOp() const { return TestIsStrictOp; }
8055 /// Build the expression to calculate the number of iterations.
8056 Expr *buildNumIterations(
8057 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8058 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8059 /// Build the precondition expression for the loops.
8060 Expr *
8061 buildPreCond(Scope *S, Expr *Cond,
8062 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8063 /// Build reference expression to the counter be used for codegen.
8064 DeclRefExpr *
8065 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8066 DSAStackTy &DSA) const;
8067 /// Build reference expression to the private counter be used for
8068 /// codegen.
8069 Expr *buildPrivateCounterVar() const;
8070 /// Build initialization of the counter be used for codegen.
8071 Expr *buildCounterInit() const;
8072 /// Build step of the counter be used for codegen.
8073 Expr *buildCounterStep() const;
8074 /// Build loop data with counter value for depend clauses in ordered
8075 /// directives.
8076 Expr *
8077 buildOrderedLoopData(Scope *S, Expr *Counter,
8078 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8079 SourceLocation Loc, Expr *Inc = nullptr,
8080 OverloadedOperatorKind OOK = OO_Amp);
8081 /// Builds the minimum value for the loop counter.
8082 std::pair<Expr *, Expr *> buildMinMaxValues(
8083 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8084 /// Builds final condition for the non-rectangular loops.
8085 Expr *buildFinalCondition(Scope *S) const;
8086 /// Return true if any expression is dependent.
8087 bool dependent() const;
8088 /// Returns true if the initializer forms non-rectangular loop.
8089 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
8090 /// Returns true if the condition forms non-rectangular loop.
8091 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
8092 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
8093 unsigned getLoopDependentIdx() const {
8094 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
8095 }
8096
8097private:
8098 /// Check the right-hand side of an assignment in the increment
8099 /// expression.
8100 bool checkAndSetIncRHS(Expr *RHS);
8101 /// Helper to set loop counter variable and its initializer.
8102 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8103 bool EmitDiags);
8104 /// Helper to set upper bound.
8105 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
8106 SourceRange SR, SourceLocation SL);
8107 /// Helper to set loop increment.
8108 bool setStep(Expr *NewStep, bool Subtract);
8109};
8110
8111bool OpenMPIterationSpaceChecker::dependent() const {
8112 if (!LCDecl) {
8113 assert(!LB && !UB && !Step);
8114 return false;
8115 }
8116 return LCDecl->getType()->isDependentType() ||
8117 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
8118 (Step && Step->isValueDependent());
8119}
8120
8121bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
8122 Expr *NewLCRefExpr,
8123 Expr *NewLB, bool EmitDiags) {
8124 // State consistency checking to ensure correct usage.
8125 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
8126 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8127 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
8128 return true;
8129 LCDecl = getCanonicalDecl(NewLCDecl);
8130 LCRef = NewLCRefExpr;
8131 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
8132 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8133 if ((Ctor->isCopyOrMoveConstructor() ||
8134 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8135 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8136 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
8137 LB = NewLB;
8138 if (EmitDiags)
8139 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
8140 return false;
8141}
8142
8143bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
8144 bool StrictOp, SourceRange SR,
8145 SourceLocation SL) {
8146 // State consistency checking to ensure correct usage.
8147 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
8148 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8149 if (!NewUB || NewUB->containsErrors())
8150 return true;
8151 UB = NewUB;
8152 if (LessOp)
8153 TestIsLessOp = LessOp;
8154 TestIsStrictOp = StrictOp;
8155 ConditionSrcRange = SR;
8156 ConditionLoc = SL;
8157 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
8158 return false;
8159}
8160
8161bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
8162 // State consistency checking to ensure correct usage.
8163 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
8164 if (!NewStep || NewStep->containsErrors())
8165 return true;
8166 if (!NewStep->isValueDependent()) {
8167 // Check that the step is integer expression.
8168 SourceLocation StepLoc = NewStep->getBeginLoc();
8170 StepLoc, getExprAsWritten(NewStep));
8171 if (Val.isInvalid())
8172 return true;
8173 NewStep = Val.get();
8174
8175 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8176 // If test-expr is of form var relational-op b and relational-op is < or
8177 // <= then incr-expr must cause var to increase on each iteration of the
8178 // loop. If test-expr is of form var relational-op b and relational-op is
8179 // > or >= then incr-expr must cause var to decrease on each iteration of
8180 // the loop.
8181 // If test-expr is of form b relational-op var and relational-op is < or
8182 // <= then incr-expr must cause var to decrease on each iteration of the
8183 // loop. If test-expr is of form b relational-op var and relational-op is
8184 // > or >= then incr-expr must cause var to increase on each iteration of
8185 // the loop.
8186 std::optional<llvm::APSInt> Result =
8187 NewStep->getIntegerConstantExpr(SemaRef.Context);
8188 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
8189 bool IsConstNeg =
8190 Result && Result->isSigned() && (Subtract != Result->isNegative());
8191 bool IsConstPos =
8192 Result && Result->isSigned() && (Subtract == Result->isNegative());
8193 bool IsConstZero = Result && !Result->getBoolValue();
8194
8195 // != with increment is treated as <; != with decrement is treated as >
8196 if (!TestIsLessOp)
8197 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8198 if (UB && (IsConstZero ||
8199 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8200 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8201 SemaRef.Diag(NewStep->getExprLoc(),
8202 diag::err_omp_loop_incr_not_compatible)
8203 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
8204 SemaRef.Diag(ConditionLoc,
8205 diag::note_omp_loop_cond_requires_compatible_incr)
8206 << *TestIsLessOp << ConditionSrcRange;
8207 return true;
8208 }
8209 if (*TestIsLessOp == Subtract) {
8210 NewStep =
8211 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
8212 .get();
8213 Subtract = !Subtract;
8214 }
8215 }
8216
8217 Step = NewStep;
8218 SubtractStep = Subtract;
8219 return false;
8220}
8221
8222namespace {
8223/// Checker for the non-rectangular loops. Checks if the initializer or
8224/// condition expression references loop counter variable.
8225class LoopCounterRefChecker final
8226 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8227 Sema &SemaRef;
8228 DSAStackTy &Stack;
8229 const ValueDecl *CurLCDecl = nullptr;
8230 const ValueDecl *DepDecl = nullptr;
8231 const ValueDecl *PrevDepDecl = nullptr;
8232 bool IsInitializer = true;
8233 bool SupportsNonRectangular;
8234 unsigned BaseLoopId = 0;
8235 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8236 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
8237 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8238 << (IsInitializer ? 0 : 1);
8239 return false;
8240 }
8241 const auto &&Data = Stack.isLoopControlVariable(VD);
8242 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8243 // The type of the loop iterator on which we depend may not have a random
8244 // access iterator type.
8245 if (Data.first && VD->getType()->isRecordType()) {
8246 SmallString<128> Name;
8247 llvm::raw_svector_ostream OS(Name);
8248 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8249 /*Qualified=*/true);
8250 SemaRef.Diag(E->getExprLoc(),
8251 diag::err_omp_wrong_dependency_iterator_type)
8252 << OS.str();
8253 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8254 return false;
8255 }
8256 if (Data.first && !SupportsNonRectangular) {
8257 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8258 return false;
8259 }
8260 if (Data.first &&
8261 (DepDecl || (PrevDepDecl &&
8262 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8263 if (!DepDecl && PrevDepDecl)
8264 DepDecl = PrevDepDecl;
8265 SmallString<128> Name;
8266 llvm::raw_svector_ostream OS(Name);
8267 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8268 /*Qualified=*/true);
8269 SemaRef.Diag(E->getExprLoc(),
8270 diag::err_omp_invariant_or_linear_dependency)
8271 << OS.str();
8272 return false;
8273 }
8274 if (Data.first) {
8275 DepDecl = VD;
8276 BaseLoopId = Data.first;
8277 }
8278 return Data.first;
8279 }
8280
8281public:
8282 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8283 const ValueDecl *VD = E->getDecl();
8284 if (isa<VarDecl>(VD))
8285 return checkDecl(E, VD);
8286 return false;
8287 }
8288 bool VisitMemberExpr(const MemberExpr *E) {
8289 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8290 const ValueDecl *VD = E->getMemberDecl();
8291 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8292 return checkDecl(E, VD);
8293 }
8294 return false;
8295 }
8296 bool VisitStmt(const Stmt *S) {
8297 bool Res = false;
8298 for (const Stmt *Child : S->children())
8299 Res = (Child && Visit(Child)) || Res;
8300 return Res;
8301 }
8302 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8303 const ValueDecl *CurLCDecl, bool IsInitializer,
8304 const ValueDecl *PrevDepDecl = nullptr,
8305 bool SupportsNonRectangular = true)
8306 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8307 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8308 SupportsNonRectangular(SupportsNonRectangular) {}
8309 unsigned getBaseLoopId() const {
8310 assert(CurLCDecl && "Expected loop dependency.");
8311 return BaseLoopId;
8312 }
8313 const ValueDecl *getDepDecl() const {
8314 assert(CurLCDecl && "Expected loop dependency.");
8315 return DepDecl;
8316 }
8317};
8318} // namespace
8319
8320std::optional<unsigned>
8321OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8322 bool IsInitializer) {
8323 // Check for the non-rectangular loops.
8324 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8325 DepDecl, SupportsNonRectangular);
8326 if (LoopStmtChecker.Visit(S)) {
8327 DepDecl = LoopStmtChecker.getDepDecl();
8328 return LoopStmtChecker.getBaseLoopId();
8329 }
8330 return std::nullopt;
8331}
8332
8333bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8334 // Check init-expr for canonical loop form and save loop counter
8335 // variable - #Var and its initialization value - #LB.
8336 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8337 // var = lb
8338 // integer-type var = lb
8339 // random-access-iterator-type var = lb
8340 // pointer-type var = lb
8341 //
8342 if (!S) {
8343 if (EmitDiags) {
8344 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8345 }
8346 return true;
8347 }
8348 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8349 if (!ExprTemp->cleanupsHaveSideEffects())
8350 S = ExprTemp->getSubExpr();
8351
8352 if (!CollapsedLoopVarDecls.empty()) {
8353 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8354 if (!FSEC.TraverseStmt(S)) {
8355 SourceRange Range = FSEC.getErrRange();
8356 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8357 << Range.getEnd() << 0 << FSEC.getForbiddenVar();
8358 return true;
8359 }
8360 }
8361
8362 InitSrcRange = S->getSourceRange();
8363 if (Expr *E = dyn_cast<Expr>(S))
8364 S = E->IgnoreParens();
8365 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8366 if (BO->getOpcode() == BO_Assign) {
8367 Expr *LHS = BO->getLHS()->IgnoreParens();
8368 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8369 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8370 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8371 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8372 EmitDiags);
8373 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8374 }
8375 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8376 if (ME->isArrow() &&
8377 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8378 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8379 EmitDiags);
8380 }
8381 }
8382 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8383 if (DS->isSingleDecl()) {
8384 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8385 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8386 // Accept non-canonical init form here but emit ext. warning.
8387 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8388 SemaRef.Diag(S->getBeginLoc(),
8389 diag::ext_omp_loop_not_canonical_init)
8390 << S->getSourceRange();
8391 return setLCDeclAndLB(
8392 Var,
8393 buildDeclRefExpr(SemaRef, Var,
8394 Var->getType().getNonReferenceType(),
8395 DS->getBeginLoc()),
8396 Var->getInit(), EmitDiags);
8397 }
8398 }
8399 }
8400 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8401 if (CE->getOperator() == OO_Equal) {
8402 Expr *LHS = CE->getArg(0);
8403 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8404 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8405 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8406 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8407 EmitDiags);
8408 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8409 }
8410 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8411 if (ME->isArrow() &&
8412 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8413 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8414 EmitDiags);
8415 }
8416 }
8417 }
8418
8419 if (dependent() || SemaRef.CurContext->isDependentContext())
8420 return false;
8421 if (EmitDiags) {
8422 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8423 << S->getSourceRange();
8424 }
8425 return true;
8426}
8427
8428/// Ignore parenthesizes, implicit casts, copy constructor and return the
8429/// variable (which may be the loop variable) if possible.
8430static const ValueDecl *getInitLCDecl(const Expr *E) {
8431 if (!E)
8432 return nullptr;
8433 E = getExprAsWritten(E);
8434 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8435 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8436 if ((Ctor->isCopyOrMoveConstructor() ||
8437 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8438 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8439 E = CE->getArg(0)->IgnoreParenImpCasts();
8440 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8441 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8442 return getCanonicalDecl(VD);
8443 }
8444 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8445 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8446 return getCanonicalDecl(ME->getMemberDecl());
8447 return nullptr;
8448}
8449
8450bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8451 // Check test-expr for canonical form, save upper-bound UB, flags for
8452 // less/greater and for strict/non-strict comparison.
8453 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8454 // var relational-op b
8455 // b relational-op var
8456 //
8457 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8458 if (!S) {
8459 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8460 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8461 return true;
8462 }
8463 Condition = S;
8464 S = getExprAsWritten(S);
8465
8466 if (!CollapsedLoopVarDecls.empty()) {
8467 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8468 if (!FSEC.TraverseStmt(S)) {
8469 SourceRange Range = FSEC.getErrRange();
8470 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8471 << Range.getEnd() << 1 << FSEC.getForbiddenVar();
8472 return true;
8473 }
8474 }
8475
8476 SourceLocation CondLoc = S->getBeginLoc();
8477 auto &&CheckAndSetCond =
8478 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8479 const Expr *RHS, SourceRange SR,
8480 SourceLocation OpLoc) -> std::optional<bool> {
8481 if (BinaryOperator::isRelationalOp(Opcode)) {
8482 if (getInitLCDecl(LHS) == LCDecl)
8483 return setUB(const_cast<Expr *>(RHS),
8484 (Opcode == BO_LT || Opcode == BO_LE),
8485 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8486 if (getInitLCDecl(RHS) == LCDecl)
8487 return setUB(const_cast<Expr *>(LHS),
8488 (Opcode == BO_GT || Opcode == BO_GE),
8489 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8490 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8491 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8492 /*LessOp=*/std::nullopt,
8493 /*StrictOp=*/true, SR, OpLoc);
8494 }
8495 return std::nullopt;
8496 };
8497 std::optional<bool> Res;
8498 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8499 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8500 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8501 RBO->getOperatorLoc());
8502 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8503 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8504 BO->getSourceRange(), BO->getOperatorLoc());
8505 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8506 if (CE->getNumArgs() == 2) {
8507 Res = CheckAndSetCond(
8508 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8509 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8510 }
8511 }
8512 if (Res)
8513 return *Res;
8514 if (dependent() || SemaRef.CurContext->isDependentContext())
8515 return false;
8516 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8517 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8518 return true;
8519}
8520
8521bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8522 // RHS of canonical loop form increment can be:
8523 // var + incr
8524 // incr + var
8525 // var - incr
8526 //
8527 RHS = RHS->IgnoreParenImpCasts();
8528 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8529 if (BO->isAdditiveOp()) {
8530 bool IsAdd = BO->getOpcode() == BO_Add;
8531 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8532 return setStep(BO->getRHS(), !IsAdd);
8533 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8534 return setStep(BO->getLHS(), /*Subtract=*/false);
8535 }
8536 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8537 bool IsAdd = CE->getOperator() == OO_Plus;
8538 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8539 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8540 return setStep(CE->getArg(1), !IsAdd);
8541 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8542 return setStep(CE->getArg(0), /*Subtract=*/false);
8543 }
8544 }
8545 if (dependent() || SemaRef.CurContext->isDependentContext())
8546 return false;
8547 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8548 << RHS->getSourceRange() << LCDecl;
8549 return true;
8550}
8551
8552bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8553 // Check incr-expr for canonical loop form and return true if it
8554 // does not conform.
8555 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8556 // ++var
8557 // var++
8558 // --var
8559 // var--
8560 // var += incr
8561 // var -= incr
8562 // var = var + incr
8563 // var = incr + var
8564 // var = var - incr
8565 //
8566 if (!S) {
8567 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8568 return true;
8569 }
8570 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8571 if (!ExprTemp->cleanupsHaveSideEffects())
8572 S = ExprTemp->getSubExpr();
8573
8574 if (!CollapsedLoopVarDecls.empty()) {
8575 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8576 if (!FSEC.TraverseStmt(S)) {
8577 SourceRange Range = FSEC.getErrRange();
8578 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8579 << Range.getEnd() << 2 << FSEC.getForbiddenVar();
8580 return true;
8581 }
8582 }
8583
8584 IncrementSrcRange = S->getSourceRange();
8585 S = S->IgnoreParens();
8586 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8587 if (UO->isIncrementDecrementOp() &&
8588 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8589 return setStep(SemaRef
8590 .ActOnIntegerConstant(UO->getBeginLoc(),
8591 (UO->isDecrementOp() ? -1 : 1))
8592 .get(),
8593 /*Subtract=*/false);
8594 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8595 switch (BO->getOpcode()) {
8596 case BO_AddAssign:
8597 case BO_SubAssign:
8598 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8599 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8600 break;
8601 case BO_Assign:
8602 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8603 return checkAndSetIncRHS(BO->getRHS());
8604 break;
8605 default:
8606 break;
8607 }
8608 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8609 switch (CE->getOperator()) {
8610 case OO_PlusPlus:
8611 case OO_MinusMinus:
8612 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8613 return setStep(SemaRef
8614 .ActOnIntegerConstant(
8615 CE->getBeginLoc(),
8616 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8617 .get(),
8618 /*Subtract=*/false);
8619 break;
8620 case OO_PlusEqual:
8621 case OO_MinusEqual:
8622 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8623 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8624 break;
8625 case OO_Equal:
8626 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8627 return checkAndSetIncRHS(CE->getArg(1));
8628 break;
8629 default:
8630 break;
8631 }
8632 }
8633 if (dependent() || SemaRef.CurContext->isDependentContext())
8634 return false;
8635 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8636 << S->getSourceRange() << LCDecl;
8637 return true;
8638}
8639
8640static ExprResult
8641tryBuildCapture(Sema &SemaRef, Expr *Capture,
8642 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8643 StringRef Name = ".capture_expr.") {
8644 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8645 return Capture;
8646 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8647 return SemaRef.PerformImplicitConversion(Capture->IgnoreImpCasts(),
8648 Capture->getType(),
8650 /*AllowExplicit=*/true);
8651 auto I = Captures.find(Capture);
8652 if (I != Captures.end())
8653 return buildCapture(SemaRef, Capture, I->second, Name);
8654 DeclRefExpr *Ref = nullptr;
8655 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8656 Captures[Capture] = Ref;
8657 return Res;
8658}
8659
8660/// Calculate number of iterations, transforming to unsigned, if number of
8661/// iterations may be larger than the original type.
8662static Expr *
8663calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8664 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8665 bool TestIsStrictOp, bool RoundToStep,
8666 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8667 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8668 if (!NewStep.isUsable())
8669 return nullptr;
8670 llvm::APSInt LRes, SRes;
8671 bool IsLowerConst = false, IsStepConst = false;
8672 if (std::optional<llvm::APSInt> Res =
8673 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8674 LRes = *Res;
8675 IsLowerConst = true;
8676 }
8677 if (std::optional<llvm::APSInt> Res =
8678 Step->getIntegerConstantExpr(SemaRef.Context)) {
8679 SRes = *Res;
8680 IsStepConst = true;
8681 }
8682 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8683 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8684 (TestIsStrictOp && LRes.isStrictlyPositive()));
8685 bool NeedToReorganize = false;
8686 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8687 if (!NoNeedToConvert && IsLowerConst &&
8688 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8689 NoNeedToConvert = true;
8690 if (RoundToStep) {
8691 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8692 ? LRes.getBitWidth()
8693 : SRes.getBitWidth();
8694 LRes = LRes.extend(BW + 1);
8695 LRes.setIsSigned(true);
8696 SRes = SRes.extend(BW + 1);
8697 SRes.setIsSigned(true);
8698 LRes -= SRes;
8699 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8700 LRes = LRes.trunc(BW);
8701 }
8702 if (TestIsStrictOp) {
8703 unsigned BW = LRes.getBitWidth();
8704 LRes = LRes.extend(BW + 1);
8705 LRes.setIsSigned(true);
8706 ++LRes;
8707 NoNeedToConvert =
8708 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8709 // truncate to the original bitwidth.
8710 LRes = LRes.trunc(BW);
8711 }
8712 NeedToReorganize = NoNeedToConvert;
8713 }
8714 llvm::APSInt URes;
8715 bool IsUpperConst = false;
8716 if (std::optional<llvm::APSInt> Res =
8717 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8718 URes = *Res;
8719 IsUpperConst = true;
8720 }
8721 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8722 (!RoundToStep || IsStepConst)) {
8723 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8724 : URes.getBitWidth();
8725 LRes = LRes.extend(BW + 1);
8726 LRes.setIsSigned(true);
8727 URes = URes.extend(BW + 1);
8728 URes.setIsSigned(true);
8729 URes -= LRes;
8730 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8731 NeedToReorganize = NoNeedToConvert;
8732 }
8733 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8734 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8735 // unsigned.
8736 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8737 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8738 QualType LowerTy = Lower->getType();
8739 QualType UpperTy = Upper->getType();
8740 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8741 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8742 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8743 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8745 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8746 Upper =
8747 SemaRef
8749 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8751 .get();
8752 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8753 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8754 }
8755 }
8756 if (!Lower || !Upper || NewStep.isInvalid())
8757 return nullptr;
8758
8759 ExprResult Diff;
8760 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8761 // 1]).
8762 if (NeedToReorganize) {
8763 Diff = Lower;
8764
8765 if (RoundToStep) {
8766 // Lower - Step
8767 Diff =
8768 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8769 if (!Diff.isUsable())
8770 return nullptr;
8771 }
8772
8773 // Lower - Step [+ 1]
8774 if (TestIsStrictOp)
8775 Diff = SemaRef.BuildBinOp(
8776 S, DefaultLoc, BO_Add, Diff.get(),
8777 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8778 if (!Diff.isUsable())
8779 return nullptr;
8780
8781 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8782 if (!Diff.isUsable())
8783 return nullptr;
8784
8785 // Upper - (Lower - Step [+ 1]).
8786 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8787 if (!Diff.isUsable())
8788 return nullptr;
8789 } else {
8790 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8791
8792 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8793 // BuildBinOp already emitted error, this one is to point user to upper
8794 // and lower bound, and to tell what is passed to 'operator-'.
8795 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8796 << Upper->getSourceRange() << Lower->getSourceRange();
8797 return nullptr;
8798 }
8799
8800 if (!Diff.isUsable())
8801 return nullptr;
8802
8803 // Upper - Lower [- 1]
8804 if (TestIsStrictOp)
8805 Diff = SemaRef.BuildBinOp(
8806 S, DefaultLoc, BO_Sub, Diff.get(),
8807 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8808 if (!Diff.isUsable())
8809 return nullptr;
8810
8811 if (RoundToStep) {
8812 // Upper - Lower [- 1] + Step
8813 Diff =
8814 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8815 if (!Diff.isUsable())
8816 return nullptr;
8817 }
8818 }
8819
8820 // Parentheses (for dumping/debugging purposes only).
8821 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8822 if (!Diff.isUsable())
8823 return nullptr;
8824
8825 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8826 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8827 if (!Diff.isUsable())
8828 return nullptr;
8829
8830 return Diff.get();
8831}
8832
8833/// Build the expression to calculate the number of iterations.
8834Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8835 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8836 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8837 QualType VarType = LCDecl->getType().getNonReferenceType();
8838 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8839 !SemaRef.getLangOpts().CPlusPlus)
8840 return nullptr;
8841 Expr *LBVal = LB;
8842 Expr *UBVal = UB;
8843 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8844 // max(LB(MinVal), LB(MaxVal)))
8845 if (InitDependOnLC) {
8846 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8847 if (!IS.MinValue || !IS.MaxValue)
8848 return nullptr;
8849 // OuterVar = Min
8850 ExprResult MinValue =
8851 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8852 if (!MinValue.isUsable())
8853 return nullptr;
8854
8855 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8856 IS.CounterVar, MinValue.get());
8857 if (!LBMinVal.isUsable())
8858 return nullptr;
8859 // OuterVar = Min, LBVal
8860 LBMinVal =
8861 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8862 if (!LBMinVal.isUsable())
8863 return nullptr;
8864 // (OuterVar = Min, LBVal)
8865 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8866 if (!LBMinVal.isUsable())
8867 return nullptr;
8868
8869 // OuterVar = Max
8870 ExprResult MaxValue =
8871 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8872 if (!MaxValue.isUsable())
8873 return nullptr;
8874
8875 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8876 IS.CounterVar, MaxValue.get());
8877 if (!LBMaxVal.isUsable())
8878 return nullptr;
8879 // OuterVar = Max, LBVal
8880 LBMaxVal =
8881 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8882 if (!LBMaxVal.isUsable())
8883 return nullptr;
8884 // (OuterVar = Max, LBVal)
8885 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8886 if (!LBMaxVal.isUsable())
8887 return nullptr;
8888
8889 Expr *LBMin =
8890 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
8891 Expr *LBMax =
8892 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
8893 if (!LBMin || !LBMax)
8894 return nullptr;
8895 // LB(MinVal) < LB(MaxVal)
8896 ExprResult MinLessMaxRes =
8897 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8898 if (!MinLessMaxRes.isUsable())
8899 return nullptr;
8900 Expr *MinLessMax =
8901 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
8902 .get();
8903 if (!MinLessMax)
8904 return nullptr;
8905 if (*TestIsLessOp) {
8906 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8907 // LB(MaxVal))
8908 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8909 MinLessMax, LBMin, LBMax);
8910 if (!MinLB.isUsable())
8911 return nullptr;
8912 LBVal = MinLB.get();
8913 } else {
8914 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8915 // LB(MaxVal))
8916 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8917 MinLessMax, LBMax, LBMin);
8918 if (!MaxLB.isUsable())
8919 return nullptr;
8920 LBVal = MaxLB.get();
8921 }
8922 // OuterVar = LB
8923 LBMinVal =
8924 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8925 if (!LBMinVal.isUsable())
8926 return nullptr;
8927 LBVal = LBMinVal.get();
8928 }
8929 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8930 // min(UB(MinVal), UB(MaxVal))
8931 if (CondDependOnLC) {
8932 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8933 if (!IS.MinValue || !IS.MaxValue)
8934 return nullptr;
8935 // OuterVar = Min
8936 ExprResult MinValue =
8937 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8938 if (!MinValue.isUsable())
8939 return nullptr;
8940
8941 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8942 IS.CounterVar, MinValue.get());
8943 if (!UBMinVal.isUsable())
8944 return nullptr;
8945 // OuterVar = Min, UBVal
8946 UBMinVal =
8947 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
8948 if (!UBMinVal.isUsable())
8949 return nullptr;
8950 // (OuterVar = Min, UBVal)
8951 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
8952 if (!UBMinVal.isUsable())
8953 return nullptr;
8954
8955 // OuterVar = Max
8956 ExprResult MaxValue =
8957 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8958 if (!MaxValue.isUsable())
8959 return nullptr;
8960
8961 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8962 IS.CounterVar, MaxValue.get());
8963 if (!UBMaxVal.isUsable())
8964 return nullptr;
8965 // OuterVar = Max, UBVal
8966 UBMaxVal =
8967 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
8968 if (!UBMaxVal.isUsable())
8969 return nullptr;
8970 // (OuterVar = Max, UBVal)
8971 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
8972 if (!UBMaxVal.isUsable())
8973 return nullptr;
8974
8975 Expr *UBMin =
8976 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
8977 Expr *UBMax =
8978 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
8979 if (!UBMin || !UBMax)
8980 return nullptr;
8981 // UB(MinVal) > UB(MaxVal)
8982 ExprResult MinGreaterMaxRes =
8983 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8984 if (!MinGreaterMaxRes.isUsable())
8985 return nullptr;
8986 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
8987 Captures, ".min_greater_max")
8988 .get();
8989 if (!MinGreaterMax)
8990 return nullptr;
8991 if (*TestIsLessOp) {
8992 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8993 // UB(MaxVal))
8994 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
8995 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8996 if (!MaxUB.isUsable())
8997 return nullptr;
8998 UBVal = MaxUB.get();
8999 } else {
9000 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
9001 // UB(MaxVal))
9002 ExprResult MinUB = SemaRef.ActOnConditionalOp(
9003 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
9004 if (!MinUB.isUsable())
9005 return nullptr;
9006 UBVal = MinUB.get();
9007 }
9008 }
9009 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9010 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9011 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
9012 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
9013 if (!Upper || !Lower)
9014 return nullptr;
9015
9016 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9017 Step, VarType, TestIsStrictOp,
9018 /*RoundToStep=*/true, Captures);
9019 if (!Diff.isUsable())
9020 return nullptr;
9021
9022 // OpenMP runtime requires 32-bit or 64-bit loop variables.
9023 QualType Type = Diff.get()->getType();
9024 ASTContext &C = SemaRef.Context;
9025 bool UseVarType = VarType->hasIntegerRepresentation() &&
9026 C.getTypeSize(Type) > C.getTypeSize(VarType);
9027 if (!Type->isIntegerType() || UseVarType) {
9028 unsigned NewSize =
9029 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
9030 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
9032 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
9033 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
9034 Diff = SemaRef.PerformImplicitConversion(Diff.get(), Type,
9036 /*AllowExplicit=*/true);
9037 if (!Diff.isUsable())
9038 return nullptr;
9039 }
9040 }
9041 if (LimitedType) {
9042 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
9043 if (NewSize != C.getTypeSize(Type)) {
9044 if (NewSize < C.getTypeSize(Type)) {
9045 assert(NewSize == 64 && "incorrect loop var size");
9046 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
9047 << InitSrcRange << ConditionSrcRange;
9048 }
9049 QualType NewType = C.getIntTypeForBitwidth(
9051 C.getTypeSize(Type) < NewSize);
9052 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
9053 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
9055 /*AllowExplicit=*/true);
9056 if (!Diff.isUsable())
9057 return nullptr;
9058 }
9059 }
9060 }
9061
9062 return Diff.get();
9063}
9064
9065std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9066 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9067 // Do not build for iterators, they cannot be used in non-rectangular loop
9068 // nests.
9069 if (LCDecl->getType()->isRecordType())
9070 return std::make_pair(nullptr, nullptr);
9071 // If we subtract, the min is in the condition, otherwise the min is in the
9072 // init value.
9073 Expr *MinExpr = nullptr;
9074 Expr *MaxExpr = nullptr;
9075 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9076 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9077 bool LBNonRect =
9078 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9079 bool UBNonRect =
9080 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9081 Expr *Lower =
9082 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
9083 Expr *Upper =
9084 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
9085 if (!Upper || !Lower)
9086 return std::make_pair(nullptr, nullptr);
9087
9088 if (*TestIsLessOp)
9089 MinExpr = Lower;
9090 else
9091 MaxExpr = Upper;
9092
9093 // Build minimum/maximum value based on number of iterations.
9094 QualType VarType = LCDecl->getType().getNonReferenceType();
9095
9096 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9097 Step, VarType, TestIsStrictOp,
9098 /*RoundToStep=*/false, Captures);
9099 if (!Diff.isUsable())
9100 return std::make_pair(nullptr, nullptr);
9101
9102 // ((Upper - Lower [- 1]) / Step) * Step
9103 // Parentheses (for dumping/debugging purposes only).
9104 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9105 if (!Diff.isUsable())
9106 return std::make_pair(nullptr, nullptr);
9107
9108 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
9109 if (!NewStep.isUsable())
9110 return std::make_pair(nullptr, nullptr);
9111 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
9112 if (!Diff.isUsable())
9113 return std::make_pair(nullptr, nullptr);
9114
9115 // Parentheses (for dumping/debugging purposes only).
9116 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9117 if (!Diff.isUsable())
9118 return std::make_pair(nullptr, nullptr);
9119
9120 // Convert to the ptrdiff_t, if original type is pointer.
9121 if (VarType->isAnyPointerType() &&
9122 !SemaRef.Context.hasSameType(
9123 Diff.get()->getType(),
9125 Diff = SemaRef.PerformImplicitConversion(
9126 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
9127 AssignmentAction::Converting, /*AllowExplicit=*/true);
9128 }
9129 if (!Diff.isUsable())
9130 return std::make_pair(nullptr, nullptr);
9131
9132 if (*TestIsLessOp) {
9133 // MinExpr = Lower;
9134 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
9135 Diff = SemaRef.BuildBinOp(
9136 S, DefaultLoc, BO_Add,
9137 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
9138 Diff.get());
9139 if (!Diff.isUsable())
9140 return std::make_pair(nullptr, nullptr);
9141 } else {
9142 // MaxExpr = Upper;
9143 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
9144 Diff = SemaRef.BuildBinOp(
9145 S, DefaultLoc, BO_Sub,
9146 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
9147 Diff.get());
9148 if (!Diff.isUsable())
9149 return std::make_pair(nullptr, nullptr);
9150 }
9151
9152 // Convert to the original type.
9153 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
9154 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
9156 /*AllowExplicit=*/true);
9157 if (!Diff.isUsable())
9158 return std::make_pair(nullptr, nullptr);
9159
9160 Sema::TentativeAnalysisScope Trap(SemaRef);
9161 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
9162 if (!Diff.isUsable())
9163 return std::make_pair(nullptr, nullptr);
9164
9165 if (*TestIsLessOp)
9166 MaxExpr = Diff.get();
9167 else
9168 MinExpr = Diff.get();
9169
9170 return std::make_pair(MinExpr, MaxExpr);
9171}
9172
9173Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
9174 if (InitDependOnLC || CondDependOnLC)
9175 return Condition;
9176 return nullptr;
9177}
9178
9179Expr *OpenMPIterationSpaceChecker::buildPreCond(
9180 Scope *S, Expr *Cond,
9181 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9182 // Do not build a precondition when the condition/initialization is dependent
9183 // to prevent pessimistic early loop exit.
9184 // TODO: this can be improved by calculating min/max values but not sure that
9185 // it will be very effective.
9186 if (CondDependOnLC || InitDependOnLC)
9187 return SemaRef
9189 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
9190 SemaRef.Context.BoolTy, /*Action=*/AssignmentAction::Casting,
9191 /*AllowExplicit=*/true)
9192 .get();
9193
9194 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
9195 Sema::TentativeAnalysisScope Trap(SemaRef);
9196
9197 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9198 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9199 if (!NewLB.isUsable() || !NewUB.isUsable())
9200 return nullptr;
9201
9202 ExprResult CondExpr =
9203 SemaRef.BuildBinOp(S, DefaultLoc,
9204 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9205 : (TestIsStrictOp ? BO_GT : BO_GE),
9206 NewLB.get(), NewUB.get());
9207 if (CondExpr.isUsable()) {
9208 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
9209 SemaRef.Context.BoolTy))
9210 CondExpr = SemaRef.PerformImplicitConversion(
9211 CondExpr.get(), SemaRef.Context.BoolTy,
9212 /*Action=*/AssignmentAction::Casting,
9213 /*AllowExplicit=*/true);
9214 }
9215
9216 // Otherwise use original loop condition and evaluate it in runtime.
9217 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9218}
9219
9220/// Build reference expression to the counter be used for codegen.
9221DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9222 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9223 DSAStackTy &DSA) const {
9224 auto *VD = dyn_cast<VarDecl>(LCDecl);
9225 if (!VD) {
9226 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(LCDecl);
9228 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
9229 const DSAStackTy::DSAVarData Data =
9230 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
9231 // If the loop control decl is explicitly marked as private, do not mark it
9232 // as captured again.
9233 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
9234 Captures.insert(std::make_pair(LCRef, Ref));
9235 return Ref;
9236 }
9237 return cast<DeclRefExpr>(LCRef);
9238}
9239
9240Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9241 if (LCDecl && !LCDecl->isInvalidDecl()) {
9243 VarDecl *PrivateVar = buildVarDecl(
9244 SemaRef, DefaultLoc, Type, LCDecl->getName(),
9245 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9246 isa<VarDecl>(LCDecl)
9247 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
9248 : nullptr);
9249 if (PrivateVar->isInvalidDecl())
9250 return nullptr;
9251 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
9252 }
9253 return nullptr;
9254}
9255
9256/// Build initialization of the counter to be used for codegen.
9257Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9258
9259/// Build step of the counter be used for codegen.
9260Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9261
9262Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9263 Scope *S, Expr *Counter,
9264 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9265 Expr *Inc, OverloadedOperatorKind OOK) {
9266 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
9267 if (!Cnt)
9268 return nullptr;
9269 if (Inc) {
9270 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9271 "Expected only + or - operations for depend clauses.");
9272 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9273 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
9274 if (!Cnt)
9275 return nullptr;
9276 }
9277 QualType VarType = LCDecl->getType().getNonReferenceType();
9278 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9279 !SemaRef.getLangOpts().CPlusPlus)
9280 return nullptr;
9281 // Upper - Lower
9282 Expr *Upper =
9283 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9284 Expr *Lower =
9285 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9286 if (!Upper || !Lower)
9287 return nullptr;
9288
9289 ExprResult Diff = calculateNumIters(
9290 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9291 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9292 if (!Diff.isUsable())
9293 return nullptr;
9294
9295 return Diff.get();
9296}
9297} // namespace
9298
9300 Stmt *Init) {
9301 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9302 assert(Init && "Expected loop in canonical form.");
9303 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9304 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9305 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
9306 return;
9307
9308 DSAStack->loopStart();
9310 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9311 *DSAStack, ForLoc, EmptyDeclSet);
9312 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9313 if (ValueDecl *D = ISC.getLoopDecl()) {
9314 auto *VD = dyn_cast<VarDecl>(D);
9315 DeclRefExpr *PrivateRef = nullptr;
9316 if (!VD) {
9318 VD = Private;
9319 } else {
9320 PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(),
9321 /*WithInit=*/false);
9322 VD = cast<VarDecl>(PrivateRef->getDecl());
9323 }
9324 }
9325 DSAStack->addLoopControlVariable(D, VD);
9326 const Decl *LD = DSAStack->getPossiblyLoopCounter();
9327 if (LD != D->getCanonicalDecl()) {
9328 DSAStack->resetPossibleLoopCounter();
9329 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9330 SemaRef.MarkDeclarationsReferencedInExpr(buildDeclRefExpr(
9331 SemaRef, const_cast<VarDecl *>(Var),
9332 Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
9333 /*RefersToCapture=*/true));
9334 }
9335 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9336 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9337 // associated for-loop of a simd construct with just one associated
9338 // for-loop may be listed in a linear clause with a constant-linear-step
9339 // that is the increment of the associated for-loop. The loop iteration
9340 // variable(s) in the associated for-loop(s) of a for or parallel for
9341 // construct may be listed in a private or lastprivate clause.
9342 DSAStackTy::DSAVarData DVar =
9343 DSAStack->getTopDSA(D, /*FromParent=*/false);
9344 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9345 // is declared in the loop and it is predetermined as a private.
9346 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9347 OpenMPClauseKind PredeterminedCKind =
9349 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9350 : OMPC_private;
9351 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
9352 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9353 };
9354 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9355 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9356 (getLangOpts().OpenMP <= 45 ||
9357 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9359 IsOpenMPTaskloopDirective(DKind) ||
9361 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9362 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9363 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9364 unsigned OMPVersion = getLangOpts().OpenMP;
9365 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9366 << getOpenMPClauseNameForDiag(DVar.CKind)
9367 << getOpenMPDirectiveName(DKind, OMPVersion)
9368 << getOpenMPClauseNameForDiag(PredeterminedCKind);
9369 if (DVar.RefExpr == nullptr)
9370 DVar.CKind = PredeterminedCKind;
9371 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
9372 } else if (LoopDeclRefExpr) {
9373 // Make the loop iteration variable private (for worksharing
9374 // constructs), linear (for simd directives with the only one
9375 // associated loop) or lastprivate (for simd directives with several
9376 // collapsed or ordered loops).
9377 if (DVar.CKind == OMPC_unknown)
9378 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9379 }
9380 }
9381 }
9382 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9383}
9384
9385namespace {
9386// Utility for OpenMP doacross clause kind
9387class OMPDoacrossKind {
9388public:
9389 bool isSource(const OMPDoacrossClause *C) {
9390 return C->getDependenceType() == OMPC_DOACROSS_source ||
9391 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9392 }
9393 bool isSink(const OMPDoacrossClause *C) {
9394 return C->getDependenceType() == OMPC_DOACROSS_sink;
9395 }
9396 bool isSinkIter(const OMPDoacrossClause *C) {
9397 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9398 }
9399};
9400} // namespace
9401/// Called on a for stmt to check and extract its iteration space
9402/// for further processing (such as collapsing).
9404 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9405 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9406 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9407 Expr *OrderedLoopCountExpr,
9408 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9410 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9411 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9412 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9413 // OpenMP [2.9.1, Canonical Loop Form]
9414 // for (init-expr; test-expr; incr-expr) structured-block
9415 // for (range-decl: range-expr) structured-block
9416 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9417 S = CanonLoop->getLoopStmt();
9418 auto *For = dyn_cast_or_null<ForStmt>(S);
9419 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9420 // Ranged for is supported only in OpenMP 5.0.
9421 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9422 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
9423 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9424 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9425 << getOpenMPDirectiveName(DKind, OMPVersion) << TotalNestedLoopCount
9426 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9427 if (TotalNestedLoopCount > 1) {
9428 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9429 SemaRef.Diag(DSA.getConstructLoc(),
9430 diag::note_omp_collapse_ordered_expr)
9431 << 2 << CollapseLoopCountExpr->getSourceRange()
9432 << OrderedLoopCountExpr->getSourceRange();
9433 else if (CollapseLoopCountExpr)
9434 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9435 diag::note_omp_collapse_ordered_expr)
9436 << 0 << CollapseLoopCountExpr->getSourceRange();
9437 else if (OrderedLoopCountExpr)
9438 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9439 diag::note_omp_collapse_ordered_expr)
9440 << 1 << OrderedLoopCountExpr->getSourceRange();
9441 }
9442 return true;
9443 }
9444 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9445 "No loop body.");
9446 // Postpone analysis in dependent contexts for ranged for loops.
9447 if (CXXFor && SemaRef.CurContext->isDependentContext())
9448 return false;
9449
9450 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9451 For ? For->getForLoc() : CXXFor->getForLoc(),
9452 CollapsedLoopVarDecls);
9453
9454 // Check init.
9455 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9456 if (ISC.checkAndSetInit(Init))
9457 return true;
9458
9459 bool HasErrors = false;
9460
9461 // Check loop variable's type.
9462 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9463 // OpenMP [2.6, Canonical Loop Form]
9464 // Var is one of the following:
9465 // A variable of signed or unsigned integer type.
9466 // For C++, a variable of a random access iterator type.
9467 // For C, a variable of a pointer type.
9468 QualType VarType = LCDecl->getType().getNonReferenceType();
9469 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9470 !VarType->isPointerType() &&
9471 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9472 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9473 << SemaRef.getLangOpts().CPlusPlus;
9474 HasErrors = true;
9475 }
9476
9477 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9478 // a Construct
9479 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9480 // parallel for construct is (are) private.
9481 // The loop iteration variable in the associated for-loop of a simd
9482 // construct with just one associated for-loop is linear with a
9483 // constant-linear-step that is the increment of the associated for-loop.
9484 // Exclude loop var from the list of variables with implicitly defined data
9485 // sharing attributes.
9486 VarsWithImplicitDSA.erase(LCDecl);
9487
9488 assert((isOpenMPLoopDirective(DKind) ||
9490 "DSA for non-loop vars");
9491
9492 // Check test-expr.
9493 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9494
9495 // Check incr-expr.
9496 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9497 }
9498
9499 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9500 return HasErrors;
9501
9502 // Build the loop's iteration space representation.
9503 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9504 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9505 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9506 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9512 Captures);
9513 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9514 ISC.buildCounterVar(Captures, DSA);
9515 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9516 ISC.buildPrivateCounterVar();
9517 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9518 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9519 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9520 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9521 ISC.getConditionSrcRange();
9522 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9523 ISC.getIncrementSrcRange();
9524 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9525 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9526 ISC.isStrictTestOp();
9527 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9528 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9529 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9530 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9531 ISC.buildFinalCondition(DSA.getCurScope());
9532 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9533 ISC.doesInitDependOnLC();
9534 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9535 ISC.doesCondDependOnLC();
9536 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9537 ISC.getLoopDependentIdx();
9538
9539 HasErrors |=
9540 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9541 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9542 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9543 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9544 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9545 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9546 if (!HasErrors && DSA.isOrderedRegion()) {
9547 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9548 if (CurrentNestedLoopCount <
9549 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9550 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9551 CurrentNestedLoopCount,
9552 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9553 DSA.getOrderedRegionParam().second->setLoopCounter(
9554 CurrentNestedLoopCount,
9555 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9556 }
9557 }
9558 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9559 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9560 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9561 unsigned NumLoops =
9562 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9563 if (CurrentNestedLoopCount >= NumLoops) {
9564 // Erroneous case - clause has some problems.
9565 continue;
9566 }
9567 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9568 Pair.second.size() <= CurrentNestedLoopCount) {
9569 // Erroneous case - clause has some problems.
9570 DependC->setLoopData(CurrentNestedLoopCount, nullptr);
9571 continue;
9572 }
9573 OMPDoacrossKind ODK;
9574 if (DoacrossC && ODK.isSink(DoacrossC) &&
9575 Pair.second.size() <= CurrentNestedLoopCount) {
9576 // Erroneous case - clause has some problems.
9577 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
9578 continue;
9579 }
9580 Expr *CntValue;
9581 SourceLocation DepLoc =
9582 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9583 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9584 (DoacrossC && ODK.isSource(DoacrossC)))
9585 CntValue = ISC.buildOrderedLoopData(
9586 DSA.getCurScope(),
9587 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9588 DepLoc);
9589 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9590 Expr *Cnt = SemaRef
9592 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9593 .get();
9594 if (!Cnt)
9595 continue;
9596 // build CounterVar - 1
9597 Expr *Inc =
9598 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
9599 .get();
9600 CntValue = ISC.buildOrderedLoopData(
9601 DSA.getCurScope(),
9602 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9603 DepLoc, Inc, clang::OO_Minus);
9604 } else
9605 CntValue = ISC.buildOrderedLoopData(
9606 DSA.getCurScope(),
9607 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9608 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9609 Pair.second[CurrentNestedLoopCount].second);
9610 if (DependC)
9611 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9612 else
9613 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9614 }
9615 }
9616
9617 return HasErrors;
9618}
9619
9620/// Build 'VarRef = Start.
9621static ExprResult
9623 ExprResult Start, bool IsNonRectangularLB,
9624 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9625 // Build 'VarRef = Start.
9626 ExprResult NewStart = IsNonRectangularLB
9627 ? Start.get()
9628 : tryBuildCapture(SemaRef, Start.get(), Captures);
9629 if (!NewStart.isUsable())
9630 return ExprError();
9631 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9632 VarRef.get()->getType())) {
9633 NewStart = SemaRef.PerformImplicitConversion(
9634 NewStart.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9635 /*AllowExplicit=*/true);
9636 if (!NewStart.isUsable())
9637 return ExprError();
9638 }
9639
9641 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9642 return Init;
9643}
9644
9645/// Build 'VarRef = Start + Iter * Step'.
9647 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9648 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9649 bool IsNonRectangularLB,
9650 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9651 // Add parentheses (for debugging purposes only).
9652 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9653 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9654 !Step.isUsable())
9655 return ExprError();
9656
9657 ExprResult NewStep = Step;
9658 if (Captures)
9659 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9660 if (NewStep.isInvalid())
9661 return ExprError();
9663 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9664 if (!Update.isUsable())
9665 return ExprError();
9666
9667 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9668 // 'VarRef = Start (+|-) Iter * Step'.
9669 if (!Start.isUsable())
9670 return ExprError();
9671 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9672 if (!NewStart.isUsable())
9673 return ExprError();
9674 if (Captures && !IsNonRectangularLB)
9675 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9676 if (NewStart.isInvalid())
9677 return ExprError();
9678
9679 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9680 ExprResult SavedUpdate = Update;
9681 ExprResult UpdateVal;
9682 if (VarRef.get()->getType()->isOverloadableType() ||
9683 NewStart.get()->getType()->isOverloadableType() ||
9684 Update.get()->getType()->isOverloadableType()) {
9685 Sema::TentativeAnalysisScope Trap(SemaRef);
9686
9687 Update =
9688 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9689 if (Update.isUsable()) {
9690 UpdateVal =
9691 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9692 VarRef.get(), SavedUpdate.get());
9693 if (UpdateVal.isUsable()) {
9694 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9695 UpdateVal.get());
9696 }
9697 }
9698 }
9699
9700 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9701 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9702 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9703 NewStart.get(), SavedUpdate.get());
9704 if (!Update.isUsable())
9705 return ExprError();
9706
9707 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9708 VarRef.get()->getType())) {
9710 Update.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9711 /*AllowExplicit=*/true);
9712 if (!Update.isUsable())
9713 return ExprError();
9714 }
9715
9716 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9717 }
9718 return Update;
9719}
9720
9721/// Convert integer expression \a E to make it have at least \a Bits
9722/// bits.
9723static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9724 if (E == nullptr)
9725 return ExprError();
9726 ASTContext &C = SemaRef.Context;
9727 QualType OldType = E->getType();
9728 unsigned HasBits = C.getTypeSize(OldType);
9729 if (HasBits >= Bits)
9730 return ExprResult(E);
9731 // OK to convert to signed, because new type has more bits than old.
9732 QualType NewType = C.getIntTypeForBitwidth(Bits, /*Signed=*/true);
9733 return SemaRef.PerformImplicitConversion(
9734 E, NewType, AssignmentAction::Converting, /*AllowExplicit=*/true);
9735}
9736
9737/// Check if the given expression \a E is a constant integer that fits
9738/// into \a Bits bits.
9739static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9740 if (E == nullptr)
9741 return false;
9742 if (std::optional<llvm::APSInt> Result =
9743 E->getIntegerConstantExpr(SemaRef.Context))
9744 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9745 return false;
9746}
9747
9748/// Build preinits statement for the given declarations.
9750 MutableArrayRef<Decl *> PreInits) {
9751 if (!PreInits.empty()) {
9752 return new (Context) DeclStmt(
9753 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9755 }
9756 return nullptr;
9757}
9758
9759/// Append the \p Item or the content of a CompoundStmt to the list \p
9760/// TargetList.
9761///
9762/// A CompoundStmt is used as container in case multiple statements need to be
9763/// stored in lieu of using an explicit list. Flattening is necessary because
9764/// contained DeclStmts need to be visible after the execution of the list. Used
9765/// for OpenMP pre-init declarations/statements.
9767 Stmt *Item) {
9768 // nullptr represents an empty list.
9769 if (!Item)
9770 return;
9771
9772 if (auto *CS = dyn_cast<CompoundStmt>(Item))
9773 llvm::append_range(TargetList, CS->body());
9774 else
9775 TargetList.push_back(Item);
9776}
9777
9778/// Build preinits statement for the given declarations.
9779static Stmt *
9781 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9782 if (!Captures.empty()) {
9783 SmallVector<Decl *, 16> PreInits;
9784 for (const auto &Pair : Captures)
9785 PreInits.push_back(Pair.second->getDecl());
9786 return buildPreInits(Context, PreInits);
9787 }
9788 return nullptr;
9789}
9790
9791/// Build pre-init statement for the given statements.
9792static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
9793 if (PreInits.empty())
9794 return nullptr;
9795
9796 SmallVector<Stmt *> Stmts;
9797 for (Stmt *S : PreInits)
9798 appendFlattenedStmtList(Stmts, S);
9799 return CompoundStmt::Create(Context, PreInits, FPOptionsOverride(), {}, {});
9800}
9801
9802/// Build postupdate expression for the given list of postupdates expressions.
9803static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9804 Expr *PostUpdate = nullptr;
9805 if (!PostUpdates.empty()) {
9806 for (Expr *E : PostUpdates) {
9807 Expr *ConvE = S.BuildCStyleCastExpr(
9808 E->getExprLoc(),
9810 E->getExprLoc(), E)
9811 .get();
9812 PostUpdate = PostUpdate
9813 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9814 PostUpdate, ConvE)
9815 .get()
9816 : ConvE;
9817 }
9818 }
9819 return PostUpdate;
9820}
9821
9822/// Look for variables declared in the body parts of a for-loop nest. Used
9823/// for verifying loop nest structure before performing a loop collapse
9824/// operation.
9826 int NestingDepth = 0;
9827 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9828
9829public:
9830 explicit ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl *> &VD)
9831 : VarDecls(VD) {}
9832
9833 bool VisitForStmt(ForStmt *F) override {
9834 ++NestingDepth;
9835 TraverseStmt(F->getBody());
9836 --NestingDepth;
9837 return false;
9838 }
9839
9841 ++NestingDepth;
9842 TraverseStmt(RF->getBody());
9843 --NestingDepth;
9844 return false;
9845 }
9846
9847 bool VisitVarDecl(VarDecl *D) override {
9848 Decl *C = D->getCanonicalDecl();
9849 if (NestingDepth > 0)
9850 VarDecls.insert(C);
9851 return true;
9852 }
9853};
9854
9855/// Called on a for stmt to check itself and nested loops (if any).
9856/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9857/// number of collapsed loops otherwise.
9858static unsigned
9859checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9860 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9861 DSAStackTy &DSA,
9862 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9863 OMPLoopBasedDirective::HelperExprs &Built) {
9864 // If either of the loop expressions exist and contain errors, we bail out
9865 // early because diagnostics have already been emitted and we can't reliably
9866 // check more about the loop.
9867 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->containsErrors()) ||
9868 (OrderedLoopCountExpr && OrderedLoopCountExpr->containsErrors()))
9869 return 0;
9870
9871 unsigned NestedLoopCount = 1;
9872 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9874 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopVarDecls;
9875
9876 if (CollapseLoopCountExpr) {
9877 // Found 'collapse' clause - calculate collapse number.
9878 Expr::EvalResult Result;
9879 if (!CollapseLoopCountExpr->isValueDependent() &&
9880 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9881 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9882
9883 ForVarDeclFinder FVDF{CollapsedLoopVarDecls};
9884 FVDF.TraverseStmt(AStmt);
9885 } else {
9886 Built.clear(/*Size=*/1);
9887 return 1;
9888 }
9889 }
9890 unsigned OrderedLoopCount = 1;
9891 if (OrderedLoopCountExpr) {
9892 // Found 'ordered' clause - calculate collapse number.
9893 Expr::EvalResult EVResult;
9894 if (!OrderedLoopCountExpr->isValueDependent() &&
9895 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9896 SemaRef.getASTContext())) {
9897 llvm::APSInt Result = EVResult.Val.getInt();
9898 if (Result.getLimitedValue() < NestedLoopCount) {
9899 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9900 diag::err_omp_wrong_ordered_loop_count)
9901 << OrderedLoopCountExpr->getSourceRange();
9902 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9903 diag::note_collapse_loop_count)
9904 << CollapseLoopCountExpr->getSourceRange();
9905 }
9906 OrderedLoopCount = Result.getLimitedValue();
9907 } else {
9908 Built.clear(/*Size=*/1);
9909 return 1;
9910 }
9911 }
9912 // This is helper routine for loop directives (e.g., 'for', 'simd',
9913 // 'for simd', etc.).
9914 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9915 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9916 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9917 if (!OMPLoopBasedDirective::doForAllLoops(
9918 AStmt->IgnoreContainers(
9920 SupportsNonPerfectlyNested, NumLoops,
9921 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9922 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9923 &IterSpaces, &Captures,
9924 &CollapsedLoopVarDecls](unsigned Cnt, Stmt *CurStmt) {
9926 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9927 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9928 VarsWithImplicitDSA, IterSpaces, Captures,
9929 CollapsedLoopVarDecls))
9930 return true;
9931 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9932 IterSpaces[Cnt].CounterVar) {
9933 // Handle initialization of captured loop iterator variables.
9934 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9935 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9936 Captures[DRE] = DRE;
9937 }
9938 }
9939 return false;
9940 },
9941 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9942 Stmt *DependentPreInits = Transform->getPreInits();
9943 if (!DependentPreInits)
9944 return;
9945
9946 // Search for pre-init declared variables that need to be captured
9947 // to be referenceable inside the directive.
9948 SmallVector<Stmt *> Constituents;
9949 appendFlattenedStmtList(Constituents, DependentPreInits);
9950 for (Stmt *S : Constituents) {
9951 if (auto *DC = dyn_cast<DeclStmt>(S)) {
9952 for (Decl *C : DC->decls()) {
9953 auto *D = cast<VarDecl>(C);
9955 SemaRef, D, D->getType().getNonReferenceType(),
9956 cast<OMPExecutableDirective>(Transform->getDirective())
9957 ->getBeginLoc());
9958 Captures[Ref] = Ref;
9959 }
9960 }
9961 }
9962 }))
9963 return 0;
9964
9965 Built.clear(/*size=*/NestedLoopCount);
9966
9967 if (SemaRef.CurContext->isDependentContext())
9968 return NestedLoopCount;
9969
9970 // An example of what is generated for the following code:
9971 //
9972 // #pragma omp simd collapse(2) ordered(2)
9973 // for (i = 0; i < NI; ++i)
9974 // for (k = 0; k < NK; ++k)
9975 // for (j = J0; j < NJ; j+=2) {
9976 // <loop body>
9977 // }
9978 //
9979 // We generate the code below.
9980 // Note: the loop body may be outlined in CodeGen.
9981 // Note: some counters may be C++ classes, operator- is used to find number of
9982 // iterations and operator+= to calculate counter value.
9983 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9984 // or i64 is currently supported).
9985 //
9986 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9987 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9988 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9989 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9990 // // similar updates for vars in clauses (e.g. 'linear')
9991 // <loop body (using local i and j)>
9992 // }
9993 // i = NI; // assign final values of counters
9994 // j = NJ;
9995 //
9996
9997 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9998 // the iteration counts of the collapsed for loops.
9999 // Precondition tests if there is at least one iteration (all conditions are
10000 // true).
10001 auto PreCond = ExprResult(IterSpaces[0].PreCond);
10002 Expr *N0 = IterSpaces[0].NumIterations;
10003 ExprResult LastIteration32 = widenIterationCount(
10004 /*Bits=*/32,
10005 SemaRef
10006 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
10008 /*AllowExplicit=*/true)
10009 .get(),
10010 SemaRef);
10011 ExprResult LastIteration64 = widenIterationCount(
10012 /*Bits=*/64,
10013 SemaRef
10014 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
10016 /*AllowExplicit=*/true)
10017 .get(),
10018 SemaRef);
10019
10020 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
10021 return NestedLoopCount;
10022
10023 ASTContext &C = SemaRef.Context;
10024 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
10025
10026 Scope *CurScope = DSA.getCurScope();
10027 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
10028 if (PreCond.isUsable()) {
10029 PreCond =
10030 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
10031 PreCond.get(), IterSpaces[Cnt].PreCond);
10032 }
10033 Expr *N = IterSpaces[Cnt].NumIterations;
10034 SourceLocation Loc = N->getExprLoc();
10035 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
10036 if (LastIteration32.isUsable())
10037 LastIteration32 = SemaRef.BuildBinOp(
10038 CurScope, Loc, BO_Mul, LastIteration32.get(),
10039 SemaRef
10042 /*AllowExplicit=*/true)
10043 .get());
10044 if (LastIteration64.isUsable())
10045 LastIteration64 = SemaRef.BuildBinOp(
10046 CurScope, Loc, BO_Mul, LastIteration64.get(),
10047 SemaRef
10050 /*AllowExplicit=*/true)
10051 .get());
10052 }
10053
10054 // Choose either the 32-bit or 64-bit version.
10055 ExprResult LastIteration = LastIteration64;
10056 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
10057 (LastIteration32.isUsable() &&
10058 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
10059 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
10060 fitsInto(
10061 /*Bits=*/32,
10062 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
10063 LastIteration64.get(), SemaRef))))
10064 LastIteration = LastIteration32;
10065 QualType VType = LastIteration.get()->getType();
10066 QualType RealVType = VType;
10067 QualType StrideVType = VType;
10068 if (isOpenMPTaskLoopDirective(DKind)) {
10069 VType =
10070 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
10071 StrideVType =
10072 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
10073 }
10074
10075 if (!LastIteration.isUsable())
10076 return 0;
10077
10078 // Save the number of iterations.
10079 ExprResult NumIterations = LastIteration;
10080 {
10081 LastIteration = SemaRef.BuildBinOp(
10082 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
10083 LastIteration.get(),
10084 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
10085 if (!LastIteration.isUsable())
10086 return 0;
10087 }
10088
10089 // Calculate the last iteration number beforehand instead of doing this on
10090 // each iteration. Do not do this if the number of iterations may be kfold-ed.
10091 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
10092 ExprResult CalcLastIteration;
10093 if (!IsConstant) {
10094 ExprResult SaveRef =
10095 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
10096 LastIteration = SaveRef;
10097
10098 // Prepare SaveRef + 1.
10099 NumIterations = SemaRef.BuildBinOp(
10100 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
10101 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
10102 if (!NumIterations.isUsable())
10103 return 0;
10104 }
10105
10106 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
10107
10108 // Build variables passed into runtime, necessary for worksharing directives.
10109 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
10114 // Lower bound variable, initialized with zero.
10115 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
10116 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
10117 SemaRef.AddInitializerToDecl(LBDecl,
10118 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10119 /*DirectInit=*/false);
10120
10121 // Upper bound variable, initialized with last iteration number.
10122 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
10123 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
10124 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
10125 /*DirectInit=*/false);
10126
10127 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
10128 // This will be used to implement clause 'lastprivate'.
10129 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
10130 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
10131 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
10132 SemaRef.AddInitializerToDecl(ILDecl,
10133 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10134 /*DirectInit=*/false);
10135
10136 // Stride variable returned by runtime (we initialize it to 1 by default).
10137 VarDecl *STDecl =
10138 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
10139 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
10140 SemaRef.AddInitializerToDecl(STDecl,
10141 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
10142 /*DirectInit=*/false);
10143
10144 // Build expression: UB = min(UB, LastIteration)
10145 // It is necessary for CodeGen of directives with static scheduling.
10146 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
10147 UB.get(), LastIteration.get());
10148 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10149 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
10150 LastIteration.get(), UB.get());
10151 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
10152 CondOp.get());
10153 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue=*/false);
10154
10155 // If we have a combined directive that combines 'distribute', 'for' or
10156 // 'simd' we need to be able to access the bounds of the schedule of the
10157 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
10158 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
10160 // Lower bound variable, initialized with zero.
10161 VarDecl *CombLBDecl =
10162 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
10163 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
10164 SemaRef.AddInitializerToDecl(
10165 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10166 /*DirectInit=*/false);
10167
10168 // Upper bound variable, initialized with last iteration number.
10169 VarDecl *CombUBDecl =
10170 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
10171 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
10172 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
10173 /*DirectInit=*/false);
10174
10175 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
10176 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
10177 ExprResult CombCondOp =
10178 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
10179 LastIteration.get(), CombUB.get());
10180 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
10181 CombCondOp.get());
10182 CombEUB =
10183 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue=*/false);
10184
10185 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
10186 // We expect to have at least 2 more parameters than the 'parallel'
10187 // directive does - the lower and upper bounds of the previous schedule.
10188 assert(CD->getNumParams() >= 4 &&
10189 "Unexpected number of parameters in loop combined directive");
10190
10191 // Set the proper type for the bounds given what we learned from the
10192 // enclosed loops.
10193 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
10194 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
10195
10196 // Previous lower and upper bounds are obtained from the region
10197 // parameters.
10198 PrevLB =
10199 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
10200 PrevUB =
10201 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
10202 }
10203 }
10204
10205 // Build the iteration variable and its initialization before loop.
10206 ExprResult IV;
10207 ExprResult Init, CombInit;
10208 {
10209 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
10210 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
10211 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
10216 ? LB.get()
10217 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10218 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
10219 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue=*/false);
10220
10222 Expr *CombRHS =
10227 ? CombLB.get()
10228 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10229 CombInit =
10230 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
10231 CombInit =
10232 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue=*/false);
10233 }
10234 }
10235
10236 bool UseStrictCompare =
10237 RealVType->hasUnsignedIntegerRepresentation() &&
10238 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
10239 return LIS.IsStrictCompare;
10240 });
10241 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10242 // unsigned IV)) for worksharing loops.
10243 SourceLocation CondLoc = AStmt->getBeginLoc();
10244 Expr *BoundUB = UB.get();
10245 if (UseStrictCompare) {
10246 BoundUB =
10247 SemaRef
10248 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10249 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10250 .get();
10251 BoundUB =
10252 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue=*/false).get();
10253 }
10259 ? SemaRef.BuildBinOp(CurScope, CondLoc,
10260 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
10261 BoundUB)
10262 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10263 NumIterations.get());
10264 ExprResult CombDistCond;
10266 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10267 NumIterations.get());
10268 }
10269
10270 ExprResult CombCond;
10272 Expr *BoundCombUB = CombUB.get();
10273 if (UseStrictCompare) {
10274 BoundCombUB =
10275 SemaRef
10276 .BuildBinOp(
10277 CurScope, CondLoc, BO_Add, BoundCombUB,
10278 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10279 .get();
10280 BoundCombUB =
10281 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue=*/false)
10282 .get();
10283 }
10284 CombCond =
10285 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10286 IV.get(), BoundCombUB);
10287 }
10288 // Loop increment (IV = IV + 1)
10289 SourceLocation IncLoc = AStmt->getBeginLoc();
10290 ExprResult Inc =
10291 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
10292 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
10293 if (!Inc.isUsable())
10294 return 0;
10295 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
10296 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue=*/false);
10297 if (!Inc.isUsable())
10298 return 0;
10299
10300 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10301 // Used for directives with static scheduling.
10302 // In combined construct, add combined version that use CombLB and CombUB
10303 // base variables for the update
10304 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10309 // LB + ST
10310 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
10311 if (!NextLB.isUsable())
10312 return 0;
10313 // LB = LB + ST
10314 NextLB =
10315 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
10316 NextLB =
10317 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue=*/false);
10318 if (!NextLB.isUsable())
10319 return 0;
10320 // UB + ST
10321 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
10322 if (!NextUB.isUsable())
10323 return 0;
10324 // UB = UB + ST
10325 NextUB =
10326 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
10327 NextUB =
10328 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue=*/false);
10329 if (!NextUB.isUsable())
10330 return 0;
10332 CombNextLB =
10333 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
10334 if (!NextLB.isUsable())
10335 return 0;
10336 // LB = LB + ST
10337 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
10338 CombNextLB.get());
10339 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
10340 /*DiscardedValue=*/false);
10341 if (!CombNextLB.isUsable())
10342 return 0;
10343 // UB + ST
10344 CombNextUB =
10345 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
10346 if (!CombNextUB.isUsable())
10347 return 0;
10348 // UB = UB + ST
10349 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
10350 CombNextUB.get());
10351 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
10352 /*DiscardedValue=*/false);
10353 if (!CombNextUB.isUsable())
10354 return 0;
10355 }
10356 }
10357
10358 // Create increment expression for distribute loop when combined in a same
10359 // directive with for as IV = IV + ST; ensure upper bound expression based
10360 // on PrevUB instead of NumIterations - used to implement 'for' when found
10361 // in combination with 'distribute', like in 'distribute parallel for'
10362 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10363 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10365 DistCond = SemaRef.BuildBinOp(
10366 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10367 assert(DistCond.isUsable() && "distribute cond expr was not built");
10368
10369 DistInc =
10370 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10371 assert(DistInc.isUsable() && "distribute inc expr was not built");
10372 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10373 DistInc.get());
10374 DistInc =
10375 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue=*/false);
10376 assert(DistInc.isUsable() && "distribute inc expr was not built");
10377
10378 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10379 // construct
10380 ExprResult NewPrevUB = PrevUB;
10381 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10382 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10383 PrevUB.get()->getType())) {
10384 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10385 DistEUBLoc,
10387 DistEUBLoc, NewPrevUB.get());
10388 if (!NewPrevUB.isUsable())
10389 return 0;
10390 }
10391 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10392 UB.get(), NewPrevUB.get());
10393 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10394 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10395 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10396 CondOp.get());
10397 PrevEUB =
10398 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue=*/false);
10399
10400 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10401 // parallel for is in combination with a distribute directive with
10402 // schedule(static, 1)
10403 Expr *BoundPrevUB = PrevUB.get();
10404 if (UseStrictCompare) {
10405 BoundPrevUB =
10406 SemaRef
10407 .BuildBinOp(
10408 CurScope, CondLoc, BO_Add, BoundPrevUB,
10409 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10410 .get();
10411 BoundPrevUB =
10412 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue=*/false)
10413 .get();
10414 }
10415 ParForInDistCond =
10416 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10417 IV.get(), BoundPrevUB);
10418 }
10419
10420 // Build updates and final values of the loop counters.
10421 bool HasErrors = false;
10422 Built.Counters.resize(NestedLoopCount);
10423 Built.Inits.resize(NestedLoopCount);
10424 Built.Updates.resize(NestedLoopCount);
10425 Built.Finals.resize(NestedLoopCount);
10426 Built.DependentCounters.resize(NestedLoopCount);
10427 Built.DependentInits.resize(NestedLoopCount);
10428 Built.FinalsConditions.resize(NestedLoopCount);
10429 {
10430 // We implement the following algorithm for obtaining the
10431 // original loop iteration variable values based on the
10432 // value of the collapsed loop iteration variable IV.
10433 //
10434 // Let n+1 be the number of collapsed loops in the nest.
10435 // Iteration variables (I0, I1, .... In)
10436 // Iteration counts (N0, N1, ... Nn)
10437 //
10438 // Acc = IV;
10439 //
10440 // To compute Ik for loop k, 0 <= k <= n, generate:
10441 // Prod = N(k+1) * N(k+2) * ... * Nn;
10442 // Ik = Acc / Prod;
10443 // Acc -= Ik * Prod;
10444 //
10445 ExprResult Acc = IV;
10446 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10447 LoopIterationSpace &IS = IterSpaces[Cnt];
10448 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10449 ExprResult Iter;
10450
10451 // Compute prod
10452 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10453 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10454 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10455 IterSpaces[K].NumIterations);
10456
10457 // Iter = Acc / Prod
10458 // If there is at least one more inner loop to avoid
10459 // multiplication by 1.
10460 if (Cnt + 1 < NestedLoopCount)
10461 Iter =
10462 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10463 else
10464 Iter = Acc;
10465 if (!Iter.isUsable()) {
10466 HasErrors = true;
10467 break;
10468 }
10469
10470 // Update Acc:
10471 // Acc -= Iter * Prod
10472 // Check if there is at least one more inner loop to avoid
10473 // multiplication by 1.
10474 if (Cnt + 1 < NestedLoopCount)
10475 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10476 Prod.get());
10477 else
10478 Prod = Iter;
10479 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10480
10481 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10482 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10483 DeclRefExpr *CounterVar = buildDeclRefExpr(
10484 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10485 /*RefersToCapture=*/true);
10487 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10488 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10489 if (!Init.isUsable()) {
10490 HasErrors = true;
10491 break;
10492 }
10494 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10495 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10496 if (!Update.isUsable()) {
10497 HasErrors = true;
10498 break;
10499 }
10500
10501 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10502 ExprResult Final =
10503 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10504 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10505 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10506 if (!Final.isUsable()) {
10507 HasErrors = true;
10508 break;
10509 }
10510
10511 if (!Update.isUsable() || !Final.isUsable()) {
10512 HasErrors = true;
10513 break;
10514 }
10515 // Save results
10516 Built.Counters[Cnt] = IS.CounterVar;
10517 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10518 Built.Inits[Cnt] = Init.get();
10519 Built.Updates[Cnt] = Update.get();
10520 Built.Finals[Cnt] = Final.get();
10521 Built.DependentCounters[Cnt] = nullptr;
10522 Built.DependentInits[Cnt] = nullptr;
10523 Built.FinalsConditions[Cnt] = nullptr;
10524 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10525 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10526 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10527 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10528 }
10529 }
10530 }
10531
10532 if (HasErrors)
10533 return 0;
10534
10535 // Save results
10536 Built.IterationVarRef = IV.get();
10537 Built.LastIteration = LastIteration.get();
10538 Built.NumIterations = NumIterations.get();
10539 Built.CalcLastIteration = SemaRef
10540 .ActOnFinishFullExpr(CalcLastIteration.get(),
10541 /*DiscardedValue=*/false)
10542 .get();
10543 Built.PreCond = PreCond.get();
10544 Built.PreInits = buildPreInits(C, Captures);
10545 Built.Cond = Cond.get();
10546 Built.Init = Init.get();
10547 Built.Inc = Inc.get();
10548 Built.LB = LB.get();
10549 Built.UB = UB.get();
10550 Built.IL = IL.get();
10551 Built.ST = ST.get();
10552 Built.EUB = EUB.get();
10553 Built.NLB = NextLB.get();
10554 Built.NUB = NextUB.get();
10555 Built.PrevLB = PrevLB.get();
10556 Built.PrevUB = PrevUB.get();
10557 Built.DistInc = DistInc.get();
10558 Built.PrevEUB = PrevEUB.get();
10559 Built.DistCombinedFields.LB = CombLB.get();
10560 Built.DistCombinedFields.UB = CombUB.get();
10561 Built.DistCombinedFields.EUB = CombEUB.get();
10562 Built.DistCombinedFields.Init = CombInit.get();
10563 Built.DistCombinedFields.Cond = CombCond.get();
10564 Built.DistCombinedFields.NLB = CombNextLB.get();
10565 Built.DistCombinedFields.NUB = CombNextUB.get();
10566 Built.DistCombinedFields.DistCond = CombDistCond.get();
10567 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10568
10569 return NestedLoopCount;
10570}
10571
10573 auto CollapseClauses =
10574 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10575 if (CollapseClauses.begin() != CollapseClauses.end())
10576 return (*CollapseClauses.begin())->getNumForLoops();
10577 return nullptr;
10578}
10579
10581 auto OrderedClauses =
10582 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10583 if (OrderedClauses.begin() != OrderedClauses.end())
10584 return (*OrderedClauses.begin())->getNumForLoops();
10585 return nullptr;
10586}
10587
10589 const ArrayRef<OMPClause *> Clauses) {
10590 const OMPSafelenClause *Safelen = nullptr;
10591 const OMPSimdlenClause *Simdlen = nullptr;
10592
10593 for (const OMPClause *Clause : Clauses) {
10594 if (Clause->getClauseKind() == OMPC_safelen)
10595 Safelen = cast<OMPSafelenClause>(Clause);
10596 else if (Clause->getClauseKind() == OMPC_simdlen)
10597 Simdlen = cast<OMPSimdlenClause>(Clause);
10598 if (Safelen && Simdlen)
10599 break;
10600 }
10601
10602 if (Simdlen && Safelen) {
10603 const Expr *SimdlenLength = Simdlen->getSimdlen();
10604 const Expr *SafelenLength = Safelen->getSafelen();
10605 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10606 SimdlenLength->isInstantiationDependent() ||
10607 SimdlenLength->containsUnexpandedParameterPack())
10608 return false;
10609 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10610 SafelenLength->isInstantiationDependent() ||
10611 SafelenLength->containsUnexpandedParameterPack())
10612 return false;
10613 Expr::EvalResult SimdlenResult, SafelenResult;
10614 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10615 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10616 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10617 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10618 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10619 // If both simdlen and safelen clauses are specified, the value of the
10620 // simdlen parameter must be less than or equal to the value of the safelen
10621 // parameter.
10622 if (SimdlenRes > SafelenRes) {
10623 S.Diag(SimdlenLength->getExprLoc(),
10624 diag::err_omp_wrong_simdlen_safelen_values)
10625 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10626 return true;
10627 }
10628 }
10629 return false;
10630}
10631
10633 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10634 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10635 if (!AStmt)
10636 return StmtError();
10637
10638 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_simd, AStmt);
10639
10640 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10641 OMPLoopBasedDirective::HelperExprs B;
10642 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10643 // define the nested loops number.
10644 unsigned NestedLoopCount = checkOpenMPLoop(
10645 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10646 CS, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10647 if (NestedLoopCount == 0)
10648 return StmtError();
10649
10650 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10651 return StmtError();
10652
10654 return StmtError();
10655
10656 auto *SimdDirective = OMPSimdDirective::Create(
10657 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10658 return SimdDirective;
10659}
10660
10662 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10663 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10664 if (!AStmt)
10665 return StmtError();
10666
10667 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10668 OMPLoopBasedDirective::HelperExprs B;
10669 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10670 // define the nested loops number.
10671 unsigned NestedLoopCount = checkOpenMPLoop(
10672 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10673 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10674 if (NestedLoopCount == 0)
10675 return StmtError();
10676
10677 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10678 return StmtError();
10679
10680 auto *ForDirective = OMPForDirective::Create(
10681 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10682 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10683 return ForDirective;
10684}
10685
10687 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10688 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10689 if (!AStmt)
10690 return StmtError();
10691
10692 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_for_simd, AStmt);
10693
10694 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10695 OMPLoopBasedDirective::HelperExprs B;
10696 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10697 // define the nested loops number.
10698 unsigned NestedLoopCount =
10699 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10700 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10701 VarsWithImplicitDSA, B);
10702 if (NestedLoopCount == 0)
10703 return StmtError();
10704
10705 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10706 return StmtError();
10707
10709 return StmtError();
10710
10711 return OMPForSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
10712 NestedLoopCount, Clauses, AStmt, B);
10713}
10714
10716 Stmt *AStmt, DSAStackTy *Stack) {
10717 if (!AStmt)
10718 return true;
10719
10720 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10721 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
10722 auto BaseStmt = AStmt;
10723 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10724 BaseStmt = CS->getCapturedStmt();
10725 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10726 auto S = C->children();
10727 if (S.begin() == S.end())
10728 return true;
10729 // All associated statements must be '#pragma omp section' except for
10730 // the first one.
10731 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10732 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10733 if (SectionStmt)
10734 SemaRef.Diag(SectionStmt->getBeginLoc(),
10735 diag::err_omp_sections_substmt_not_section)
10736 << getOpenMPDirectiveName(DKind, OMPVersion);
10737 return true;
10738 }
10739 cast<OMPSectionDirective>(SectionStmt)
10740 ->setHasCancel(Stack->isCancelRegion());
10741 }
10742 } else {
10743 SemaRef.Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10744 << getOpenMPDirectiveName(DKind, OMPVersion);
10745 return true;
10746 }
10747 return false;
10748}
10749
10752 Stmt *AStmt, SourceLocation StartLoc,
10753 SourceLocation EndLoc) {
10754 if (checkSectionsDirective(SemaRef, OMPD_sections, AStmt, DSAStack))
10755 return StmtError();
10756
10757 SemaRef.setFunctionHasBranchProtectedScope();
10758
10759 return OMPSectionsDirective::Create(
10760 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10761 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10762}
10763
10765 SourceLocation StartLoc,
10766 SourceLocation EndLoc) {
10767 if (!AStmt)
10768 return StmtError();
10769
10770 SemaRef.setFunctionHasBranchProtectedScope();
10771 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10772
10773 return OMPSectionDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt,
10774 DSAStack->isCancelRegion());
10775}
10776
10778 E = E->IgnoreParenCasts()->IgnoreImplicit();
10779 if (auto *CE = dyn_cast<CallExpr>(E))
10780 if (CE->getDirectCallee())
10781 return E;
10782 return nullptr;
10783}
10784
10787 Stmt *AStmt, SourceLocation StartLoc,
10788 SourceLocation EndLoc) {
10789 if (!AStmt)
10790 return StmtError();
10791
10792 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10793
10794 // 5.1 OpenMP
10795 // expression-stmt : an expression statement with one of the following forms:
10796 // expression = target-call ( [expression-list] );
10797 // target-call ( [expression-list] );
10798
10799 SourceLocation TargetCallLoc;
10800
10801 if (!SemaRef.CurContext->isDependentContext()) {
10802 Expr *TargetCall = nullptr;
10803
10804 auto *E = dyn_cast<Expr>(S);
10805 if (!E) {
10806 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10807 return StmtError();
10808 }
10809
10810 E = E->IgnoreParenCasts()->IgnoreImplicit();
10811
10812 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10813 if (BO->getOpcode() == BO_Assign)
10814 TargetCall = getDirectCallExpr(BO->getRHS());
10815 } else {
10816 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10817 if (COCE->getOperator() == OO_Equal)
10818 TargetCall = getDirectCallExpr(COCE->getArg(1));
10819 if (!TargetCall)
10820 TargetCall = getDirectCallExpr(E);
10821 }
10822 if (!TargetCall) {
10823 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10824 return StmtError();
10825 }
10826 TargetCallLoc = TargetCall->getExprLoc();
10827 }
10828
10829 SemaRef.setFunctionHasBranchProtectedScope();
10830
10831 return OMPDispatchDirective::Create(getASTContext(), StartLoc, EndLoc,
10832 Clauses, AStmt, TargetCallLoc);
10833}
10834
10837 DSAStackTy *Stack) {
10838 bool ErrorFound = false;
10839 for (OMPClause *C : Clauses) {
10840 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10841 for (Expr *RefExpr : LPC->varlist()) {
10842 SourceLocation ELoc;
10843 SourceRange ERange;
10844 Expr *SimpleRefExpr = RefExpr;
10845 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10846 if (ValueDecl *D = Res.first) {
10847 auto &&Info = Stack->isLoopControlVariable(D);
10848 if (!Info.first) {
10849 unsigned OMPVersion = S.getLangOpts().OpenMP;
10850 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10851 << getOpenMPDirectiveName(K, OMPVersion);
10852 ErrorFound = true;
10853 }
10854 }
10855 }
10856 }
10857 }
10858 return ErrorFound;
10859}
10860
10862 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10863 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10864 if (!AStmt)
10865 return StmtError();
10866
10867 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10868 // A list item may not appear in a lastprivate clause unless it is the
10869 // loop iteration variable of a loop that is associated with the construct.
10870 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack))
10871 return StmtError();
10872
10873 setBranchProtectedScope(SemaRef, OMPD_loop, AStmt);
10874
10875 OMPLoopDirective::HelperExprs B;
10876 // In presence of clause 'collapse', it will define the nested loops number.
10877 unsigned NestedLoopCount = checkOpenMPLoop(
10878 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10879 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10880 if (NestedLoopCount == 0)
10881 return StmtError();
10882
10883 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10884 "omp loop exprs were not built");
10885
10886 return OMPGenericLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
10887 NestedLoopCount, Clauses, AStmt, B);
10888}
10889
10891 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10892 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10893 if (!AStmt)
10894 return StmtError();
10895
10896 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10897 // A list item may not appear in a lastprivate clause unless it is the
10898 // loop iteration variable of a loop that is associated with the construct.
10899 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack))
10900 return StmtError();
10901
10902 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_teams_loop, AStmt);
10903
10904 OMPLoopDirective::HelperExprs B;
10905 // In presence of clause 'collapse', it will define the nested loops number.
10906 unsigned NestedLoopCount =
10907 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10908 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10909 VarsWithImplicitDSA, B);
10910 if (NestedLoopCount == 0)
10911 return StmtError();
10912
10913 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10914 "omp loop exprs were not built");
10915
10916 DSAStack->setParentTeamsRegionLoc(StartLoc);
10917
10919 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10920}
10921
10923 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10924 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10925 if (!AStmt)
10926 return StmtError();
10927
10928 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10929 // A list item may not appear in a lastprivate clause unless it is the
10930 // loop iteration variable of a loop that is associated with the construct.
10931 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop,
10932 DSAStack))
10933 return StmtError();
10934
10935 CapturedStmt *CS =
10936 setBranchProtectedScope(SemaRef, OMPD_target_teams_loop, AStmt);
10937
10938 OMPLoopDirective::HelperExprs B;
10939 // In presence of clause 'collapse', it will define the nested loops number.
10940 unsigned NestedLoopCount =
10941 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10942 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10943 VarsWithImplicitDSA, B);
10944 if (NestedLoopCount == 0)
10945 return StmtError();
10946
10947 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10948 "omp loop exprs were not built");
10949
10951 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_parallel_loop,
10965 DSAStack))
10966 return StmtError();
10967
10968 CapturedStmt *CS =
10969 setBranchProtectedScope(SemaRef, OMPD_parallel_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_parallel_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);
10985}
10986
10988 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10989 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10990 if (!AStmt)
10991 return StmtError();
10992
10993 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10994 // A list item may not appear in a lastprivate clause unless it is the
10995 // loop iteration variable of a loop that is associated with the construct.
10996 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_parallel_loop,
10997 DSAStack))
10998 return StmtError();
10999
11000 CapturedStmt *CS =
11001 setBranchProtectedScope(SemaRef, OMPD_target_parallel_loop, AStmt);
11002
11003 OMPLoopDirective::HelperExprs B;
11004 // In presence of clause 'collapse', it will define the nested loops number.
11005 unsigned NestedLoopCount =
11006 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
11007 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
11008 VarsWithImplicitDSA, B);
11009 if (NestedLoopCount == 0)
11010 return StmtError();
11011
11012 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11013 "omp loop exprs were not built");
11014
11016 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11017}
11018
11020 Stmt *AStmt,
11021 SourceLocation StartLoc,
11022 SourceLocation EndLoc) {
11023 if (!AStmt)
11024 return StmtError();
11025
11026 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11027
11028 SemaRef.setFunctionHasBranchProtectedScope();
11029
11030 // OpenMP [2.7.3, single Construct, Restrictions]
11031 // The copyprivate clause must not be used with the nowait clause.
11032 const OMPClause *Nowait = nullptr;
11033 const OMPClause *Copyprivate = nullptr;
11034 for (const OMPClause *Clause : Clauses) {
11035 if (Clause->getClauseKind() == OMPC_nowait)
11036 Nowait = Clause;
11037 else if (Clause->getClauseKind() == OMPC_copyprivate)
11038 Copyprivate = Clause;
11039 if (Copyprivate && Nowait) {
11040 Diag(Copyprivate->getBeginLoc(),
11041 diag::err_omp_single_copyprivate_with_nowait);
11042 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
11043 return StmtError();
11044 }
11045 }
11046
11047 return OMPSingleDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11048 AStmt);
11049}
11050
11052 SourceLocation StartLoc,
11053 SourceLocation EndLoc) {
11054 if (!AStmt)
11055 return StmtError();
11056
11057 SemaRef.setFunctionHasBranchProtectedScope();
11058
11059 return OMPMasterDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt);
11060}
11061
11063 Stmt *AStmt,
11064 SourceLocation StartLoc,
11065 SourceLocation EndLoc) {
11066 if (!AStmt)
11067 return StmtError();
11068
11069 SemaRef.setFunctionHasBranchProtectedScope();
11070
11071 return OMPMaskedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11072 AStmt);
11073}
11074
11076 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
11077 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
11078 if (!AStmt)
11079 return StmtError();
11080
11081 bool ErrorFound = false;
11082 llvm::APSInt Hint;
11083 SourceLocation HintLoc;
11084 bool DependentHint = false;
11085 for (const OMPClause *C : Clauses) {
11086 if (C->getClauseKind() == OMPC_hint) {
11087 if (!DirName.getName()) {
11088 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
11089 ErrorFound = true;
11090 }
11091 Expr *E = cast<OMPHintClause>(C)->getHint();
11092 if (E->isTypeDependent() || E->isValueDependent() ||
11094 DependentHint = true;
11095 } else {
11097 HintLoc = C->getBeginLoc();
11098 }
11099 }
11100 }
11101 if (ErrorFound)
11102 return StmtError();
11103 const auto Pair = DSAStack->getCriticalWithHint(DirName);
11104 if (Pair.first && DirName.getName() && !DependentHint) {
11105 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
11106 Diag(StartLoc, diag::err_omp_critical_with_hint);
11107 if (HintLoc.isValid())
11108 Diag(HintLoc, diag::note_omp_critical_hint_here)
11109 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
11110 else
11111 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
11112 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
11113 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
11114 << 1
11115 << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()),
11116 /*Radix=*/10, /*Signed=*/false);
11117 } else {
11118 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
11119 }
11120 }
11121 }
11122
11123 SemaRef.setFunctionHasBranchProtectedScope();
11124
11125 auto *Dir = OMPCriticalDirective::Create(getASTContext(), DirName, StartLoc,
11126 EndLoc, Clauses, AStmt);
11127 if (!Pair.first && DirName.getName() && !DependentHint)
11128 DSAStack->addCriticalWithHint(Dir, Hint);
11129 return Dir;
11130}
11131
11133 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11134 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11135 if (!AStmt)
11136 return StmtError();
11137
11138 setBranchProtectedScope(SemaRef, OMPD_parallel_for, AStmt);
11139
11140 OMPLoopBasedDirective::HelperExprs B;
11141 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11142 // define the nested loops number.
11143 unsigned NestedLoopCount =
11144 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
11145 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
11146 VarsWithImplicitDSA, B);
11147 if (NestedLoopCount == 0)
11148 return StmtError();
11149
11150 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11151 return StmtError();
11152
11153 return OMPParallelForDirective::Create(
11154 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11155 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11156}
11157
11159 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11160 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11161 if (!AStmt)
11162 return StmtError();
11163
11164 CapturedStmt *CS =
11165 setBranchProtectedScope(SemaRef, OMPD_parallel_for_simd, AStmt);
11166
11167 OMPLoopBasedDirective::HelperExprs B;
11168 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11169 // define the nested loops number.
11170 unsigned NestedLoopCount =
11171 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
11172 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
11173 VarsWithImplicitDSA, B);
11174 if (NestedLoopCount == 0)
11175 return StmtError();
11176
11177 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11178 return StmtError();
11179
11181 return StmtError();
11182
11183 return OMPParallelForSimdDirective::Create(
11184 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11185}
11186
11188 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11189 SourceLocation EndLoc) {
11190 if (!AStmt)
11191 return StmtError();
11192
11193 setBranchProtectedScope(SemaRef, OMPD_parallel_master, AStmt);
11194
11195 return OMPParallelMasterDirective::Create(
11196 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11197 DSAStack->getTaskgroupReductionRef());
11198}
11199
11201 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11202 SourceLocation EndLoc) {
11203 if (!AStmt)
11204 return StmtError();
11205
11206 setBranchProtectedScope(SemaRef, OMPD_parallel_masked, AStmt);
11207
11208 return OMPParallelMaskedDirective::Create(
11209 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11210 DSAStack->getTaskgroupReductionRef());
11211}
11212
11214 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11215 SourceLocation EndLoc) {
11216 if (checkSectionsDirective(SemaRef, OMPD_parallel_sections, AStmt, DSAStack))
11217 return StmtError();
11218
11219 SemaRef.setFunctionHasBranchProtectedScope();
11220
11221 return OMPParallelSectionsDirective::Create(
11222 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11223 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11224}
11225
11226/// Find and diagnose mutually exclusive clause kinds.
11228 Sema &S, ArrayRef<OMPClause *> Clauses,
11229 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11230 const OMPClause *PrevClause = nullptr;
11231 bool ErrorFound = false;
11232 for (const OMPClause *C : Clauses) {
11233 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
11234 if (!PrevClause) {
11235 PrevClause = C;
11236 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11237 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11238 << getOpenMPClauseNameForDiag(C->getClauseKind())
11239 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11240 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
11241 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11242 ErrorFound = true;
11243 }
11244 }
11245 }
11246 return ErrorFound;
11247}
11248
11250 Stmt *AStmt,
11251 SourceLocation StartLoc,
11252 SourceLocation EndLoc) {
11253 if (!AStmt)
11254 return StmtError();
11255
11256 // OpenMP 5.0, 2.10.1 task Construct
11257 // If a detach clause appears on the directive, then a mergeable clause cannot
11258 // appear on the same directive.
11260 {OMPC_detach, OMPC_mergeable}))
11261 return StmtError();
11262
11263 setBranchProtectedScope(SemaRef, OMPD_task, AStmt);
11264
11265 return OMPTaskDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11266 AStmt, DSAStack->isCancelRegion());
11267}
11268
11270 SourceLocation EndLoc) {
11271 return OMPTaskyieldDirective::Create(getASTContext(), StartLoc, EndLoc);
11272}
11273
11275 SourceLocation EndLoc) {
11276 return OMPBarrierDirective::Create(getASTContext(), StartLoc, EndLoc);
11277}
11278
11280 SourceLocation StartLoc,
11281 SourceLocation EndLoc,
11282 bool InExContext) {
11283 const OMPAtClause *AtC =
11284 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11285
11286 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11287 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11288 return StmtError();
11289 }
11290
11291 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11292 const OMPSeverityClause *SeverityC =
11293 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11294 const OMPMessageClause *MessageC =
11295 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11296 std::optional<std::string> SL =
11297 MessageC ? MessageC->tryEvaluateString(getASTContext()) : std::nullopt;
11298
11299 if (MessageC && !SL)
11300 Diag(MessageC->getMessageString()->getBeginLoc(),
11301 diag::warn_clause_expected_string)
11302 << getOpenMPClauseNameForDiag(OMPC_message) << 1;
11303 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11304 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11305 << SL.value_or("WARNING");
11306 else
11307 Diag(StartLoc, diag::err_diagnose_if_succeeded) << SL.value_or("ERROR");
11308 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11309 return StmtError();
11310 }
11311
11312 return OMPErrorDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11313}
11314
11317 SourceLocation StartLoc,
11318 SourceLocation EndLoc) {
11319 const OMPNowaitClause *NowaitC =
11320 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11321 bool HasDependC =
11322 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11323 .empty();
11324 if (NowaitC && !HasDependC) {
11325 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11326 return StmtError();
11327 }
11328
11329 return OMPTaskwaitDirective::Create(getASTContext(), StartLoc, EndLoc,
11330 Clauses);
11331}
11332
11335 Stmt *AStmt, SourceLocation StartLoc,
11336 SourceLocation EndLoc) {
11337 if (!AStmt)
11338 return StmtError();
11339
11340 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11341
11342 SemaRef.setFunctionHasBranchProtectedScope();
11343
11344 return OMPTaskgroupDirective::Create(getASTContext(), StartLoc, EndLoc,
11345 Clauses, AStmt,
11346 DSAStack->getTaskgroupReductionRef());
11347}
11348
11350 SourceLocation StartLoc,
11351 SourceLocation EndLoc) {
11352 OMPFlushClause *FC = nullptr;
11353 OMPClause *OrderClause = nullptr;
11354 for (OMPClause *C : Clauses) {
11355 if (C->getClauseKind() == OMPC_flush)
11356 FC = cast<OMPFlushClause>(C);
11357 else
11358 OrderClause = C;
11359 }
11360 unsigned OMPVersion = getLangOpts().OpenMP;
11361 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11362 SourceLocation MemOrderLoc;
11363 for (const OMPClause *C : Clauses) {
11364 if (C->getClauseKind() == OMPC_acq_rel ||
11365 C->getClauseKind() == OMPC_acquire ||
11366 C->getClauseKind() == OMPC_release ||
11367 C->getClauseKind() == OMPC_seq_cst /*OpenMP 5.1*/) {
11368 if (MemOrderKind != OMPC_unknown) {
11369 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11370 << getOpenMPDirectiveName(OMPD_flush, OMPVersion) << 1
11371 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11372 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11373 << getOpenMPClauseNameForDiag(MemOrderKind);
11374 } else {
11375 MemOrderKind = C->getClauseKind();
11376 MemOrderLoc = C->getBeginLoc();
11377 }
11378 }
11379 }
11380 if (FC && OrderClause) {
11381 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11382 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11383 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11384 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11385 return StmtError();
11386 }
11387 return OMPFlushDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11388}
11389
11391 SourceLocation StartLoc,
11392 SourceLocation EndLoc) {
11393 if (Clauses.empty()) {
11394 Diag(StartLoc, diag::err_omp_depobj_expected);
11395 return StmtError();
11396 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11397 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11398 return StmtError();
11399 }
11400 // Only depobj expression and another single clause is allowed.
11401 if (Clauses.size() > 2) {
11402 Diag(Clauses[2]->getBeginLoc(),
11403 diag::err_omp_depobj_single_clause_expected);
11404 return StmtError();
11405 } else if (Clauses.size() < 1) {
11406 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11407 return StmtError();
11408 }
11409 return OMPDepobjDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11410}
11411
11413 SourceLocation StartLoc,
11414 SourceLocation EndLoc) {
11415 // Check that exactly one clause is specified.
11416 if (Clauses.size() != 1) {
11417 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11418 diag::err_omp_scan_single_clause_expected);
11419 return StmtError();
11420 }
11421 // Check that scan directive is used in the scope of the OpenMP loop body.
11422 if (Scope *S = DSAStack->getCurScope()) {
11423 Scope *ParentS = S->getParent();
11424 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11425 !ParentS->getBreakParent()->isOpenMPLoopScope()) {
11426 unsigned OMPVersion = getLangOpts().OpenMP;
11427 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11428 << getOpenMPDirectiveName(OMPD_scan, OMPVersion) << 5);
11429 }
11430 }
11431 // Check that only one instance of scan directives is used in the same outer
11432 // region.
11433 if (DSAStack->doesParentHasScanDirective()) {
11434 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11435 Diag(DSAStack->getParentScanDirectiveLoc(),
11436 diag::note_omp_previous_directive)
11437 << "scan";
11438 return StmtError();
11439 }
11440 DSAStack->setParentHasScanDirective(StartLoc);
11441 return OMPScanDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11442}
11443
11446 Stmt *AStmt, SourceLocation StartLoc,
11447 SourceLocation EndLoc) {
11448 const OMPClause *DependFound = nullptr;
11449 const OMPClause *DependSourceClause = nullptr;
11450 const OMPClause *DependSinkClause = nullptr;
11451 const OMPClause *DoacrossFound = nullptr;
11452 const OMPClause *DoacrossSourceClause = nullptr;
11453 const OMPClause *DoacrossSinkClause = nullptr;
11454 bool ErrorFound = false;
11455 const OMPThreadsClause *TC = nullptr;
11456 const OMPSIMDClause *SC = nullptr;
11457 for (const OMPClause *C : Clauses) {
11458 auto DOC = dyn_cast<OMPDoacrossClause>(C);
11459 auto DC = dyn_cast<OMPDependClause>(C);
11460 if (DC || DOC) {
11461 DependFound = DC ? C : nullptr;
11462 DoacrossFound = DOC ? C : nullptr;
11463 OMPDoacrossKind ODK;
11464 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11465 (DOC && (ODK.isSource(DOC)))) {
11466 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11467 unsigned OMPVersion = getLangOpts().OpenMP;
11468 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11469 << getOpenMPDirectiveName(OMPD_ordered, OMPVersion)
11470 << getOpenMPClauseNameForDiag(DC ? OMPC_depend : OMPC_doacross)
11471 << 2;
11472 ErrorFound = true;
11473 } else {
11474 if (DC)
11475 DependSourceClause = C;
11476 else
11477 DoacrossSourceClause = C;
11478 }
11479 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11480 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11481 << (DC ? "depend" : "doacross") << 0;
11482 ErrorFound = true;
11483 }
11484 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11485 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11486 if (DependSourceClause || DoacrossSourceClause) {
11487 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11488 << (DC ? "depend" : "doacross") << 1;
11489 ErrorFound = true;
11490 }
11491 if (DC)
11492 DependSinkClause = C;
11493 else
11494 DoacrossSinkClause = C;
11495 }
11496 } else if (C->getClauseKind() == OMPC_threads) {
11498 } else if (C->getClauseKind() == OMPC_simd) {
11499 SC = cast<OMPSIMDClause>(C);
11500 }
11501 }
11502 if (!ErrorFound && !SC &&
11503 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11504 // OpenMP [2.8.1,simd Construct, Restrictions]
11505 // An ordered construct with the simd clause is the only OpenMP construct
11506 // that can appear in the simd region.
11507 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11508 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11509 ErrorFound = true;
11510 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11511 SourceLocation Loc =
11512 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11513 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11514 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend : OMPC_doacross)
11516 : SC->getClauseKind());
11517 ErrorFound = true;
11518 } else if ((DependFound || DoacrossFound) &&
11519 !DSAStack->getParentOrderedRegionParam().first) {
11520 SourceLocation Loc =
11521 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11522 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11523 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend
11524 : OMPC_doacross);
11525 ErrorFound = true;
11526 } else if (TC || Clauses.empty()) {
11527 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11528 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11529 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11530 << (TC != nullptr);
11531 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11532 ErrorFound = true;
11533 }
11534 }
11535 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11536 return StmtError();
11537
11538 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11539 // During execution of an iteration of a worksharing-loop or a loop nest
11540 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11541 // must not execute more than one ordered region corresponding to an ordered
11542 // construct without a depend clause.
11543 if (!DependFound && !DoacrossFound) {
11544 if (DSAStack->doesParentHasOrderedDirective()) {
11545 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11546 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11547 diag::note_omp_previous_directive)
11548 << "ordered";
11549 return StmtError();
11550 }
11551 DSAStack->setParentHasOrderedDirective(StartLoc);
11552 }
11553
11554 if (AStmt) {
11555 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11556
11557 SemaRef.setFunctionHasBranchProtectedScope();
11558 }
11559
11560 return OMPOrderedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11561 AStmt);
11562}
11563
11564namespace {
11565/// Helper class for checking expression in 'omp atomic [update]'
11566/// construct.
11567class OpenMPAtomicUpdateChecker {
11568 /// Error results for atomic update expressions.
11569 enum ExprAnalysisErrorCode {
11570 /// A statement is not an expression statement.
11571 NotAnExpression,
11572 /// Expression is not builtin binary or unary operation.
11573 NotABinaryOrUnaryExpression,
11574 /// Unary operation is not post-/pre- increment/decrement operation.
11575 NotAnUnaryIncDecExpression,
11576 /// An expression is not of scalar type.
11577 NotAScalarType,
11578 /// A binary operation is not an assignment operation.
11579 NotAnAssignmentOp,
11580 /// RHS part of the binary operation is not a binary expression.
11581 NotABinaryExpression,
11582 /// RHS part is not additive/multiplicative/shift/bitwise binary
11583 /// expression.
11584 NotABinaryOperator,
11585 /// RHS binary operation does not have reference to the updated LHS
11586 /// part.
11587 NotAnUpdateExpression,
11588 /// An expression contains semantical error not related to
11589 /// 'omp atomic [update]'
11590 NotAValidExpression,
11591 /// No errors is found.
11592 NoError
11593 };
11594 /// Reference to Sema.
11595 Sema &SemaRef;
11596 /// A location for note diagnostics (when error is found).
11597 SourceLocation NoteLoc;
11598 /// 'x' lvalue part of the source atomic expression.
11599 Expr *X;
11600 /// 'expr' rvalue part of the source atomic expression.
11601 Expr *E;
11602 /// Helper expression of the form
11603 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11604 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11605 Expr *UpdateExpr;
11606 /// Is 'x' a LHS in a RHS part of full update expression. It is
11607 /// important for non-associative operations.
11608 bool IsXLHSInRHSPart;
11610 SourceLocation OpLoc;
11611 /// true if the source expression is a postfix unary operation, false
11612 /// if it is a prefix unary operation.
11613 bool IsPostfixUpdate;
11614
11615public:
11616 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11617 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11618 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11619 /// Check specified statement that it is suitable for 'atomic update'
11620 /// constructs and extract 'x', 'expr' and Operation from the original
11621 /// expression. If DiagId and NoteId == 0, then only check is performed
11622 /// without error notification.
11623 /// \param DiagId Diagnostic which should be emitted if error is found.
11624 /// \param NoteId Diagnostic note for the main error message.
11625 /// \return true if statement is not an update expression, false otherwise.
11626 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11627 /// Return the 'x' lvalue part of the source atomic expression.
11628 Expr *getX() const { return X; }
11629 /// Return the 'expr' rvalue part of the source atomic expression.
11630 Expr *getExpr() const { return E; }
11631 /// Return the update expression used in calculation of the updated
11632 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11633 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11634 Expr *getUpdateExpr() const { return UpdateExpr; }
11635 /// Return true if 'x' is LHS in RHS part of full update expression,
11636 /// false otherwise.
11637 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11638
11639 /// true if the source expression is a postfix unary operation, false
11640 /// if it is a prefix unary operation.
11641 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11642
11643private:
11644 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11645 unsigned NoteId = 0);
11646};
11647
11648bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11649 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11650 ExprAnalysisErrorCode ErrorFound = NoError;
11651 SourceLocation ErrorLoc, NoteLoc;
11652 SourceRange ErrorRange, NoteRange;
11653 // Allowed constructs are:
11654 // x = x binop expr;
11655 // x = expr binop x;
11656 if (AtomicBinOp->getOpcode() == BO_Assign) {
11657 X = AtomicBinOp->getLHS();
11658 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11659 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11660 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11661 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11662 AtomicInnerBinOp->isBitwiseOp()) {
11663 Op = AtomicInnerBinOp->getOpcode();
11664 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11665 Expr *LHS = AtomicInnerBinOp->getLHS();
11666 Expr *RHS = AtomicInnerBinOp->getRHS();
11667 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11668 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11669 /*Canonical=*/true);
11670 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11671 /*Canonical=*/true);
11672 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11673 /*Canonical=*/true);
11674 if (XId == LHSId) {
11675 E = RHS;
11676 IsXLHSInRHSPart = true;
11677 } else if (XId == RHSId) {
11678 E = LHS;
11679 IsXLHSInRHSPart = false;
11680 } else {
11681 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11682 ErrorRange = AtomicInnerBinOp->getSourceRange();
11683 NoteLoc = X->getExprLoc();
11684 NoteRange = X->getSourceRange();
11685 ErrorFound = NotAnUpdateExpression;
11686 }
11687 } else {
11688 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11689 ErrorRange = AtomicInnerBinOp->getSourceRange();
11690 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11691 NoteRange = SourceRange(NoteLoc, NoteLoc);
11692 ErrorFound = NotABinaryOperator;
11693 }
11694 } else {
11695 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11696 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11697 ErrorFound = NotABinaryExpression;
11698 }
11699 } else {
11700 ErrorLoc = AtomicBinOp->getExprLoc();
11701 ErrorRange = AtomicBinOp->getSourceRange();
11702 NoteLoc = AtomicBinOp->getOperatorLoc();
11703 NoteRange = SourceRange(NoteLoc, NoteLoc);
11704 ErrorFound = NotAnAssignmentOp;
11705 }
11706 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11707 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11708 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11709 return true;
11710 }
11711 if (SemaRef.CurContext->isDependentContext())
11712 E = X = UpdateExpr = nullptr;
11713 return ErrorFound != NoError;
11714}
11715
11716bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11717 unsigned NoteId) {
11718 ExprAnalysisErrorCode ErrorFound = NoError;
11719 SourceLocation ErrorLoc, NoteLoc;
11720 SourceRange ErrorRange, NoteRange;
11721 // Allowed constructs are:
11722 // x++;
11723 // x--;
11724 // ++x;
11725 // --x;
11726 // x binop= expr;
11727 // x = x binop expr;
11728 // x = expr binop x;
11729 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11730 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11731 if (AtomicBody->getType()->isScalarType() ||
11732 AtomicBody->isInstantiationDependent()) {
11733 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11734 AtomicBody->IgnoreParenImpCasts())) {
11735 // Check for Compound Assignment Operation
11737 AtomicCompAssignOp->getOpcode());
11738 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11739 E = AtomicCompAssignOp->getRHS();
11740 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11741 IsXLHSInRHSPart = true;
11742 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11743 AtomicBody->IgnoreParenImpCasts())) {
11744 // Check for Binary Operation
11745 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11746 return true;
11747 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11748 AtomicBody->IgnoreParenImpCasts())) {
11749 // Check for Unary Operation
11750 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11751 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11752 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11753 OpLoc = AtomicUnaryOp->getOperatorLoc();
11754 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11755 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11756 IsXLHSInRHSPart = true;
11757 } else {
11758 ErrorFound = NotAnUnaryIncDecExpression;
11759 ErrorLoc = AtomicUnaryOp->getExprLoc();
11760 ErrorRange = AtomicUnaryOp->getSourceRange();
11761 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11762 NoteRange = SourceRange(NoteLoc, NoteLoc);
11763 }
11764 } else if (!AtomicBody->isInstantiationDependent()) {
11765 ErrorFound = NotABinaryOrUnaryExpression;
11766 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11767 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11768 } else if (AtomicBody->containsErrors()) {
11769 ErrorFound = NotAValidExpression;
11770 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11771 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11772 }
11773 } else {
11774 ErrorFound = NotAScalarType;
11775 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11776 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11777 }
11778 } else {
11779 ErrorFound = NotAnExpression;
11780 NoteLoc = ErrorLoc = S->getBeginLoc();
11781 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11782 }
11783 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11784 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11785 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11786 return true;
11787 }
11788 if (SemaRef.CurContext->isDependentContext())
11789 E = X = UpdateExpr = nullptr;
11790 if (ErrorFound == NoError && E && X) {
11791 // Build an update expression of form 'OpaqueValueExpr(x) binop
11792 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11793 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11794 auto *OVEX = new (SemaRef.getASTContext())
11795 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11796 auto *OVEExpr = new (SemaRef.getASTContext())
11799 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11800 IsXLHSInRHSPart ? OVEExpr : OVEX);
11801 if (Update.isInvalid())
11802 return true;
11803 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11805 if (Update.isInvalid())
11806 return true;
11807 UpdateExpr = Update.get();
11808 }
11809 return ErrorFound != NoError;
11810}
11811
11812/// Get the node id of the fixed point of an expression \a S.
11813llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11814 llvm::FoldingSetNodeID Id;
11815 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11816 return Id;
11817}
11818
11819/// Check if two expressions are same.
11820bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11821 const Expr *RHS) {
11822 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11823}
11824
11825class OpenMPAtomicCompareChecker {
11826public:
11827 /// All kinds of errors that can occur in `atomic compare`
11828 enum ErrorTy {
11829 /// Empty compound statement.
11830 NoStmt = 0,
11831 /// More than one statement in a compound statement.
11832 MoreThanOneStmt,
11833 /// Not an assignment binary operator.
11834 NotAnAssignment,
11835 /// Not a conditional operator.
11836 NotCondOp,
11837 /// Wrong false expr. According to the spec, 'x' should be at the false
11838 /// expression of a conditional expression.
11839 WrongFalseExpr,
11840 /// The condition of a conditional expression is not a binary operator.
11841 NotABinaryOp,
11842 /// Invalid binary operator (not <, >, or ==).
11843 InvalidBinaryOp,
11844 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11845 InvalidComparison,
11846 /// X is not a lvalue.
11847 XNotLValue,
11848 /// Not a scalar.
11849 NotScalar,
11850 /// Not an integer.
11851 NotInteger,
11852 /// 'else' statement is not expected.
11853 UnexpectedElse,
11854 /// Not an equality operator.
11855 NotEQ,
11856 /// Invalid assignment (not v == x).
11857 InvalidAssignment,
11858 /// Not if statement
11859 NotIfStmt,
11860 /// More than two statements in a compound statement.
11861 MoreThanTwoStmts,
11862 /// Not a compound statement.
11863 NotCompoundStmt,
11864 /// No else statement.
11865 NoElse,
11866 /// Not 'if (r)'.
11867 InvalidCondition,
11868 /// No error.
11869 NoError,
11870 };
11871
11872 struct ErrorInfoTy {
11873 ErrorTy Error;
11874 SourceLocation ErrorLoc;
11875 SourceRange ErrorRange;
11876 SourceLocation NoteLoc;
11877 SourceRange NoteRange;
11878 };
11879
11880 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11881
11882 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11883 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11884
11885 Expr *getX() const { return X; }
11886 Expr *getE() const { return E; }
11887 Expr *getD() const { return D; }
11888 Expr *getCond() const { return C; }
11889 bool isXBinopExpr() const { return IsXBinopExpr; }
11890
11891protected:
11892 /// Reference to ASTContext
11893 ASTContext &ContextRef;
11894 /// 'x' lvalue part of the source atomic expression.
11895 Expr *X = nullptr;
11896 /// 'expr' or 'e' rvalue part of the source atomic expression.
11897 Expr *E = nullptr;
11898 /// 'd' rvalue part of the source atomic expression.
11899 Expr *D = nullptr;
11900 /// 'cond' part of the source atomic expression. It is in one of the following
11901 /// forms:
11902 /// expr ordop x
11903 /// x ordop expr
11904 /// x == e
11905 /// e == x
11906 Expr *C = nullptr;
11907 /// True if the cond expr is in the form of 'x ordop expr'.
11908 bool IsXBinopExpr = true;
11909
11910 /// Check if it is a valid conditional update statement (cond-update-stmt).
11911 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11912
11913 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11914 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11915
11916 /// Check if all captured values have right type.
11917 bool checkType(ErrorInfoTy &ErrorInfo) const;
11918
11919 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11920 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11921 if (E->isInstantiationDependent())
11922 return true;
11923
11924 if (ShouldBeLValue && !E->isLValue()) {
11925 ErrorInfo.Error = ErrorTy::XNotLValue;
11926 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11927 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11928 return false;
11929 }
11930
11931 QualType QTy = E->getType();
11932 if (!QTy->isScalarType()) {
11933 ErrorInfo.Error = ErrorTy::NotScalar;
11934 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11935 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11936 return false;
11937 }
11938 if (ShouldBeInteger && !QTy->isIntegerType()) {
11939 ErrorInfo.Error = ErrorTy::NotInteger;
11940 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11941 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11942 return false;
11943 }
11944
11945 return true;
11946 }
11947};
11948
11949bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11950 ErrorInfoTy &ErrorInfo) {
11951 auto *Then = S->getThen();
11952 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11953 if (CS->body_empty()) {
11954 ErrorInfo.Error = ErrorTy::NoStmt;
11955 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11956 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11957 return false;
11958 }
11959 if (CS->size() > 1) {
11960 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11961 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11962 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11963 return false;
11964 }
11965 Then = CS->body_front();
11966 }
11967
11968 auto *BO = dyn_cast<BinaryOperator>(Then);
11969 if (!BO) {
11970 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11971 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11972 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11973 return false;
11974 }
11975 if (BO->getOpcode() != BO_Assign) {
11976 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11977 ErrorInfo.ErrorLoc = BO->getExprLoc();
11978 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11979 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11980 return false;
11981 }
11982
11983 X = BO->getLHS();
11984
11985 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11986 auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
11987 Expr *LHS = nullptr;
11988 Expr *RHS = nullptr;
11989 if (Cond) {
11990 LHS = Cond->getLHS();
11991 RHS = Cond->getRHS();
11992 } else if (Call) {
11993 LHS = Call->getArg(0);
11994 RHS = Call->getArg(1);
11995 } else {
11996 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11997 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11998 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11999 return false;
12000 }
12001
12002 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12003 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12004 C = S->getCond();
12005 D = BO->getRHS();
12006 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12007 E = RHS;
12008 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12009 E = LHS;
12010 } else {
12011 ErrorInfo.Error = ErrorTy::InvalidComparison;
12012 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12013 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12014 S->getCond()->getSourceRange();
12015 return false;
12016 }
12017 } else if ((Cond &&
12018 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12019 (Call &&
12020 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12021 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12022 E = BO->getRHS();
12023 if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
12024 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12025 C = S->getCond();
12026 } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12027 checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12028 C = S->getCond();
12029 IsXBinopExpr = false;
12030 } else {
12031 ErrorInfo.Error = ErrorTy::InvalidComparison;
12032 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12033 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12034 S->getCond()->getSourceRange();
12035 return false;
12036 }
12037 } else {
12038 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12039 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12040 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12041 return false;
12042 }
12043
12044 if (S->getElse()) {
12045 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12046 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
12047 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
12048 return false;
12049 }
12050
12051 return true;
12052}
12053
12054bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
12055 ErrorInfoTy &ErrorInfo) {
12056 auto *BO = dyn_cast<BinaryOperator>(S);
12057 if (!BO) {
12058 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12059 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12060 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12061 return false;
12062 }
12063 if (BO->getOpcode() != BO_Assign) {
12064 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12065 ErrorInfo.ErrorLoc = BO->getExprLoc();
12066 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12067 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12068 return false;
12069 }
12070
12071 X = BO->getLHS();
12072
12073 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
12074 if (!CO) {
12075 ErrorInfo.Error = ErrorTy::NotCondOp;
12076 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12077 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12078 return false;
12079 }
12080
12081 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
12082 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12083 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12084 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12085 CO->getFalseExpr()->getSourceRange();
12086 return false;
12087 }
12088
12089 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
12090 auto *Call = dyn_cast<CXXOperatorCallExpr>(CO->getCond());
12091 Expr *LHS = nullptr;
12092 Expr *RHS = nullptr;
12093 if (Cond) {
12094 LHS = Cond->getLHS();
12095 RHS = Cond->getRHS();
12096 } else if (Call) {
12097 LHS = Call->getArg(0);
12098 RHS = Call->getArg(1);
12099 } else {
12100 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12101 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12102 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12103 CO->getCond()->getSourceRange();
12104 return false;
12105 }
12106
12107 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12108 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12109 C = CO->getCond();
12110 D = CO->getTrueExpr();
12111 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12112 E = RHS;
12113 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12114 E = LHS;
12115 } else {
12116 ErrorInfo.Error = ErrorTy::InvalidComparison;
12117 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12118 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12119 CO->getCond()->getSourceRange();
12120 return false;
12121 }
12122 } else if ((Cond &&
12123 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12124 (Call &&
12125 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12126 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12127
12128 E = CO->getTrueExpr();
12129 if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
12130 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12131 C = CO->getCond();
12132 } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12133 checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12134 C = CO->getCond();
12135 IsXBinopExpr = false;
12136 } else {
12137 ErrorInfo.Error = ErrorTy::InvalidComparison;
12138 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12139 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12140 CO->getCond()->getSourceRange();
12141 return false;
12142 }
12143 } else {
12144 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12145 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12146 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12147 CO->getCond()->getSourceRange();
12148 return false;
12149 }
12150
12151 return true;
12152}
12153
12154bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
12155 // 'x' and 'e' cannot be nullptr
12156 assert(X && E && "X and E cannot be nullptr");
12157
12158 if (!CheckValue(X, ErrorInfo, true))
12159 return false;
12160
12161 if (!CheckValue(E, ErrorInfo, false))
12162 return false;
12163
12164 if (D && !CheckValue(D, ErrorInfo, false))
12165 return false;
12166
12167 return true;
12168}
12169
12170bool OpenMPAtomicCompareChecker::checkStmt(
12171 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12172 auto *CS = dyn_cast<CompoundStmt>(S);
12173 if (CS) {
12174 if (CS->body_empty()) {
12175 ErrorInfo.Error = ErrorTy::NoStmt;
12176 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12177 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12178 return false;
12179 }
12180
12181 if (CS->size() != 1) {
12182 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12183 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12184 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12185 return false;
12186 }
12187 S = CS->body_front();
12188 }
12189
12190 auto Res = false;
12191
12192 if (auto *IS = dyn_cast<IfStmt>(S)) {
12193 // Check if the statement is in one of the following forms
12194 // (cond-update-stmt):
12195 // if (expr ordop x) { x = expr; }
12196 // if (x ordop expr) { x = expr; }
12197 // if (x == e) { x = d; }
12198 Res = checkCondUpdateStmt(IS, ErrorInfo);
12199 } else {
12200 // Check if the statement is in one of the following forms (cond-expr-stmt):
12201 // x = expr ordop x ? expr : x;
12202 // x = x ordop expr ? expr : x;
12203 // x = x == e ? d : x;
12204 Res = checkCondExprStmt(S, ErrorInfo);
12205 }
12206
12207 if (!Res)
12208 return false;
12209
12210 return checkType(ErrorInfo);
12211}
12212
12213class OpenMPAtomicCompareCaptureChecker final
12214 : public OpenMPAtomicCompareChecker {
12215public:
12216 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12217
12218 Expr *getV() const { return V; }
12219 Expr *getR() const { return R; }
12220 bool isFailOnly() const { return IsFailOnly; }
12221 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12222
12223 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12224 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12225
12226private:
12227 bool checkType(ErrorInfoTy &ErrorInfo);
12228
12229 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12230 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12231 // spec p.p. 82:
12232 // (1) { v = x; cond-update-stmt }
12233 // (2) { cond-update-stmt v = x; }
12234 // (3) if(x == e) { x = d; } else { v = x; }
12235 // (4) { r = x == e; if(r) { x = d; } }
12236 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12237
12238 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12239 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12240
12241 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12242 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12243 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12244
12245 /// 'v' lvalue part of the source atomic expression.
12246 Expr *V = nullptr;
12247 /// 'r' lvalue part of the source atomic expression.
12248 Expr *R = nullptr;
12249 /// If 'v' is only updated when the comparison fails.
12250 bool IsFailOnly = false;
12251 /// If original value of 'x' must be stored in 'v', not an updated one.
12252 bool IsPostfixUpdate = false;
12253};
12254
12255bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12256 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12257 return false;
12258
12259 if (V && !CheckValue(V, ErrorInfo, true))
12260 return false;
12261
12262 if (R && !CheckValue(R, ErrorInfo, true, true))
12263 return false;
12264
12265 return true;
12266}
12267
12268bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12269 ErrorInfoTy &ErrorInfo) {
12270 IsFailOnly = true;
12271
12272 auto *Then = S->getThen();
12273 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12274 if (CS->body_empty()) {
12275 ErrorInfo.Error = ErrorTy::NoStmt;
12276 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12277 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12278 return false;
12279 }
12280 if (CS->size() > 1) {
12281 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12282 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12283 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12284 return false;
12285 }
12286 Then = CS->body_front();
12287 }
12288
12289 auto *BO = dyn_cast<BinaryOperator>(Then);
12290 if (!BO) {
12291 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12292 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12293 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12294 return false;
12295 }
12296 if (BO->getOpcode() != BO_Assign) {
12297 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12298 ErrorInfo.ErrorLoc = BO->getExprLoc();
12299 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12300 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12301 return false;
12302 }
12303
12304 X = BO->getLHS();
12305 D = BO->getRHS();
12306
12307 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12308 auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
12309 Expr *LHS = nullptr;
12310 Expr *RHS = nullptr;
12311 if (Cond) {
12312 LHS = Cond->getLHS();
12313 RHS = Cond->getRHS();
12314 } else if (Call) {
12315 LHS = Call->getArg(0);
12316 RHS = Call->getArg(1);
12317 } else {
12318 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12319 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12320 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12321 return false;
12322 }
12323 if ((Cond && Cond->getOpcode() != BO_EQ) ||
12324 (Call && Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12325 ErrorInfo.Error = ErrorTy::NotEQ;
12326 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12327 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12328 return false;
12329 }
12330
12331 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12332 E = RHS;
12333 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12334 E = LHS;
12335 } else {
12336 ErrorInfo.Error = ErrorTy::InvalidComparison;
12337 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12338 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12339 return false;
12340 }
12341
12342 C = S->getCond();
12343
12344 if (!S->getElse()) {
12345 ErrorInfo.Error = ErrorTy::NoElse;
12346 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12347 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12348 return false;
12349 }
12350
12351 auto *Else = S->getElse();
12352 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12353 if (CS->body_empty()) {
12354 ErrorInfo.Error = ErrorTy::NoStmt;
12355 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12356 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12357 return false;
12358 }
12359 if (CS->size() > 1) {
12360 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12361 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12362 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12363 return false;
12364 }
12365 Else = CS->body_front();
12366 }
12367
12368 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12369 if (!ElseBO) {
12370 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12371 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12372 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12373 return false;
12374 }
12375 if (ElseBO->getOpcode() != BO_Assign) {
12376 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12377 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12378 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12379 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12380 return false;
12381 }
12382
12383 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12384 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12385 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12386 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12387 ElseBO->getRHS()->getSourceRange();
12388 return false;
12389 }
12390
12391 V = ElseBO->getLHS();
12392
12393 return checkType(ErrorInfo);
12394}
12395
12396bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12397 ErrorInfoTy &ErrorInfo) {
12398 // We don't check here as they should be already done before call this
12399 // function.
12400 auto *CS = cast<CompoundStmt>(S);
12401 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12402 auto *S1 = cast<BinaryOperator>(CS->body_front());
12403 auto *S2 = cast<IfStmt>(CS->body_back());
12404 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12405
12406 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12407 ErrorInfo.Error = ErrorTy::InvalidCondition;
12408 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12409 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12410 return false;
12411 }
12412
12413 R = S1->getLHS();
12414
12415 auto *Then = S2->getThen();
12416 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12417 if (ThenCS->body_empty()) {
12418 ErrorInfo.Error = ErrorTy::NoStmt;
12419 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12420 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12421 return false;
12422 }
12423 if (ThenCS->size() > 1) {
12424 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12425 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12426 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12427 return false;
12428 }
12429 Then = ThenCS->body_front();
12430 }
12431
12432 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12433 if (!ThenBO) {
12434 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12435 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12436 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12437 return false;
12438 }
12439 if (ThenBO->getOpcode() != BO_Assign) {
12440 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12441 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12442 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12443 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12444 return false;
12445 }
12446
12447 X = ThenBO->getLHS();
12448 D = ThenBO->getRHS();
12449
12450 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12451 if (BO->getOpcode() != BO_EQ) {
12452 ErrorInfo.Error = ErrorTy::NotEQ;
12453 ErrorInfo.ErrorLoc = BO->getExprLoc();
12454 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12455 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12456 return false;
12457 }
12458
12459 C = BO;
12460
12461 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12462 E = BO->getRHS();
12463 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12464 E = BO->getLHS();
12465 } else {
12466 ErrorInfo.Error = ErrorTy::InvalidComparison;
12467 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12468 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12469 return false;
12470 }
12471
12472 if (S2->getElse()) {
12473 IsFailOnly = true;
12474
12475 auto *Else = S2->getElse();
12476 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12477 if (ElseCS->body_empty()) {
12478 ErrorInfo.Error = ErrorTy::NoStmt;
12479 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12480 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12481 return false;
12482 }
12483 if (ElseCS->size() > 1) {
12484 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12485 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12486 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12487 return false;
12488 }
12489 Else = ElseCS->body_front();
12490 }
12491
12492 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12493 if (!ElseBO) {
12494 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12495 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12496 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12497 return false;
12498 }
12499 if (ElseBO->getOpcode() != BO_Assign) {
12500 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12501 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12502 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12503 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12504 return false;
12505 }
12506 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12507 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12508 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12509 ErrorInfo.NoteLoc = X->getExprLoc();
12510 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12511 ErrorInfo.NoteRange = X->getSourceRange();
12512 return false;
12513 }
12514
12515 V = ElseBO->getLHS();
12516 }
12517
12518 return checkType(ErrorInfo);
12519}
12520
12521bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12522 ErrorInfoTy &ErrorInfo) {
12523 // if(x == e) { x = d; } else { v = x; }
12524 if (auto *IS = dyn_cast<IfStmt>(S))
12525 return checkForm3(IS, ErrorInfo);
12526
12527 auto *CS = dyn_cast<CompoundStmt>(S);
12528 if (!CS) {
12529 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12530 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12531 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12532 return false;
12533 }
12534 if (CS->body_empty()) {
12535 ErrorInfo.Error = ErrorTy::NoStmt;
12536 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12537 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12538 return false;
12539 }
12540
12541 // { if(x == e) { x = d; } else { v = x; } }
12542 if (CS->size() == 1) {
12543 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12544 if (!IS) {
12545 ErrorInfo.Error = ErrorTy::NotIfStmt;
12546 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12547 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12548 CS->body_front()->getSourceRange();
12549 return false;
12550 }
12551
12552 return checkForm3(IS, ErrorInfo);
12553 } else if (CS->size() == 2) {
12554 auto *S1 = CS->body_front();
12555 auto *S2 = CS->body_back();
12556
12557 Stmt *UpdateStmt = nullptr;
12558 Stmt *CondUpdateStmt = nullptr;
12559 Stmt *CondExprStmt = nullptr;
12560
12561 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12562 // It could be one of the following cases:
12563 // { v = x; cond-update-stmt }
12564 // { v = x; cond-expr-stmt }
12565 // { cond-expr-stmt; v = x; }
12566 // form 45
12567 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12568 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12569 // check if form 45
12570 if (isa<IfStmt>(S2))
12571 return checkForm45(CS, ErrorInfo);
12572 // { cond-expr-stmt; v = x; }
12573 CondExprStmt = S1;
12574 UpdateStmt = S2;
12575 } else {
12576 IsPostfixUpdate = true;
12577 UpdateStmt = S1;
12578 if (isa<IfStmt>(S2)) {
12579 // { v = x; cond-update-stmt }
12580 CondUpdateStmt = S2;
12581 } else {
12582 // { v = x; cond-expr-stmt }
12583 CondExprStmt = S2;
12584 }
12585 }
12586 } else {
12587 // { cond-update-stmt v = x; }
12588 UpdateStmt = S2;
12589 CondUpdateStmt = S1;
12590 }
12591
12592 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12593 auto *IS = dyn_cast<IfStmt>(CUS);
12594 if (!IS) {
12595 ErrorInfo.Error = ErrorTy::NotIfStmt;
12596 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12597 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12598 return false;
12599 }
12600
12601 return checkCondUpdateStmt(IS, ErrorInfo);
12602 };
12603
12604 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12605 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12606 auto *BO = dyn_cast<BinaryOperator>(US);
12607 if (!BO) {
12608 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12609 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12610 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12611 return false;
12612 }
12613 if (BO->getOpcode() != BO_Assign) {
12614 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12615 ErrorInfo.ErrorLoc = BO->getExprLoc();
12616 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12617 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12618 return false;
12619 }
12620 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12621 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12622 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12623 ErrorInfo.NoteLoc = this->X->getExprLoc();
12624 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12625 ErrorInfo.NoteRange = this->X->getSourceRange();
12626 return false;
12627 }
12628
12629 this->V = BO->getLHS();
12630
12631 return true;
12632 };
12633
12634 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12635 return false;
12636 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12637 return false;
12638 if (!CheckUpdateStmt(UpdateStmt))
12639 return false;
12640 } else {
12641 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12642 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12643 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12644 return false;
12645 }
12646
12647 return checkType(ErrorInfo);
12648}
12649} // namespace
12650
12652 Stmt *AStmt,
12653 SourceLocation StartLoc,
12654 SourceLocation EndLoc) {
12655 ASTContext &Context = getASTContext();
12656 unsigned OMPVersion = getLangOpts().OpenMP;
12657 // Register location of the first atomic directive.
12658 DSAStack->addAtomicDirectiveLoc(StartLoc);
12659 if (!AStmt)
12660 return StmtError();
12661
12662 // 1.2.2 OpenMP Language Terminology
12663 // Structured block - An executable statement with a single entry at the
12664 // top and a single exit at the bottom.
12665 // The point of exit cannot be a branch out of the structured block.
12666 // longjmp() and throw() must not violate the entry/exit criteria.
12667 OpenMPClauseKind AtomicKind = OMPC_unknown;
12668 SourceLocation AtomicKindLoc;
12669 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12670 SourceLocation MemOrderLoc;
12671 bool MutexClauseEncountered = false;
12672 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12673 for (const OMPClause *C : Clauses) {
12674 switch (C->getClauseKind()) {
12675 case OMPC_read:
12676 case OMPC_write:
12677 case OMPC_update:
12678 MutexClauseEncountered = true;
12679 [[fallthrough]];
12680 case OMPC_capture:
12681 case OMPC_compare: {
12682 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12683 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12684 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12685 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12686 << getOpenMPClauseNameForDiag(AtomicKind);
12687 } else {
12688 AtomicKind = C->getClauseKind();
12689 AtomicKindLoc = C->getBeginLoc();
12690 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12691 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12692 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12693 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12694 << getOpenMPClauseNameForDiag(AtomicKind);
12695 }
12696 }
12697 break;
12698 }
12699 case OMPC_weak:
12700 case OMPC_fail: {
12701 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12702 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12703 << getOpenMPClauseNameForDiag(C->getClauseKind())
12704 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12705 return StmtError();
12706 }
12707 break;
12708 }
12709 case OMPC_seq_cst:
12710 case OMPC_acq_rel:
12711 case OMPC_acquire:
12712 case OMPC_release:
12713 case OMPC_relaxed: {
12714 if (MemOrderKind != OMPC_unknown) {
12715 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12716 << getOpenMPDirectiveName(OMPD_atomic, OMPVersion) << 0
12717 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12718 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12719 << getOpenMPClauseNameForDiag(MemOrderKind);
12720 } else {
12721 MemOrderKind = C->getClauseKind();
12722 MemOrderLoc = C->getBeginLoc();
12723 }
12724 break;
12725 }
12726 // The following clauses are allowed, but we don't need to do anything here.
12727 case OMPC_hint:
12728 break;
12729 default:
12730 llvm_unreachable("unknown clause is encountered");
12731 }
12732 }
12733 bool IsCompareCapture = false;
12734 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12735 EncounteredAtomicKinds.contains(OMPC_capture)) {
12736 IsCompareCapture = true;
12737 AtomicKind = OMPC_compare;
12738 }
12739 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12740 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12741 // release.
12742 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12743 // acquire.
12744 // If atomic-clause is update or not present then memory-order-clause must not
12745 // be acq_rel or acquire.
12746 if ((AtomicKind == OMPC_read &&
12747 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12748 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12749 AtomicKind == OMPC_unknown) &&
12750 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12751 SourceLocation Loc = AtomicKindLoc;
12752 if (AtomicKind == OMPC_unknown)
12753 Loc = StartLoc;
12754 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12755 << getOpenMPClauseNameForDiag(AtomicKind)
12756 << (AtomicKind == OMPC_unknown ? 1 : 0)
12757 << getOpenMPClauseNameForDiag(MemOrderKind);
12758 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12759 << getOpenMPClauseNameForDiag(MemOrderKind);
12760 }
12761
12762 Stmt *Body = AStmt;
12763 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12764 Body = EWC->getSubExpr();
12765
12766 Expr *X = nullptr;
12767 Expr *V = nullptr;
12768 Expr *E = nullptr;
12769 Expr *UE = nullptr;
12770 Expr *D = nullptr;
12771 Expr *CE = nullptr;
12772 Expr *R = nullptr;
12773 bool IsXLHSInRHSPart = false;
12774 bool IsPostfixUpdate = false;
12775 bool IsFailOnly = false;
12776 // OpenMP [2.12.6, atomic Construct]
12777 // In the next expressions:
12778 // * x and v (as applicable) are both l-value expressions with scalar type.
12779 // * During the execution of an atomic region, multiple syntactic
12780 // occurrences of x must designate the same storage location.
12781 // * Neither of v and expr (as applicable) may access the storage location
12782 // designated by x.
12783 // * Neither of x and expr (as applicable) may access the storage location
12784 // designated by v.
12785 // * expr is an expression with scalar type.
12786 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12787 // * binop, binop=, ++, and -- are not overloaded operators.
12788 // * The expression x binop expr must be numerically equivalent to x binop
12789 // (expr). This requirement is satisfied if the operators in expr have
12790 // precedence greater than binop, or by using parentheses around expr or
12791 // subexpressions of expr.
12792 // * The expression expr binop x must be numerically equivalent to (expr)
12793 // binop x. This requirement is satisfied if the operators in expr have
12794 // precedence equal to or greater than binop, or by using parentheses around
12795 // expr or subexpressions of expr.
12796 // * For forms that allow multiple occurrences of x, the number of times
12797 // that x is evaluated is unspecified.
12798 if (AtomicKind == OMPC_read) {
12799 enum {
12800 NotAnExpression,
12801 NotAnAssignmentOp,
12802 NotAScalarType,
12803 NotAnLValue,
12804 NoError
12805 } ErrorFound = NoError;
12806 SourceLocation ErrorLoc, NoteLoc;
12807 SourceRange ErrorRange, NoteRange;
12808 // If clause is read:
12809 // v = x;
12810 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12811 const auto *AtomicBinOp =
12812 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12813 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12814 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12815 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12816 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12817 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12818 if (!X->isLValue() || !V->isLValue()) {
12819 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12820 ErrorFound = NotAnLValue;
12821 ErrorLoc = AtomicBinOp->getExprLoc();
12822 ErrorRange = AtomicBinOp->getSourceRange();
12823 NoteLoc = NotLValueExpr->getExprLoc();
12824 NoteRange = NotLValueExpr->getSourceRange();
12825 }
12826 } else if (!X->isInstantiationDependent() ||
12827 !V->isInstantiationDependent()) {
12828 const Expr *NotScalarExpr =
12829 (X->isInstantiationDependent() || X->getType()->isScalarType())
12830 ? V
12831 : X;
12832 ErrorFound = NotAScalarType;
12833 ErrorLoc = AtomicBinOp->getExprLoc();
12834 ErrorRange = AtomicBinOp->getSourceRange();
12835 NoteLoc = NotScalarExpr->getExprLoc();
12836 NoteRange = NotScalarExpr->getSourceRange();
12837 }
12838 } else if (!AtomicBody->isInstantiationDependent()) {
12839 ErrorFound = NotAnAssignmentOp;
12840 ErrorLoc = AtomicBody->getExprLoc();
12841 ErrorRange = AtomicBody->getSourceRange();
12842 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12843 : AtomicBody->getExprLoc();
12844 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12845 : AtomicBody->getSourceRange();
12846 }
12847 } else {
12848 ErrorFound = NotAnExpression;
12849 NoteLoc = ErrorLoc = Body->getBeginLoc();
12850 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12851 }
12852 if (ErrorFound != NoError) {
12853 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12854 << ErrorRange;
12855 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12856 << ErrorFound << NoteRange;
12857 return StmtError();
12858 }
12859 if (SemaRef.CurContext->isDependentContext())
12860 V = X = nullptr;
12861 } else if (AtomicKind == OMPC_write) {
12862 enum {
12863 NotAnExpression,
12864 NotAnAssignmentOp,
12865 NotAScalarType,
12866 NotAnLValue,
12867 NoError
12868 } ErrorFound = NoError;
12869 SourceLocation ErrorLoc, NoteLoc;
12870 SourceRange ErrorRange, NoteRange;
12871 // If clause is write:
12872 // x = expr;
12873 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12874 const auto *AtomicBinOp =
12875 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12876 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12877 X = AtomicBinOp->getLHS();
12878 E = AtomicBinOp->getRHS();
12879 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12880 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
12881 if (!X->isLValue()) {
12882 ErrorFound = NotAnLValue;
12883 ErrorLoc = AtomicBinOp->getExprLoc();
12884 ErrorRange = AtomicBinOp->getSourceRange();
12885 NoteLoc = X->getExprLoc();
12886 NoteRange = X->getSourceRange();
12887 }
12888 } else if (!X->isInstantiationDependent() ||
12890 const Expr *NotScalarExpr =
12891 (X->isInstantiationDependent() || X->getType()->isScalarType())
12892 ? E
12893 : X;
12894 ErrorFound = NotAScalarType;
12895 ErrorLoc = AtomicBinOp->getExprLoc();
12896 ErrorRange = AtomicBinOp->getSourceRange();
12897 NoteLoc = NotScalarExpr->getExprLoc();
12898 NoteRange = NotScalarExpr->getSourceRange();
12899 }
12900 } else if (!AtomicBody->isInstantiationDependent()) {
12901 ErrorFound = NotAnAssignmentOp;
12902 ErrorLoc = AtomicBody->getExprLoc();
12903 ErrorRange = AtomicBody->getSourceRange();
12904 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12905 : AtomicBody->getExprLoc();
12906 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12907 : AtomicBody->getSourceRange();
12908 }
12909 } else {
12910 ErrorFound = NotAnExpression;
12911 NoteLoc = ErrorLoc = Body->getBeginLoc();
12912 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12913 }
12914 if (ErrorFound != NoError) {
12915 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12916 << ErrorRange;
12917 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12918 << ErrorFound << NoteRange;
12919 return StmtError();
12920 }
12921 if (SemaRef.CurContext->isDependentContext())
12922 E = X = nullptr;
12923 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12924 // If clause is update:
12925 // x++;
12926 // x--;
12927 // ++x;
12928 // --x;
12929 // x binop= expr;
12930 // x = x binop expr;
12931 // x = expr binop x;
12932 OpenMPAtomicUpdateChecker Checker(SemaRef);
12933 if (Checker.checkStatement(
12934 Body,
12935 (AtomicKind == OMPC_update)
12936 ? diag::err_omp_atomic_update_not_expression_statement
12937 : diag::err_omp_atomic_not_expression_statement,
12938 diag::note_omp_atomic_update))
12939 return StmtError();
12940 if (!SemaRef.CurContext->isDependentContext()) {
12941 E = Checker.getExpr();
12942 X = Checker.getX();
12943 UE = Checker.getUpdateExpr();
12944 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12945 }
12946 } else if (AtomicKind == OMPC_capture) {
12947 enum {
12948 NotAnAssignmentOp,
12949 NotACompoundStatement,
12950 NotTwoSubstatements,
12951 NotASpecificExpression,
12952 NoError
12953 } ErrorFound = NoError;
12954 SourceLocation ErrorLoc, NoteLoc;
12955 SourceRange ErrorRange, NoteRange;
12956 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12957 // If clause is a capture:
12958 // v = x++;
12959 // v = x--;
12960 // v = ++x;
12961 // v = --x;
12962 // v = x binop= expr;
12963 // v = x = x binop expr;
12964 // v = x = expr binop x;
12965 const auto *AtomicBinOp =
12966 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12967 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12968 V = AtomicBinOp->getLHS();
12969 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12970 OpenMPAtomicUpdateChecker Checker(SemaRef);
12971 if (Checker.checkStatement(
12972 Body, diag::err_omp_atomic_capture_not_expression_statement,
12973 diag::note_omp_atomic_update))
12974 return StmtError();
12975 E = Checker.getExpr();
12976 X = Checker.getX();
12977 UE = Checker.getUpdateExpr();
12978 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12979 IsPostfixUpdate = Checker.isPostfixUpdate();
12980 } else if (!AtomicBody->isInstantiationDependent()) {
12981 ErrorLoc = AtomicBody->getExprLoc();
12982 ErrorRange = AtomicBody->getSourceRange();
12983 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12984 : AtomicBody->getExprLoc();
12985 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12986 : AtomicBody->getSourceRange();
12987 ErrorFound = NotAnAssignmentOp;
12988 }
12989 if (ErrorFound != NoError) {
12990 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12991 << ErrorRange;
12992 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12993 return StmtError();
12994 }
12995 if (SemaRef.CurContext->isDependentContext())
12996 UE = V = E = X = nullptr;
12997 } else {
12998 // If clause is a capture:
12999 // { v = x; x = expr; }
13000 // { v = x; x++; }
13001 // { v = x; x--; }
13002 // { v = x; ++x; }
13003 // { v = x; --x; }
13004 // { v = x; x binop= expr; }
13005 // { v = x; x = x binop expr; }
13006 // { v = x; x = expr binop x; }
13007 // { x++; v = x; }
13008 // { x--; v = x; }
13009 // { ++x; v = x; }
13010 // { --x; v = x; }
13011 // { x binop= expr; v = x; }
13012 // { x = x binop expr; v = x; }
13013 // { x = expr binop x; v = x; }
13014 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
13015 // Check that this is { expr1; expr2; }
13016 if (CS->size() == 2) {
13017 Stmt *First = CS->body_front();
13018 Stmt *Second = CS->body_back();
13019 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
13020 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13021 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
13022 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13023 // Need to find what subexpression is 'v' and what is 'x'.
13024 OpenMPAtomicUpdateChecker Checker(SemaRef);
13025 bool IsUpdateExprFound = !Checker.checkStatement(Second);
13026 BinaryOperator *BinOp = nullptr;
13027 if (IsUpdateExprFound) {
13028 BinOp = dyn_cast<BinaryOperator>(First);
13029 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13030 }
13031 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
13032 // { v = x; x++; }
13033 // { v = x; x--; }
13034 // { v = x; ++x; }
13035 // { v = x; --x; }
13036 // { v = x; x binop= expr; }
13037 // { v = x; x = x binop expr; }
13038 // { v = x; x = expr binop x; }
13039 // Check that the first expression has form v = x.
13040 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13041 llvm::FoldingSetNodeID XId, PossibleXId;
13042 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13043 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13044 IsUpdateExprFound = XId == PossibleXId;
13045 if (IsUpdateExprFound) {
13046 V = BinOp->getLHS();
13047 X = Checker.getX();
13048 E = Checker.getExpr();
13049 UE = Checker.getUpdateExpr();
13050 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13051 IsPostfixUpdate = true;
13052 }
13053 }
13054 if (!IsUpdateExprFound) {
13055 IsUpdateExprFound = !Checker.checkStatement(First);
13056 BinOp = nullptr;
13057 if (IsUpdateExprFound) {
13058 BinOp = dyn_cast<BinaryOperator>(Second);
13059 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13060 }
13061 if (IsUpdateExprFound &&
13062 !SemaRef.CurContext->isDependentContext()) {
13063 // { x++; v = x; }
13064 // { x--; v = x; }
13065 // { ++x; v = x; }
13066 // { --x; v = x; }
13067 // { x binop= expr; v = x; }
13068 // { x = x binop expr; v = x; }
13069 // { x = expr binop x; v = x; }
13070 // Check that the second expression has form v = x.
13071 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13072 llvm::FoldingSetNodeID XId, PossibleXId;
13073 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13074 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13075 IsUpdateExprFound = XId == PossibleXId;
13076 if (IsUpdateExprFound) {
13077 V = BinOp->getLHS();
13078 X = Checker.getX();
13079 E = Checker.getExpr();
13080 UE = Checker.getUpdateExpr();
13081 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13082 IsPostfixUpdate = false;
13083 }
13084 }
13085 }
13086 if (!IsUpdateExprFound) {
13087 // { v = x; x = expr; }
13088 auto *FirstExpr = dyn_cast<Expr>(First);
13089 auto *SecondExpr = dyn_cast<Expr>(Second);
13090 if (!FirstExpr || !SecondExpr ||
13091 !(FirstExpr->isInstantiationDependent() ||
13092 SecondExpr->isInstantiationDependent())) {
13093 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
13094 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13095 ErrorFound = NotAnAssignmentOp;
13096 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13097 : First->getBeginLoc();
13098 NoteRange = ErrorRange = FirstBinOp
13099 ? FirstBinOp->getSourceRange()
13100 : SourceRange(ErrorLoc, ErrorLoc);
13101 } else {
13102 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
13103 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13104 ErrorFound = NotAnAssignmentOp;
13105 NoteLoc = ErrorLoc = SecondBinOp
13106 ? SecondBinOp->getOperatorLoc()
13107 : Second->getBeginLoc();
13108 NoteRange = ErrorRange =
13109 SecondBinOp ? SecondBinOp->getSourceRange()
13110 : SourceRange(ErrorLoc, ErrorLoc);
13111 } else {
13112 Expr *PossibleXRHSInFirst =
13113 FirstBinOp->getRHS()->IgnoreParenImpCasts();
13114 Expr *PossibleXLHSInSecond =
13115 SecondBinOp->getLHS()->IgnoreParenImpCasts();
13116 llvm::FoldingSetNodeID X1Id, X2Id;
13117 PossibleXRHSInFirst->Profile(X1Id, Context,
13118 /*Canonical=*/true);
13119 PossibleXLHSInSecond->Profile(X2Id, Context,
13120 /*Canonical=*/true);
13121 IsUpdateExprFound = X1Id == X2Id;
13122 if (IsUpdateExprFound) {
13123 V = FirstBinOp->getLHS();
13124 X = SecondBinOp->getLHS();
13125 E = SecondBinOp->getRHS();
13126 UE = nullptr;
13127 IsXLHSInRHSPart = false;
13128 IsPostfixUpdate = true;
13129 } else {
13130 ErrorFound = NotASpecificExpression;
13131 ErrorLoc = FirstBinOp->getExprLoc();
13132 ErrorRange = FirstBinOp->getSourceRange();
13133 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13134 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13135 }
13136 }
13137 }
13138 }
13139 }
13140 } else {
13141 NoteLoc = ErrorLoc = Body->getBeginLoc();
13142 NoteRange = ErrorRange =
13143 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13144 ErrorFound = NotTwoSubstatements;
13145 }
13146 } else {
13147 NoteLoc = ErrorLoc = Body->getBeginLoc();
13148 NoteRange = ErrorRange =
13149 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13150 ErrorFound = NotACompoundStatement;
13151 }
13152 }
13153 if (ErrorFound != NoError) {
13154 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
13155 << ErrorRange;
13156 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13157 return StmtError();
13158 }
13159 if (SemaRef.CurContext->isDependentContext())
13160 UE = V = E = X = nullptr;
13161 } else if (AtomicKind == OMPC_compare) {
13162 if (IsCompareCapture) {
13163 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13164 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
13165 if (!Checker.checkStmt(Body, ErrorInfo)) {
13166 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
13167 << ErrorInfo.ErrorRange;
13168 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13169 << ErrorInfo.Error << ErrorInfo.NoteRange;
13170 return StmtError();
13171 }
13172 X = Checker.getX();
13173 E = Checker.getE();
13174 D = Checker.getD();
13175 CE = Checker.getCond();
13176 V = Checker.getV();
13177 R = Checker.getR();
13178 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13179 IsXLHSInRHSPart = Checker.isXBinopExpr();
13180 IsFailOnly = Checker.isFailOnly();
13181 IsPostfixUpdate = Checker.isPostfixUpdate();
13182 } else {
13183 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13184 OpenMPAtomicCompareChecker Checker(SemaRef);
13185 if (!Checker.checkStmt(Body, ErrorInfo)) {
13186 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
13187 << ErrorInfo.ErrorRange;
13188 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13189 << ErrorInfo.Error << ErrorInfo.NoteRange;
13190 return StmtError();
13191 }
13192 X = Checker.getX();
13193 E = Checker.getE();
13194 D = Checker.getD();
13195 CE = Checker.getCond();
13196 // The weak clause may only appear if the resulting atomic operation is
13197 // an atomic conditional update for which the comparison tests for
13198 // equality. It was not possible to do this check in
13199 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
13200 // could not be performed (Clauses are not available).
13201 auto *It = find_if(Clauses, [](OMPClause *C) {
13202 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13203 });
13204 if (It != Clauses.end()) {
13205 auto *Cond = dyn_cast<BinaryOperator>(CE);
13206 if (Cond->getOpcode() != BO_EQ) {
13207 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13208 ErrorInfo.ErrorLoc = Cond->getExprLoc();
13209 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
13210 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
13211
13212 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
13213 << ErrorInfo.ErrorRange;
13214 return StmtError();
13215 }
13216 }
13217 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13218 IsXLHSInRHSPart = Checker.isXBinopExpr();
13219 }
13220 }
13221
13222 SemaRef.setFunctionHasBranchProtectedScope();
13223
13224 return OMPAtomicDirective::Create(
13225 Context, StartLoc, EndLoc, Clauses, AStmt,
13226 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
13227}
13228
13230 Stmt *AStmt,
13231 SourceLocation StartLoc,
13232 SourceLocation EndLoc) {
13233 if (!AStmt)
13234 return StmtError();
13235
13236 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target, AStmt);
13237
13238 // OpenMP [2.16, Nesting of Regions]
13239 // If specified, a teams construct must be contained within a target
13240 // construct. That target construct must contain no statements or directives
13241 // outside of the teams construct.
13242 if (DSAStack->hasInnerTeamsRegion()) {
13243 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13244 bool OMPTeamsFound = true;
13245 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
13246 auto I = CS->body_begin();
13247 while (I != CS->body_end()) {
13248 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13249 bool IsTeams = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13250 if (!IsTeams || I != CS->body_begin()) {
13251 OMPTeamsFound = false;
13252 if (IsTeams && I != CS->body_begin()) {
13253 // This is the two teams case. Since the InnerTeamsRegionLoc will
13254 // point to this second one reset the iterator to the other teams.
13255 --I;
13256 }
13257 break;
13258 }
13259 ++I;
13260 }
13261 assert(I != CS->body_end() && "Not found statement");
13262 S = *I;
13263 } else {
13264 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13265 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13266 }
13267 if (!OMPTeamsFound) {
13268 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13269 Diag(DSAStack->getInnerTeamsRegionLoc(),
13270 diag::note_omp_nested_teams_construct_here);
13271 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
13273 return StmtError();
13274 }
13275 }
13276
13277 return OMPTargetDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13278 AStmt);
13279}
13280
13282 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13283 SourceLocation EndLoc) {
13284 if (!AStmt)
13285 return StmtError();
13286
13287 setBranchProtectedScope(SemaRef, OMPD_target_parallel, AStmt);
13288
13290 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
13291 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13292}
13293
13295 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13296 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13297 if (!AStmt)
13298 return StmtError();
13299
13300 CapturedStmt *CS =
13301 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for, AStmt);
13302
13303 OMPLoopBasedDirective::HelperExprs B;
13304 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13305 // define the nested loops number.
13306 unsigned NestedLoopCount =
13307 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13308 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13309 VarsWithImplicitDSA, B);
13310 if (NestedLoopCount == 0)
13311 return StmtError();
13312
13313 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13314 return StmtError();
13315
13317 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13318 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13319}
13320
13321/// Check for existence of a map clause in the list of clauses.
13323 const OpenMPClauseKind K) {
13324 return llvm::any_of(
13325 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13326}
13327
13328template <typename... Params>
13330 const Params... ClauseTypes) {
13331 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13332}
13333
13334/// Check if the variables in the mapping clause are externally visible.
13336 for (const OMPClause *C : Clauses) {
13337 if (auto *TC = dyn_cast<OMPToClause>(C))
13338 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13339 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13340 (VD->isExternallyVisible() &&
13341 VD->getVisibility() != HiddenVisibility);
13342 });
13343 else if (auto *FC = dyn_cast<OMPFromClause>(C))
13344 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13345 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13346 (VD->isExternallyVisible() &&
13347 VD->getVisibility() != HiddenVisibility);
13348 });
13349 }
13350
13351 return true;
13352}
13353
13356 Stmt *AStmt, SourceLocation StartLoc,
13357 SourceLocation EndLoc) {
13358 if (!AStmt)
13359 return StmtError();
13360
13361 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13362
13363 // OpenMP [2.12.2, target data Construct, Restrictions]
13364 // At least one map, use_device_addr or use_device_ptr clause must appear on
13365 // the directive.
13366 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13367 (getLangOpts().OpenMP < 50 ||
13368 !hasClauses(Clauses, OMPC_use_device_addr))) {
13369 StringRef Expected;
13370 if (getLangOpts().OpenMP < 50)
13371 Expected = "'map' or 'use_device_ptr'";
13372 else
13373 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13374 unsigned OMPVersion = getLangOpts().OpenMP;
13375 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13376 << Expected << getOpenMPDirectiveName(OMPD_target_data, OMPVersion);
13377 return StmtError();
13378 }
13379
13380 SemaRef.setFunctionHasBranchProtectedScope();
13381
13382 return OMPTargetDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13383 Clauses, AStmt);
13384}
13385
13387 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13388 SourceLocation EndLoc, Stmt *AStmt) {
13389 if (!AStmt)
13390 return StmtError();
13391
13392 setBranchProtectedScope(SemaRef, OMPD_target_enter_data, AStmt);
13393
13394 // OpenMP [2.10.2, Restrictions, p. 99]
13395 // At least one map clause must appear on the directive.
13396 if (!hasClauses(Clauses, OMPC_map)) {
13397 unsigned OMPVersion = getLangOpts().OpenMP;
13398 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13399 << "'map'"
13400 << getOpenMPDirectiveName(OMPD_target_enter_data, OMPVersion);
13401 return StmtError();
13402 }
13403
13404 return OMPTargetEnterDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13405 Clauses, AStmt);
13406}
13407
13409 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13410 SourceLocation EndLoc, Stmt *AStmt) {
13411 if (!AStmt)
13412 return StmtError();
13413
13414 setBranchProtectedScope(SemaRef, OMPD_target_exit_data, AStmt);
13415
13416 // OpenMP [2.10.3, Restrictions, p. 102]
13417 // At least one map clause must appear on the directive.
13418 if (!hasClauses(Clauses, OMPC_map)) {
13419 unsigned OMPVersion = getLangOpts().OpenMP;
13420 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13421 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data, OMPVersion);
13422 return StmtError();
13423 }
13424
13425 return OMPTargetExitDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13426 Clauses, AStmt);
13427}
13428
13430 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13431 SourceLocation EndLoc, Stmt *AStmt) {
13432 if (!AStmt)
13433 return StmtError();
13434
13435 setBranchProtectedScope(SemaRef, OMPD_target_update, AStmt);
13436
13437 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13438 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13439 return StmtError();
13440 }
13441
13442 if (!isClauseMappable(Clauses)) {
13443 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13444 return StmtError();
13445 }
13446
13447 return OMPTargetUpdateDirective::Create(getASTContext(), StartLoc, EndLoc,
13448 Clauses, AStmt);
13449}
13450
13451/// This checks whether a \p ClauseType clause \p C has at most \p Max
13452/// expression. If not, a diag of number \p Diag will be emitted.
13453template <typename ClauseType>
13454static bool checkNumExprsInClause(SemaBase &SemaRef,
13455 ArrayRef<OMPClause *> Clauses,
13456 unsigned MaxNum, unsigned Diag) {
13457 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13458 if (ClauseItr == Clauses.end())
13459 return true;
13460 const auto *C = cast<ClauseType>(*ClauseItr);
13461 auto VarList = C->getVarRefs();
13462 if (VarList.size() > MaxNum) {
13463 SemaRef.Diag(VarList[MaxNum]->getBeginLoc(), Diag)
13464 << getOpenMPClauseNameForDiag(C->getClauseKind());
13465 return false;
13466 }
13467 return true;
13468}
13469
13471 Stmt *AStmt,
13472 SourceLocation StartLoc,
13473 SourceLocation EndLoc) {
13474 if (!AStmt)
13475 return StmtError();
13476
13478 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
13480 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
13481 return StmtError();
13482
13483 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13484 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13485 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13486
13487 setBranchProtectedScope(SemaRef, OMPD_teams, AStmt);
13488
13489 DSAStack->setParentTeamsRegionLoc(StartLoc);
13490
13491 return OMPTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13492 AStmt);
13493}
13494
13496 SourceLocation StartLoc, SourceLocation EndLoc,
13497 OpenMPDirectiveKind CancelRegion) {
13498 if (DSAStack->isParentNowaitRegion()) {
13499 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13500 return StmtError();
13501 }
13502 if (DSAStack->isParentOrderedRegion()) {
13503 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13504 return StmtError();
13505 }
13507 EndLoc, CancelRegion);
13508}
13509
13511 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13512 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13513 if (DSAStack->isParentNowaitRegion()) {
13514 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13515 return StmtError();
13516 }
13517 if (DSAStack->isParentOrderedRegion()) {
13518 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13519 return StmtError();
13520 }
13521 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13522 return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13523 CancelRegion);
13524}
13525
13527 ArrayRef<OMPClause *> Clauses) {
13528 const OMPClause *ReductionClause = nullptr;
13529 const OMPClause *NogroupClause = nullptr;
13530 for (const OMPClause *C : Clauses) {
13531 if (C->getClauseKind() == OMPC_reduction) {
13532 ReductionClause = C;
13533 if (NogroupClause)
13534 break;
13535 continue;
13536 }
13537 if (C->getClauseKind() == OMPC_nogroup) {
13538 NogroupClause = C;
13539 if (ReductionClause)
13540 break;
13541 continue;
13542 }
13543 }
13544 if (ReductionClause && NogroupClause) {
13545 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13546 << SourceRange(NogroupClause->getBeginLoc(),
13547 NogroupClause->getEndLoc());
13548 return true;
13549 }
13550 return false;
13551}
13552
13554 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13555 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13556 if (!AStmt)
13557 return StmtError();
13558
13559 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13560 OMPLoopBasedDirective::HelperExprs B;
13561 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13562 // define the nested loops number.
13563 unsigned NestedLoopCount =
13564 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13565 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13566 *DSAStack, VarsWithImplicitDSA, B);
13567 if (NestedLoopCount == 0)
13568 return StmtError();
13569
13570 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13571 "omp for loop exprs were not built");
13572
13573 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13574 // The grainsize clause and num_tasks clause are mutually exclusive and may
13575 // not appear on the same taskloop directive.
13577 {OMPC_grainsize, OMPC_num_tasks}))
13578 return StmtError();
13579 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13580 // If a reduction clause is present on the taskloop directive, the nogroup
13581 // clause must not be specified.
13583 return StmtError();
13584
13585 SemaRef.setFunctionHasBranchProtectedScope();
13586 return OMPTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13587 NestedLoopCount, Clauses, AStmt, B,
13588 DSAStack->isCancelRegion());
13589}
13590
13592 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13593 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13594 if (!AStmt)
13595 return StmtError();
13596
13597 CapturedStmt *CS =
13598 setBranchProtectedScope(SemaRef, OMPD_taskloop_simd, AStmt);
13599
13600 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13601 OMPLoopBasedDirective::HelperExprs B;
13602 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13603 // define the nested loops number.
13604 unsigned NestedLoopCount =
13605 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13606 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13607 VarsWithImplicitDSA, B);
13608 if (NestedLoopCount == 0)
13609 return StmtError();
13610
13611 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13612 return StmtError();
13613
13614 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13615 // The grainsize clause and num_tasks clause are mutually exclusive and may
13616 // not appear on the same taskloop directive.
13618 {OMPC_grainsize, OMPC_num_tasks}))
13619 return StmtError();
13620 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13621 // If a reduction clause is present on the taskloop directive, the nogroup
13622 // clause must not be specified.
13624 return StmtError();
13626 return StmtError();
13627
13628 return OMPTaskLoopSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13629 NestedLoopCount, Clauses, AStmt, B);
13630}
13631
13633 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13634 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13635 if (!AStmt)
13636 return StmtError();
13637
13638 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13639 OMPLoopBasedDirective::HelperExprs B;
13640 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13641 // define the nested loops number.
13642 unsigned NestedLoopCount =
13643 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13644 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13645 *DSAStack, VarsWithImplicitDSA, B);
13646 if (NestedLoopCount == 0)
13647 return StmtError();
13648
13649 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13650 "omp for loop exprs were not built");
13651
13652 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13653 // The grainsize clause and num_tasks clause are mutually exclusive and may
13654 // not appear on the same taskloop directive.
13656 {OMPC_grainsize, OMPC_num_tasks}))
13657 return StmtError();
13658 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13659 // If a reduction clause is present on the taskloop directive, the nogroup
13660 // clause must not be specified.
13662 return StmtError();
13663
13664 SemaRef.setFunctionHasBranchProtectedScope();
13665 return OMPMasterTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13666 NestedLoopCount, Clauses, AStmt, B,
13667 DSAStack->isCancelRegion());
13668}
13669
13671 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13672 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13673 if (!AStmt)
13674 return StmtError();
13675
13676 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13677 OMPLoopBasedDirective::HelperExprs B;
13678 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13679 // define the nested loops number.
13680 unsigned NestedLoopCount =
13681 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13682 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13683 *DSAStack, VarsWithImplicitDSA, B);
13684 if (NestedLoopCount == 0)
13685 return StmtError();
13686
13687 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13688 "omp for loop exprs were not built");
13689
13690 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13691 // The grainsize clause and num_tasks clause are mutually exclusive and may
13692 // not appear on the same taskloop directive.
13694 {OMPC_grainsize, OMPC_num_tasks}))
13695 return StmtError();
13696 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13697 // If a reduction clause is present on the taskloop directive, the nogroup
13698 // clause must not be specified.
13700 return StmtError();
13701
13702 SemaRef.setFunctionHasBranchProtectedScope();
13703 return OMPMaskedTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13704 NestedLoopCount, Clauses, AStmt, B,
13705 DSAStack->isCancelRegion());
13706}
13707
13709 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13710 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13711 if (!AStmt)
13712 return StmtError();
13713
13714 CapturedStmt *CS =
13715 setBranchProtectedScope(SemaRef, OMPD_master_taskloop_simd, AStmt);
13716
13717 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13718 OMPLoopBasedDirective::HelperExprs B;
13719 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13720 // define the nested loops number.
13721 unsigned NestedLoopCount =
13722 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13723 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13724 VarsWithImplicitDSA, B);
13725 if (NestedLoopCount == 0)
13726 return StmtError();
13727
13728 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13729 return StmtError();
13730
13731 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13732 // The grainsize clause and num_tasks clause are mutually exclusive and may
13733 // not appear on the same taskloop directive.
13735 {OMPC_grainsize, OMPC_num_tasks}))
13736 return StmtError();
13737 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13738 // If a reduction clause is present on the taskloop directive, the nogroup
13739 // clause must not be specified.
13741 return StmtError();
13743 return StmtError();
13744
13746 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13747}
13748
13750 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13751 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13752 if (!AStmt)
13753 return StmtError();
13754
13755 CapturedStmt *CS =
13756 setBranchProtectedScope(SemaRef, OMPD_masked_taskloop_simd, AStmt);
13757
13758 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13759 OMPLoopBasedDirective::HelperExprs B;
13760 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13761 // define the nested loops number.
13762 unsigned NestedLoopCount =
13763 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13764 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13765 VarsWithImplicitDSA, B);
13766 if (NestedLoopCount == 0)
13767 return StmtError();
13768
13769 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13770 return StmtError();
13771
13772 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13773 // The grainsize clause and num_tasks clause are mutually exclusive and may
13774 // not appear on the same taskloop directive.
13776 {OMPC_grainsize, OMPC_num_tasks}))
13777 return StmtError();
13778 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13779 // If a reduction clause is present on the taskloop directive, the nogroup
13780 // clause must not be specified.
13782 return StmtError();
13784 return StmtError();
13785
13787 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13788}
13789
13791 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13792 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13793 if (!AStmt)
13794 return StmtError();
13795
13796 CapturedStmt *CS =
13797 setBranchProtectedScope(SemaRef, OMPD_parallel_master_taskloop, AStmt);
13798
13799 OMPLoopBasedDirective::HelperExprs B;
13800 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13801 // define the nested loops number.
13802 unsigned NestedLoopCount = checkOpenMPLoop(
13803 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13804 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13805 VarsWithImplicitDSA, B);
13806 if (NestedLoopCount == 0)
13807 return StmtError();
13808
13809 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13810 "omp for loop exprs were not built");
13811
13812 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13813 // The grainsize clause and num_tasks clause are mutually exclusive and may
13814 // not appear on the same taskloop directive.
13816 {OMPC_grainsize, OMPC_num_tasks}))
13817 return StmtError();
13818 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13819 // If a reduction clause is present on the taskloop directive, the nogroup
13820 // clause must not be specified.
13822 return StmtError();
13823
13825 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13826 DSAStack->isCancelRegion());
13827}
13828
13830 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13831 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13832 if (!AStmt)
13833 return StmtError();
13834
13835 CapturedStmt *CS =
13836 setBranchProtectedScope(SemaRef, OMPD_parallel_masked_taskloop, AStmt);
13837
13838 OMPLoopBasedDirective::HelperExprs B;
13839 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13840 // define the nested loops number.
13841 unsigned NestedLoopCount = checkOpenMPLoop(
13842 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13843 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13844 VarsWithImplicitDSA, B);
13845 if (NestedLoopCount == 0)
13846 return StmtError();
13847
13848 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13849 "omp for loop exprs were not built");
13850
13851 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13852 // The grainsize clause and num_tasks clause are mutually exclusive and may
13853 // not appear on the same taskloop directive.
13855 {OMPC_grainsize, OMPC_num_tasks}))
13856 return StmtError();
13857 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13858 // If a reduction clause is present on the taskloop directive, the nogroup
13859 // clause must not be specified.
13861 return StmtError();
13862
13864 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13865 DSAStack->isCancelRegion());
13866}
13867
13869 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13870 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13871 if (!AStmt)
13872 return StmtError();
13873
13875 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13876
13877 OMPLoopBasedDirective::HelperExprs B;
13878 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13879 // define the nested loops number.
13880 unsigned NestedLoopCount = checkOpenMPLoop(
13881 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13882 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13883 VarsWithImplicitDSA, B);
13884 if (NestedLoopCount == 0)
13885 return StmtError();
13886
13887 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13888 return StmtError();
13889
13890 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13891 // The grainsize clause and num_tasks clause are mutually exclusive and may
13892 // not appear on the same taskloop directive.
13894 {OMPC_grainsize, OMPC_num_tasks}))
13895 return StmtError();
13896 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13897 // If a reduction clause is present on the taskloop directive, the nogroup
13898 // clause must not be specified.
13900 return StmtError();
13902 return StmtError();
13903
13905 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13906}
13907
13909 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13910 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13911 if (!AStmt)
13912 return StmtError();
13913
13915 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13916
13917 OMPLoopBasedDirective::HelperExprs B;
13918 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13919 // define the nested loops number.
13920 unsigned NestedLoopCount = checkOpenMPLoop(
13921 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13922 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13923 VarsWithImplicitDSA, B);
13924 if (NestedLoopCount == 0)
13925 return StmtError();
13926
13927 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13928 return StmtError();
13929
13930 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13931 // The grainsize clause and num_tasks clause are mutually exclusive and may
13932 // not appear on the same taskloop directive.
13934 {OMPC_grainsize, OMPC_num_tasks}))
13935 return StmtError();
13936 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13937 // If a reduction clause is present on the taskloop directive, the nogroup
13938 // clause must not be specified.
13940 return StmtError();
13942 return StmtError();
13943
13945 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13946}
13947
13949 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13950 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13951 if (!AStmt)
13952 return StmtError();
13953
13954 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13955 OMPLoopBasedDirective::HelperExprs B;
13956 // In presence of clause 'collapse' with number of loops, it will
13957 // define the nested loops number.
13958 unsigned NestedLoopCount =
13959 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
13960 nullptr /*ordered not a clause on distribute*/, AStmt,
13961 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13962 if (NestedLoopCount == 0)
13963 return StmtError();
13964
13965 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13966 "omp for loop exprs were not built");
13967
13968 SemaRef.setFunctionHasBranchProtectedScope();
13969 auto *DistributeDirective = OMPDistributeDirective::Create(
13970 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13971 return DistributeDirective;
13972}
13973
13975 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13976 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13977 if (!AStmt)
13978 return StmtError();
13979
13980 CapturedStmt *CS =
13981 setBranchProtectedScope(SemaRef, OMPD_distribute_parallel_for, AStmt);
13982
13983 OMPLoopBasedDirective::HelperExprs B;
13984 // In presence of clause 'collapse' with number of loops, it will
13985 // define the nested loops number.
13986 unsigned NestedLoopCount = checkOpenMPLoop(
13987 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13988 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13989 VarsWithImplicitDSA, B);
13990 if (NestedLoopCount == 0)
13991 return StmtError();
13992
13993 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13994 "omp for loop exprs were not built");
13995
13997 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13998 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13999}
14000
14002 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14003 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14004 if (!AStmt)
14005 return StmtError();
14006
14008 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
14009
14010 OMPLoopBasedDirective::HelperExprs B;
14011 // In presence of clause 'collapse' with number of loops, it will
14012 // define the nested loops number.
14013 unsigned NestedLoopCount = checkOpenMPLoop(
14014 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14015 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14016 VarsWithImplicitDSA, B);
14017 if (NestedLoopCount == 0)
14018 return StmtError();
14019
14020 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14021 return StmtError();
14022
14024 return StmtError();
14025
14027 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14028}
14029
14031 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14032 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14033 if (!AStmt)
14034 return StmtError();
14035
14036 CapturedStmt *CS =
14037 setBranchProtectedScope(SemaRef, OMPD_distribute_simd, AStmt);
14038
14039 OMPLoopBasedDirective::HelperExprs B;
14040 // In presence of clause 'collapse' with number of loops, it will
14041 // define the nested loops number.
14042 unsigned NestedLoopCount =
14043 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
14044 nullptr /*ordered not a clause on distribute*/, CS,
14045 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14046 if (NestedLoopCount == 0)
14047 return StmtError();
14048
14049 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14050 return StmtError();
14051
14053 return StmtError();
14054
14055 return OMPDistributeSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
14056 NestedLoopCount, Clauses, AStmt, B);
14057}
14058
14060 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14061 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14062 if (!AStmt)
14063 return StmtError();
14064
14065 CapturedStmt *CS =
14066 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for_simd, AStmt);
14067
14068 OMPLoopBasedDirective::HelperExprs B;
14069 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14070 // define the nested loops number.
14071 unsigned NestedLoopCount = checkOpenMPLoop(
14072 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
14073 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
14074 VarsWithImplicitDSA, B);
14075 if (NestedLoopCount == 0)
14076 return StmtError();
14077
14078 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14079 return StmtError();
14080
14082 return StmtError();
14083
14085 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14086}
14087
14089 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14090 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14091 if (!AStmt)
14092 return StmtError();
14093
14094 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target_simd, AStmt);
14095
14096 OMPLoopBasedDirective::HelperExprs B;
14097 // In presence of clause 'collapse' with number of loops, it will define the
14098 // nested loops number.
14099 unsigned NestedLoopCount =
14100 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
14101 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
14102 VarsWithImplicitDSA, B);
14103 if (NestedLoopCount == 0)
14104 return StmtError();
14105
14106 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14107 return StmtError();
14108
14110 return StmtError();
14111
14112 return OMPTargetSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
14113 NestedLoopCount, Clauses, AStmt, B);
14114}
14115
14117 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14118 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14119 if (!AStmt)
14120 return StmtError();
14121
14122 CapturedStmt *CS =
14123 setBranchProtectedScope(SemaRef, OMPD_teams_distribute, AStmt);
14124
14125 OMPLoopBasedDirective::HelperExprs B;
14126 // In presence of clause 'collapse' with number of loops, it will
14127 // define the nested loops number.
14128 unsigned NestedLoopCount =
14129 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
14130 nullptr /*ordered not a clause on distribute*/, CS,
14131 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14132 if (NestedLoopCount == 0)
14133 return StmtError();
14134
14135 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14136 "omp teams distribute loop exprs were not built");
14137
14138 DSAStack->setParentTeamsRegionLoc(StartLoc);
14139
14141 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14142}
14143
14145 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14146 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14147 if (!AStmt)
14148 return StmtError();
14149
14150 CapturedStmt *CS =
14151 setBranchProtectedScope(SemaRef, OMPD_teams_distribute_simd, AStmt);
14152
14153 OMPLoopBasedDirective::HelperExprs B;
14154 // In presence of clause 'collapse' with number of loops, it will
14155 // define the nested loops number.
14156 unsigned NestedLoopCount = checkOpenMPLoop(
14157 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14158 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14159 VarsWithImplicitDSA, B);
14160 if (NestedLoopCount == 0)
14161 return StmtError();
14162
14163 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14164 return StmtError();
14165
14167 return StmtError();
14168
14169 DSAStack->setParentTeamsRegionLoc(StartLoc);
14170
14172 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14173}
14174
14176 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14177 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14178 if (!AStmt)
14179 return StmtError();
14180
14182 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
14183
14184 OMPLoopBasedDirective::HelperExprs B;
14185 // In presence of clause 'collapse' with number of loops, it will
14186 // define the nested loops number.
14187 unsigned NestedLoopCount = checkOpenMPLoop(
14188 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14189 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14190 VarsWithImplicitDSA, B);
14191 if (NestedLoopCount == 0)
14192 return StmtError();
14193
14194 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14195 return StmtError();
14196
14198 return StmtError();
14199
14200 DSAStack->setParentTeamsRegionLoc(StartLoc);
14201
14203 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14204}
14205
14207 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14208 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14209 if (!AStmt)
14210 return StmtError();
14211
14213 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
14214
14215 OMPLoopBasedDirective::HelperExprs B;
14216 // In presence of clause 'collapse' with number of loops, it will
14217 // define the nested loops number.
14218 unsigned NestedLoopCount = checkOpenMPLoop(
14219 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14220 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14221 VarsWithImplicitDSA, B);
14222
14223 if (NestedLoopCount == 0)
14224 return StmtError();
14225
14226 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14227 "omp for loop exprs were not built");
14228
14229 DSAStack->setParentTeamsRegionLoc(StartLoc);
14230
14232 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14233 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14234}
14235
14237 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14238 SourceLocation EndLoc) {
14239 if (!AStmt)
14240 return StmtError();
14241
14242 setBranchProtectedScope(SemaRef, OMPD_target_teams, AStmt);
14243
14244 const OMPClause *BareClause = nullptr;
14245 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) &&
14246 hasClauses(Clauses, OMPC_thread_limit);
14247 bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) {
14248 BareClause = C;
14249 return C->getClauseKind() == OMPC_ompx_bare;
14250 });
14251
14252 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14253 Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
14254 return StmtError();
14255 }
14256
14257 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
14258 unsigned DiagNo = HasBareClause
14259 ? diag::err_ompx_more_than_three_expr_not_allowed
14260 : diag::err_omp_multi_expr_not_allowed;
14261 if (!checkNumExprsInClause<OMPNumTeamsClause>(*this, Clauses,
14262 ClauseMaxNumExprs, DiagNo) ||
14264 ClauseMaxNumExprs, DiagNo))
14265 return StmtError();
14266
14267 return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc,
14268 Clauses, AStmt);
14269}
14270
14272 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14273 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14274 if (!AStmt)
14275 return StmtError();
14276
14278 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14280 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14281 return StmtError();
14282
14283 CapturedStmt *CS =
14284 setBranchProtectedScope(SemaRef, OMPD_target_teams_distribute, AStmt);
14285
14286 OMPLoopBasedDirective::HelperExprs B;
14287 // In presence of clause 'collapse' with number of loops, it will
14288 // define the nested loops number.
14289 unsigned NestedLoopCount = checkOpenMPLoop(
14290 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14291 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14292 VarsWithImplicitDSA, B);
14293 if (NestedLoopCount == 0)
14294 return StmtError();
14295
14296 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14297 "omp target teams distribute loop exprs were not built");
14298
14300 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14301}
14302
14304 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14305 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14306 if (!AStmt)
14307 return StmtError();
14308
14310 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14312 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14313 return StmtError();
14314
14316 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14317
14318 OMPLoopBasedDirective::HelperExprs B;
14319 // In presence of clause 'collapse' with number of loops, it will
14320 // define the nested loops number.
14321 unsigned NestedLoopCount = checkOpenMPLoop(
14322 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14323 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14324 VarsWithImplicitDSA, B);
14325 if (NestedLoopCount == 0)
14326 return StmtError();
14327
14328 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14329 return StmtError();
14330
14332 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14333 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
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_simd, 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 =
14355 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14356 getCollapseNumberExpr(Clauses),
14357 nullptr /*ordered not a clause on distribute*/, CS,
14358 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14359 if (NestedLoopCount == 0)
14360 return StmtError();
14361
14362 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14363 return StmtError();
14364
14366 return StmtError();
14367
14369 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14370}
14371
14373 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14374 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14375 if (!AStmt)
14376 return StmtError();
14377
14379 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14381 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14382 return StmtError();
14383
14385 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14386
14387 OMPLoopBasedDirective::HelperExprs B;
14388 // In presence of clause 'collapse' with number of loops, it will
14389 // define the nested loops number.
14390 unsigned NestedLoopCount = checkOpenMPLoop(
14391 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14392 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14393 VarsWithImplicitDSA, B);
14394 if (NestedLoopCount == 0)
14395 return StmtError();
14396
14397 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14398 return StmtError();
14399
14401 return StmtError();
14402
14404 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14405}
14406
14407/// Updates OriginalInits by checking Transform against loop transformation
14408/// directives and appending their pre-inits if a match is found.
14410 SmallVectorImpl<Stmt *> &PreInits) {
14411 Stmt *Dir = Transform->getDirective();
14412 switch (Dir->getStmtClass()) {
14413#define STMT(CLASS, PARENT)
14414#define ABSTRACT_STMT(CLASS)
14415#define COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT) \
14416 case Stmt::CLASS##Class: \
14417 appendFlattenedStmtList(PreInits, \
14418 static_cast<const CLASS *>(Dir)->getPreInits()); \
14419 break;
14420#define OMPCANONICALLOOPNESTTRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14421 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14422#define OMPCANONICALLOOPSEQUENCETRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14423 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14424#include "clang/AST/StmtNodes.inc"
14425#undef COMMON_OMP_LOOP_TRANSFORMATION
14426 default:
14427 llvm_unreachable("Not a loop transformation");
14428 }
14429}
14430
14431bool SemaOpenMP::checkTransformableLoopNest(
14432 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14434 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *>> &OriginalInits) {
14435 OriginalInits.emplace_back();
14436 bool Result = OMPLoopBasedDirective::doForAllLoops(
14437 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14438 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14439 Stmt *CurStmt) {
14440 VarsWithInheritedDSAType TmpDSA;
14441 unsigned SingleNumLoops =
14442 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14443 TmpDSA, LoopHelpers[Cnt]);
14444 if (SingleNumLoops == 0)
14445 return true;
14446 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14447 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14448 OriginalInits.back().push_back(For->getInit());
14449 Body = For->getBody();
14450 } else {
14451 assert(isa<CXXForRangeStmt>(CurStmt) &&
14452 "Expected canonical for or range-based for loops.");
14453 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14454 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14455 Body = CXXFor->getBody();
14456 }
14457 OriginalInits.emplace_back();
14458 return false;
14459 },
14460 [&OriginalInits](OMPLoopTransformationDirective *Transform) {
14461 updatePreInits(Transform, OriginalInits.back());
14462 });
14463 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14464 OriginalInits.pop_back();
14465 return Result;
14466}
14467
14468/// Counts the total number of OpenMP canonical nested loops, including the
14469/// outermost loop (the original loop). PRECONDITION of this visitor is that it
14470/// must be invoked from the original loop to be analyzed. The traversal stops
14471/// for Decl's and Expr's given that they may contain inner loops that must not
14472/// be counted.
14473///
14474/// Example AST structure for the code:
14475///
14476/// int main() {
14477/// #pragma omp fuse
14478/// {
14479/// for (int i = 0; i < 100; i++) { <-- Outer loop
14480/// []() {
14481/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (1)
14482/// };
14483/// for(int j = 0; j < 5; ++j) {} <-- Inner loop
14484/// }
14485/// for (int r = 0; i < 100; i++) { <-- Outer loop
14486/// struct LocalClass {
14487/// void bar() {
14488/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (2)
14489/// }
14490/// };
14491/// for(int k = 0; k < 10; ++k) {} <-- Inner loop
14492/// {x = 5; for(k = 0; k < 10; ++k) x += k; x}; <-- NOT A LOOP (3)
14493/// }
14494/// }
14495/// }
14496/// (1) because in a different function (here: a lambda)
14497/// (2) because in a different function (here: class method)
14498/// (3) because considered to be intervening-code of non-perfectly nested loop
14499/// Result: Loop 'i' contains 2 loops, Loop 'r' also contains 2 loops.
14501private:
14502 unsigned NestedLoopCount = 0;
14503
14504public:
14505 explicit NestedLoopCounterVisitor() = default;
14506
14507 unsigned getNestedLoopCount() const { return NestedLoopCount; }
14508
14509 bool VisitForStmt(ForStmt *FS) override {
14510 ++NestedLoopCount;
14511 return true;
14512 }
14513
14515 ++NestedLoopCount;
14516 return true;
14517 }
14518
14519 bool TraverseStmt(Stmt *S) override {
14520 if (!S)
14521 return true;
14522
14523 // Skip traversal of all expressions, including special cases like
14524 // LambdaExpr, StmtExpr, BlockExpr, and RequiresExpr. These expressions
14525 // may contain inner statements (and even loops), but they are not part
14526 // of the syntactic body of the surrounding loop structure.
14527 // Therefore must not be counted.
14528 if (isa<Expr>(S))
14529 return true;
14530
14531 // Only recurse into CompoundStmt (block {}) and loop bodies.
14534 }
14535
14536 // Stop traversal of the rest of statements, that break perfect
14537 // loop nesting, such as control flow (IfStmt, SwitchStmt...).
14538 return true;
14539 }
14540
14541 bool TraverseDecl(Decl *D) override {
14542 // Stop in the case of finding a declaration, it is not important
14543 // in order to find nested loops (Possible CXXRecordDecl, RecordDecl,
14544 // FunctionDecl...).
14545 return true;
14546 }
14547};
14548
14549bool SemaOpenMP::analyzeLoopSequence(Stmt *LoopSeqStmt,
14550 LoopSequenceAnalysis &SeqAnalysis,
14551 ASTContext &Context,
14552 OpenMPDirectiveKind Kind) {
14554 // Helper Lambda to handle storing initialization and body statements for
14555 // both ForStmt and CXXForRangeStmt.
14556 auto StoreLoopStatements = [](LoopAnalysis &Analysis, Stmt *LoopStmt) {
14557 if (auto *For = dyn_cast<ForStmt>(LoopStmt)) {
14558 Analysis.OriginalInits.push_back(For->getInit());
14559 Analysis.TheForStmt = For;
14560 } else {
14561 auto *CXXFor = cast<CXXForRangeStmt>(LoopStmt);
14562 Analysis.OriginalInits.push_back(CXXFor->getBeginStmt());
14563 Analysis.TheForStmt = CXXFor;
14564 }
14565 };
14566
14567 // Helper lambda functions to encapsulate the processing of different
14568 // derivations of the canonical loop sequence grammar
14569 // Modularized code for handling loop generation and transformations.
14570 auto AnalyzeLoopGeneration = [&](Stmt *Child) {
14571 auto *LoopTransform = cast<OMPLoopTransformationDirective>(Child);
14572 Stmt *TransformedStmt = LoopTransform->getTransformedStmt();
14573 unsigned NumGeneratedTopLevelLoops =
14574 LoopTransform->getNumGeneratedTopLevelLoops();
14575 // Handle the case where transformed statement is not available due to
14576 // dependent contexts
14577 if (!TransformedStmt) {
14578 if (NumGeneratedTopLevelLoops > 0) {
14579 SeqAnalysis.LoopSeqSize += NumGeneratedTopLevelLoops;
14580 return true;
14581 }
14582 // Unroll full (0 loops produced)
14583 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14584 << 0 << getOpenMPDirectiveName(Kind);
14585 return false;
14586 }
14587 // Handle loop transformations with multiple loop nests
14588 // Unroll full
14589 if (!NumGeneratedTopLevelLoops) {
14590 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14591 << 0 << getOpenMPDirectiveName(Kind);
14592 return false;
14593 }
14594 // Loop transformatons such as split or loopranged fuse
14595 if (NumGeneratedTopLevelLoops > 1) {
14596 // Get the preinits related to this loop sequence generating
14597 // loop transformation (i.e loopranged fuse, split...)
14598 // These preinits differ slightly from regular inits/pre-inits related
14599 // to single loop generating loop transformations (interchange, unroll)
14600 // given that they are not bounded to a particular loop nest
14601 // so they need to be treated independently
14602 updatePreInits(LoopTransform, SeqAnalysis.LoopSequencePreInits);
14603 return analyzeLoopSequence(TransformedStmt, SeqAnalysis, Context, Kind);
14604 }
14605 // Vast majority: (Tile, Unroll, Stripe, Reverse, Interchange, Fuse all)
14606 // Process the transformed loop statement
14607 LoopAnalysis &NewTransformedSingleLoop =
14608 SeqAnalysis.Loops.emplace_back(Child);
14609 unsigned IsCanonical = checkOpenMPLoop(
14610 Kind, nullptr, nullptr, TransformedStmt, SemaRef, *DSAStack, TmpDSA,
14611 NewTransformedSingleLoop.HelperExprs);
14612
14613 if (!IsCanonical)
14614 return false;
14615
14616 StoreLoopStatements(NewTransformedSingleLoop, TransformedStmt);
14617 updatePreInits(LoopTransform, NewTransformedSingleLoop.TransformsPreInits);
14618
14619 SeqAnalysis.LoopSeqSize++;
14620 return true;
14621 };
14622
14623 // Modularized code for handling regular canonical loops.
14624 auto AnalyzeRegularLoop = [&](Stmt *Child) {
14625 LoopAnalysis &NewRegularLoop = SeqAnalysis.Loops.emplace_back(Child);
14626 unsigned IsCanonical =
14627 checkOpenMPLoop(Kind, nullptr, nullptr, Child, SemaRef, *DSAStack,
14628 TmpDSA, NewRegularLoop.HelperExprs);
14629
14630 if (!IsCanonical)
14631 return false;
14632
14633 StoreLoopStatements(NewRegularLoop, Child);
14634 NestedLoopCounterVisitor NLCV;
14635 NLCV.TraverseStmt(Child);
14636 return true;
14637 };
14638
14639 // High level grammar validation.
14640 for (Stmt *Child : LoopSeqStmt->children()) {
14641 if (!Child)
14642 continue;
14643 // Skip over non-loop-sequence statements.
14644 if (!LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14645 Child = Child->IgnoreContainers();
14646 // Ignore empty compound statement.
14647 if (!Child)
14648 continue;
14649 // In the case of a nested loop sequence ignoring containers would not
14650 // be enough, a recurisve transversal of the loop sequence is required.
14651 if (isa<CompoundStmt>(Child)) {
14652 if (!analyzeLoopSequence(Child, SeqAnalysis, Context, Kind))
14653 return false;
14654 // Already been treated, skip this children
14655 continue;
14656 }
14657 }
14658 // Regular loop sequence handling.
14659 if (LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14660 if (LoopAnalysis::isLoopTransformation(Child)) {
14661 if (!AnalyzeLoopGeneration(Child))
14662 return false;
14663 // AnalyzeLoopGeneration updates SeqAnalysis.LoopSeqSize accordingly.
14664 } else {
14665 if (!AnalyzeRegularLoop(Child))
14666 return false;
14667 SeqAnalysis.LoopSeqSize++;
14668 }
14669 } else {
14670 // Report error for invalid statement inside canonical loop sequence.
14671 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14672 << 0 << getOpenMPDirectiveName(Kind);
14673 return false;
14674 }
14675 }
14676 return true;
14677}
14678
14679bool SemaOpenMP::checkTransformableLoopSequence(
14680 OpenMPDirectiveKind Kind, Stmt *AStmt, LoopSequenceAnalysis &SeqAnalysis,
14681 ASTContext &Context) {
14682 // Following OpenMP 6.0 API Specification, a Canonical Loop Sequence follows
14683 // the grammar:
14684 //
14685 // canonical-loop-sequence:
14686 // {
14687 // loop-sequence+
14688 // }
14689 // where loop-sequence can be any of the following:
14690 // 1. canonical-loop-sequence
14691 // 2. loop-nest
14692 // 3. loop-sequence-generating-construct (i.e OMPLoopTransformationDirective)
14693 //
14694 // To recognise and traverse this structure the helper function
14695 // analyzeLoopSequence serves as the recurisve entry point
14696 // and tries to match the input AST to the canonical loop sequence grammar
14697 // structure. This function will perform both a semantic and syntactical
14698 // analysis of the given statement according to OpenMP 6.0 definition of
14699 // the aforementioned canonical loop sequence.
14700
14701 // We expect an outer compound statement.
14702 if (!isa<CompoundStmt>(AStmt)) {
14703 Diag(AStmt->getBeginLoc(), diag::err_omp_not_a_loop_sequence)
14704 << getOpenMPDirectiveName(Kind);
14705 return false;
14706 }
14707
14708 // Recursive entry point to process the main loop sequence
14709 if (!analyzeLoopSequence(AStmt, SeqAnalysis, Context, Kind))
14710 return false;
14711
14712 // Diagnose an empty loop sequence.
14713 if (!SeqAnalysis.LoopSeqSize) {
14714 Diag(AStmt->getBeginLoc(), diag::err_omp_empty_loop_sequence)
14715 << getOpenMPDirectiveName(Kind);
14716 return false;
14717 }
14718 return true;
14719}
14720
14721/// Add preinit statements that need to be propagated from the selected loop.
14722static void addLoopPreInits(ASTContext &Context,
14723 OMPLoopBasedDirective::HelperExprs &LoopHelper,
14724 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
14725 SmallVectorImpl<Stmt *> &PreInits) {
14726
14727 // For range-based for-statements, ensure that their syntactic sugar is
14728 // executed by adding them as pre-init statements.
14729 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14730 Stmt *RangeInit = CXXRangeFor->getInit();
14731 if (RangeInit)
14732 PreInits.push_back(RangeInit);
14733
14734 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14735 PreInits.push_back(new (Context) DeclStmt(RangeStmt->getDeclGroup(),
14736 RangeStmt->getBeginLoc(),
14737 RangeStmt->getEndLoc()));
14738
14739 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14740 PreInits.push_back(new (Context) DeclStmt(RangeEnd->getDeclGroup(),
14741 RangeEnd->getBeginLoc(),
14742 RangeEnd->getEndLoc()));
14743 }
14744
14745 llvm::append_range(PreInits, OriginalInit);
14746
14747 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
14748 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
14749 PreInits.push_back(new (Context) DeclStmt(
14750 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14751 }
14752
14753 // Gather declarations for the data members used as counters.
14754 for (Expr *CounterRef : LoopHelper.Counters) {
14755 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14756 if (isa<OMPCapturedExprDecl>(CounterDecl))
14757 PreInits.push_back(new (Context) DeclStmt(
14758 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
14759 }
14760}
14761
14762/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
14763/// loop of a construct.
14764static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) {
14765 size_t NumLoops = LoopStmts.size();
14766 OMPLoopBasedDirective::doForAllLoops(
14767 AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
14768 [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
14769 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
14770 LoopStmts[Cnt] = CurStmt;
14771 return false;
14772 });
14773 assert(!is_contained(LoopStmts, nullptr) &&
14774 "Expecting a loop statement for each affected loop");
14775}
14776
14777/// Build and return a DeclRefExpr for the floor induction variable using the
14778/// SemaRef and the provided parameters.
14779static Expr *makeFloorIVRef(Sema &SemaRef, ArrayRef<VarDecl *> FloorIndVars,
14780 int I, QualType IVTy, DeclRefExpr *OrigCntVar) {
14781 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14782 OrigCntVar->getExprLoc());
14783}
14784
14786 Stmt *AStmt,
14787 SourceLocation StartLoc,
14788 SourceLocation EndLoc) {
14789 ASTContext &Context = getASTContext();
14790 Scope *CurScope = SemaRef.getCurScope();
14791
14792 const auto *SizesClause =
14793 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14794 if (!SizesClause ||
14795 llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; }))
14796 return StmtError();
14797 unsigned NumLoops = SizesClause->getNumSizes();
14798
14799 // Empty statement should only be possible if there already was an error.
14800 if (!AStmt)
14801 return StmtError();
14802
14803 // Verify and diagnose loop nest.
14805 Stmt *Body = nullptr;
14806 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
14807 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14808 OriginalInits))
14809 return StmtError();
14810
14811 // Delay tiling to when template is completely instantiated.
14812 if (SemaRef.CurContext->isDependentContext())
14813 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14814 NumLoops, AStmt, nullptr, nullptr);
14815
14816 assert(LoopHelpers.size() == NumLoops &&
14817 "Expecting loop iteration space dimensionality to match number of "
14818 "affected loops");
14819 assert(OriginalInits.size() == NumLoops &&
14820 "Expecting loop iteration space dimensionality to match number of "
14821 "affected loops");
14822
14823 // Collect all affected loop statements.
14824 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14825 collectLoopStmts(AStmt, LoopStmts);
14826
14827 SmallVector<Stmt *, 4> PreInits;
14828 CaptureVars CopyTransformer(SemaRef);
14829
14830 // Create iteration variables for the generated loops.
14831 SmallVector<VarDecl *, 4> FloorIndVars;
14832 SmallVector<VarDecl *, 4> TileIndVars;
14833 FloorIndVars.resize(NumLoops);
14834 TileIndVars.resize(NumLoops);
14835 for (unsigned I = 0; I < NumLoops; ++I) {
14836 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14837
14838 assert(LoopHelper.Counters.size() == 1 &&
14839 "Expect single-dimensional loop iteration space");
14840 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14841 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14842 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14843 QualType CntTy = IterVarRef->getType();
14844
14845 // Iteration variable for the floor (i.e. outer) loop.
14846 {
14847 std::string FloorCntName =
14848 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14849 VarDecl *FloorCntDecl =
14850 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14851 FloorIndVars[I] = FloorCntDecl;
14852 }
14853
14854 // Iteration variable for the tile (i.e. inner) loop.
14855 {
14856 std::string TileCntName =
14857 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14858
14859 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14860 // used by the expressions to derive the original iteration variable's
14861 // value from the logical iteration number.
14862 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14863 TileCntDecl->setDeclName(
14864 &SemaRef.PP.getIdentifierTable().get(TileCntName));
14865 TileIndVars[I] = TileCntDecl;
14866 }
14867
14868 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
14869 PreInits);
14870 }
14871
14872 // Once the original iteration values are set, append the innermost body.
14873 Stmt *Inner = Body;
14874
14875 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
14876 SizesClause, CurScope](int I) -> Expr * {
14877 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14878
14879 if (DimTileSizeExpr->containsErrors())
14880 return nullptr;
14881
14882 if (isa<ConstantExpr>(DimTileSizeExpr))
14883 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14884
14885 // When the tile size is not a constant but a variable, it is possible to
14886 // pass non-positive numbers. For instance:
14887 // \code{c}
14888 // int a = 0;
14889 // #pragma omp tile sizes(a)
14890 // for (int i = 0; i < 42; ++i)
14891 // body(i);
14892 // \endcode
14893 // Although there is no meaningful interpretation of the tile size, the body
14894 // should still be executed 42 times to avoid surprises. To preserve the
14895 // invariant that every loop iteration is executed exactly once and not
14896 // cause an infinite loop, apply a minimum tile size of one.
14897 // Build expr:
14898 // \code{c}
14899 // (TS <= 0) ? 1 : TS
14900 // \endcode
14901 QualType DimTy = DimTileSizeExpr->getType();
14902 uint64_t DimWidth = Context.getTypeSize(DimTy);
14904 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14905 IntegerLiteral *One =
14906 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
14907 Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
14908 CurScope, {}, BO_LE,
14909 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
14910 Expr *MinOne = new (Context) ConditionalOperator(
14911 Cond, {}, One, {},
14912 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14914 return MinOne;
14915 };
14916
14917 // Create tile loops from the inside to the outside.
14918 for (int I = NumLoops - 1; I >= 0; --I) {
14919 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14920 Expr *NumIterations = LoopHelper.NumIterations;
14921 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14922 QualType IVTy = NumIterations->getType();
14923 Stmt *LoopStmt = LoopStmts[I];
14924
14925 // Commonly used variables. One of the constraints of an AST is that every
14926 // node object must appear at most once, hence we define a lambda that
14927 // creates a new AST node at every use.
14928 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
14929 OrigCntVar]() {
14930 return buildDeclRefExpr(SemaRef, TileIndVars[I], IVTy,
14931 OrigCntVar->getExprLoc());
14932 };
14933
14934 // For init-statement: auto .tile.iv = .floor.iv
14935 SemaRef.AddInitializerToDecl(
14936 TileIndVars[I],
14937 SemaRef
14938 .DefaultLvalueConversion(
14939 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
14940 .get(),
14941 /*DirectInit=*/false);
14942 Decl *CounterDecl = TileIndVars[I];
14943 StmtResult InitStmt = new (Context)
14944 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14945 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14946 if (!InitStmt.isUsable())
14947 return StmtError();
14948
14949 // For cond-expression:
14950 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
14951 Expr *DimTileSize = MakeDimTileSize(I);
14952 if (!DimTileSize)
14953 return StmtError();
14954 ExprResult EndOfTile = SemaRef.BuildBinOp(
14955 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14956 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14957 DimTileSize);
14958 if (!EndOfTile.isUsable())
14959 return StmtError();
14960 ExprResult IsPartialTile =
14961 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14962 NumIterations, EndOfTile.get());
14963 if (!IsPartialTile.isUsable())
14964 return StmtError();
14965 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
14966 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14967 IsPartialTile.get(), NumIterations, EndOfTile.get());
14968 if (!MinTileAndIterSpace.isUsable())
14969 return StmtError();
14970 ExprResult CondExpr =
14971 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14972 MakeTileIVRef(), MinTileAndIterSpace.get());
14973 if (!CondExpr.isUsable())
14974 return StmtError();
14975
14976 // For incr-statement: ++.tile.iv
14977 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14978 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
14979 if (!IncrStmt.isUsable())
14980 return StmtError();
14981
14982 // Statements to set the original iteration variable's value from the
14983 // logical iteration number.
14984 // Generated for loop is:
14985 // \code
14986 // Original_for_init;
14987 // for (auto .tile.iv = .floor.iv;
14988 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
14989 // ++.tile.iv) {
14990 // Original_Body;
14991 // Original_counter_update;
14992 // }
14993 // \endcode
14994 // FIXME: If the innermost body is an loop itself, inserting these
14995 // statements stops it being recognized as a perfectly nested loop (e.g.
14996 // for applying tiling again). If this is the case, sink the expressions
14997 // further into the inner loop.
14998 SmallVector<Stmt *, 4> BodyParts;
14999 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15000 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15001 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15002 BodyParts.push_back(Inner);
15003 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15004 Inner->getBeginLoc(), Inner->getEndLoc());
15005 Inner = new (Context)
15006 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15007 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15008 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15009 }
15010
15011 // Create floor loops from the inside to the outside.
15012 for (int I = NumLoops - 1; I >= 0; --I) {
15013 auto &LoopHelper = LoopHelpers[I];
15014 Expr *NumIterations = LoopHelper.NumIterations;
15015 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15016 QualType IVTy = NumIterations->getType();
15017
15018 // For init-statement: auto .floor.iv = 0
15019 SemaRef.AddInitializerToDecl(
15020 FloorIndVars[I],
15021 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15022 /*DirectInit=*/false);
15023 Decl *CounterDecl = FloorIndVars[I];
15024 StmtResult InitStmt = new (Context)
15025 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15026 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15027 if (!InitStmt.isUsable())
15028 return StmtError();
15029
15030 // For cond-expression: .floor.iv < NumIterations
15031 ExprResult CondExpr = SemaRef.BuildBinOp(
15032 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15033 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15034 NumIterations);
15035 if (!CondExpr.isUsable())
15036 return StmtError();
15037
15038 // For incr-statement: .floor.iv += DimTileSize
15039 Expr *DimTileSize = MakeDimTileSize(I);
15040 if (!DimTileSize)
15041 return StmtError();
15042 ExprResult IncrStmt = SemaRef.BuildBinOp(
15043 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15044 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15045 DimTileSize);
15046 if (!IncrStmt.isUsable())
15047 return StmtError();
15048
15049 Inner = new (Context)
15050 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15051 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15052 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15053 }
15054
15055 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
15056 AStmt, Inner,
15057 buildPreInits(Context, PreInits));
15058}
15059
15061 Stmt *AStmt,
15062 SourceLocation StartLoc,
15063 SourceLocation EndLoc) {
15064 ASTContext &Context = getASTContext();
15065 Scope *CurScope = SemaRef.getCurScope();
15066
15067 const auto *SizesClause =
15068 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
15069 if (!SizesClause ||
15070 llvm::any_of(SizesClause->getSizesRefs(), [](const Expr *SizeExpr) {
15071 return !SizeExpr || SizeExpr->containsErrors();
15072 }))
15073 return StmtError();
15074 unsigned NumLoops = SizesClause->getNumSizes();
15075
15076 // Empty statement should only be possible if there already was an error.
15077 if (!AStmt)
15078 return StmtError();
15079
15080 // Verify and diagnose loop nest.
15082 Stmt *Body = nullptr;
15083 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
15084 if (!checkTransformableLoopNest(OMPD_stripe, AStmt, NumLoops, LoopHelpers,
15085 Body, OriginalInits))
15086 return StmtError();
15087
15088 // Delay striping to when template is completely instantiated.
15089 if (SemaRef.CurContext->isDependentContext())
15090 return OMPStripeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15091 NumLoops, AStmt, nullptr, nullptr);
15092
15093 assert(LoopHelpers.size() == NumLoops &&
15094 "Expecting loop iteration space dimensionality to match number of "
15095 "affected loops");
15096 assert(OriginalInits.size() == NumLoops &&
15097 "Expecting loop iteration space dimensionality to match number of "
15098 "affected loops");
15099
15100 // Collect all affected loop statements.
15101 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15102 collectLoopStmts(AStmt, LoopStmts);
15103
15104 SmallVector<Stmt *, 4> PreInits;
15105 CaptureVars CopyTransformer(SemaRef);
15106
15107 // Create iteration variables for the generated loops.
15108 SmallVector<VarDecl *, 4> FloorIndVars;
15109 SmallVector<VarDecl *, 4> StripeIndVars;
15110 FloorIndVars.resize(NumLoops);
15111 StripeIndVars.resize(NumLoops);
15112 for (unsigned I : llvm::seq<unsigned>(NumLoops)) {
15113 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15114
15115 assert(LoopHelper.Counters.size() == 1 &&
15116 "Expect single-dimensional loop iteration space");
15117 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15118 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15119 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15120 QualType CntTy = IterVarRef->getType();
15121
15122 // Iteration variable for the stripe (i.e. outer) loop.
15123 {
15124 std::string FloorCntName =
15125 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15126 VarDecl *FloorCntDecl =
15127 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
15128 FloorIndVars[I] = FloorCntDecl;
15129 }
15130
15131 // Iteration variable for the stripe (i.e. inner) loop.
15132 {
15133 std::string StripeCntName =
15134 (Twine(".stripe_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15135
15136 // Reuse the iteration variable created by checkOpenMPLoop. It is also
15137 // used by the expressions to derive the original iteration variable's
15138 // value from the logical iteration number.
15139 auto *StripeCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15140 StripeCntDecl->setDeclName(
15141 &SemaRef.PP.getIdentifierTable().get(StripeCntName));
15142 StripeIndVars[I] = StripeCntDecl;
15143 }
15144
15145 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
15146 PreInits);
15147 }
15148
15149 // Once the original iteration values are set, append the innermost body.
15150 Stmt *Inner = Body;
15151
15152 auto MakeDimStripeSize = [&](int I) -> Expr * {
15153 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
15154 if (isa<ConstantExpr>(DimStripeSizeExpr))
15155 return AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr));
15156
15157 // When the stripe size is not a constant but a variable, it is possible to
15158 // pass non-positive numbers. For instance:
15159 // \code{c}
15160 // int a = 0;
15161 // #pragma omp stripe sizes(a)
15162 // for (int i = 0; i < 42; ++i)
15163 // body(i);
15164 // \endcode
15165 // Although there is no meaningful interpretation of the stripe size, the
15166 // body should still be executed 42 times to avoid surprises. To preserve
15167 // the invariant that every loop iteration is executed exactly once and not
15168 // cause an infinite loop, apply a minimum stripe size of one.
15169 // Build expr:
15170 // \code{c}
15171 // (TS <= 0) ? 1 : TS
15172 // \endcode
15173 QualType DimTy = DimStripeSizeExpr->getType();
15174 uint64_t DimWidth = Context.getTypeSize(DimTy);
15176 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
15177 IntegerLiteral *One =
15178 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
15179 Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
15180 CurScope, {}, BO_LE,
15181 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), Zero));
15182 Expr *MinOne = new (Context) ConditionalOperator(
15183 Cond, {}, One, {},
15184 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), DimTy,
15186 return MinOne;
15187 };
15188
15189 // Create stripe loops from the inside to the outside.
15190 for (int I = NumLoops - 1; I >= 0; --I) {
15191 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15192 Expr *NumIterations = LoopHelper.NumIterations;
15193 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15194 QualType IVTy = NumIterations->getType();
15195 Stmt *LoopStmt = LoopStmts[I];
15196
15197 // For init-statement: auto .stripe.iv = .floor.iv
15198 SemaRef.AddInitializerToDecl(
15199 StripeIndVars[I],
15200 SemaRef
15201 .DefaultLvalueConversion(
15202 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
15203 .get(),
15204 /*DirectInit=*/false);
15205 Decl *CounterDecl = StripeIndVars[I];
15206 StmtResult InitStmt = new (Context)
15207 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15208 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15209 if (!InitStmt.isUsable())
15210 return StmtError();
15211
15212 // For cond-expression:
15213 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations)
15214 ExprResult EndOfStripe = SemaRef.BuildBinOp(
15215 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15216 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15217 MakeDimStripeSize(I));
15218 if (!EndOfStripe.isUsable())
15219 return StmtError();
15220 ExprResult IsPartialStripe =
15221 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15222 NumIterations, EndOfStripe.get());
15223 if (!IsPartialStripe.isUsable())
15224 return StmtError();
15225 ExprResult MinStripeAndIterSpace = SemaRef.ActOnConditionalOp(
15226 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15227 IsPartialStripe.get(), NumIterations, EndOfStripe.get());
15228 if (!MinStripeAndIterSpace.isUsable())
15229 return StmtError();
15230 ExprResult CondExpr = SemaRef.BuildBinOp(
15231 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15232 makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar),
15233 MinStripeAndIterSpace.get());
15234 if (!CondExpr.isUsable())
15235 return StmtError();
15236
15237 // For incr-statement: ++.stripe.iv
15238 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15239 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc,
15240 makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar));
15241 if (!IncrStmt.isUsable())
15242 return StmtError();
15243
15244 // Statements to set the original iteration variable's value from the
15245 // logical iteration number.
15246 // Generated for loop is:
15247 // \code
15248 // Original_for_init;
15249 // for (auto .stripe.iv = .floor.iv;
15250 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations);
15251 // ++.stripe.iv) {
15252 // Original_Body;
15253 // Original_counter_update;
15254 // }
15255 // \endcode
15256 // FIXME: If the innermost body is a loop itself, inserting these
15257 // statements stops it being recognized as a perfectly nested loop (e.g.
15258 // for applying another loop transformation). If this is the case, sink the
15259 // expressions further into the inner loop.
15260 SmallVector<Stmt *, 4> BodyParts;
15261 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15262 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15263 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15264 BodyParts.push_back(Inner);
15265 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15266 Inner->getBeginLoc(), Inner->getEndLoc());
15267 Inner = new (Context)
15268 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15269 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15270 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15271 }
15272
15273 // Create grid loops from the inside to the outside.
15274 for (int I = NumLoops - 1; I >= 0; --I) {
15275 auto &LoopHelper = LoopHelpers[I];
15276 Expr *NumIterations = LoopHelper.NumIterations;
15277 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15278 QualType IVTy = NumIterations->getType();
15279
15280 // For init-statement: auto .grid.iv = 0
15281 SemaRef.AddInitializerToDecl(
15282 FloorIndVars[I],
15283 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15284 /*DirectInit=*/false);
15285 Decl *CounterDecl = FloorIndVars[I];
15286 StmtResult InitStmt = new (Context)
15287 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15288 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15289 if (!InitStmt.isUsable())
15290 return StmtError();
15291
15292 // For cond-expression: .floor.iv < NumIterations
15293 ExprResult CondExpr = SemaRef.BuildBinOp(
15294 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15295 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15296 NumIterations);
15297 if (!CondExpr.isUsable())
15298 return StmtError();
15299
15300 // For incr-statement: .floor.iv += DimStripeSize
15301 ExprResult IncrStmt = SemaRef.BuildBinOp(
15302 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15303 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15304 MakeDimStripeSize(I));
15305 if (!IncrStmt.isUsable())
15306 return StmtError();
15307
15308 Inner = new (Context)
15309 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15310 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15311 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15312 }
15313
15314 return OMPStripeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15315 NumLoops, AStmt, Inner,
15316 buildPreInits(Context, PreInits));
15317}
15318
15320 Stmt *AStmt,
15321 SourceLocation StartLoc,
15322 SourceLocation EndLoc) {
15323 ASTContext &Context = getASTContext();
15324 Scope *CurScope = SemaRef.getCurScope();
15325 // Empty statement should only be possible if there already was an error.
15326 if (!AStmt)
15327 return StmtError();
15328
15330 {OMPC_partial, OMPC_full}))
15331 return StmtError();
15332
15333 const OMPFullClause *FullClause =
15334 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15335 const OMPPartialClause *PartialClause =
15336 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15337 assert(!(FullClause && PartialClause) &&
15338 "mutual exclusivity must have been checked before");
15339
15340 constexpr unsigned NumLoops = 1;
15341 Stmt *Body = nullptr;
15343 NumLoops);
15344 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
15345 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15346 Body, OriginalInits))
15347 return StmtError();
15348
15349 unsigned NumGeneratedTopLevelLoops = PartialClause ? 1 : 0;
15350
15351 // Delay unrolling to when template is completely instantiated.
15352 if (SemaRef.CurContext->isDependentContext())
15353 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15354 NumGeneratedTopLevelLoops, nullptr,
15355 nullptr);
15356
15357 assert(LoopHelpers.size() == NumLoops &&
15358 "Expecting a single-dimensional loop iteration space");
15359 assert(OriginalInits.size() == NumLoops &&
15360 "Expecting a single-dimensional loop iteration space");
15361 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15362
15363 if (FullClause) {
15365 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
15366 /*SuppressExprDiags=*/true)
15367 .isUsable()) {
15368 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
15369 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
15370 << "#pragma omp unroll full";
15371 return StmtError();
15372 }
15373 }
15374
15375 // The generated loop may only be passed to other loop-associated directive
15376 // when a partial clause is specified. Without the requirement it is
15377 // sufficient to generate loop unroll metadata at code-generation.
15378 if (NumGeneratedTopLevelLoops == 0)
15379 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15380 NumGeneratedTopLevelLoops, nullptr,
15381 nullptr);
15382
15383 // Otherwise, we need to provide a de-sugared/transformed AST that can be
15384 // associated with another loop directive.
15385 //
15386 // The canonical loop analysis return by checkTransformableLoopNest assumes
15387 // the following structure to be the same loop without transformations or
15388 // directives applied: \code OriginalInits; LoopHelper.PreInits;
15389 // LoopHelper.Counters;
15390 // for (; IV < LoopHelper.NumIterations; ++IV) {
15391 // LoopHelper.Updates;
15392 // Body;
15393 // }
15394 // \endcode
15395 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
15396 // and referenced by LoopHelper.IterationVarRef.
15397 //
15398 // The unrolling directive transforms this into the following loop:
15399 // \code
15400 // OriginalInits; \
15401 // LoopHelper.PreInits; > NewPreInits
15402 // LoopHelper.Counters; /
15403 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
15404 // #pragma clang loop unroll_count(Factor)
15405 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
15406 // {
15407 // LoopHelper.Updates;
15408 // Body;
15409 // }
15410 // }
15411 // \endcode
15412 // where UIV is a new logical iteration counter. IV must be the same VarDecl
15413 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
15414 // references it. If the partially unrolled loop is associated with another
15415 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
15416 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
15417 // OpenMP canonical loop. The inner loop is not an associable canonical loop
15418 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
15419 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
15420 // property of the OMPLoopBasedDirective instead of statements in
15421 // CompoundStatement. This is to allow the loop to become a non-outermost loop
15422 // of a canonical loop nest where these PreInits are emitted before the
15423 // outermost directive.
15424
15425 // Find the loop statement.
15426 Stmt *LoopStmt = nullptr;
15427 collectLoopStmts(AStmt, {LoopStmt});
15428
15429 // Determine the PreInit declarations.
15430 SmallVector<Stmt *, 4> PreInits;
15431 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15432
15433 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15434 QualType IVTy = IterationVarRef->getType();
15435 assert(LoopHelper.Counters.size() == 1 &&
15436 "Expecting a single-dimensional loop iteration space");
15437 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15438
15439 // Determine the unroll factor.
15440 uint64_t Factor;
15441 SourceLocation FactorLoc;
15442 if (Expr *FactorVal = PartialClause->getFactor();
15443 FactorVal && !FactorVal->containsErrors()) {
15444 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15445 FactorLoc = FactorVal->getExprLoc();
15446 } else {
15447 // TODO: Use a better profitability model.
15448 Factor = 2;
15449 }
15450 assert(Factor > 0 && "Expected positive unroll factor");
15451 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
15453 getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor),
15454 IVTy, FactorLoc);
15455 };
15456
15457 // Iteration variable SourceLocations.
15458 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15459 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15460 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15461
15462 // Internal variable names.
15463 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15464 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
15465 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
15466
15467 // Create the iteration variable for the unrolled loop.
15468 VarDecl *OuterIVDecl =
15469 buildVarDecl(SemaRef, {}, IVTy, OuterIVName, nullptr, OrigVar);
15470 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
15471 return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc);
15472 };
15473
15474 // Iteration variable for the inner loop: Reuse the iteration variable created
15475 // by checkOpenMPLoop.
15476 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15477 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(InnerIVName));
15478 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
15479 return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc);
15480 };
15481
15482 // Make a copy of the NumIterations expression for each use: By the AST
15483 // constraints, every expression object in a DeclContext must be unique.
15484 CaptureVars CopyTransformer(SemaRef);
15485 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15486 return AssertSuccess(
15487 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15488 };
15489
15490 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15491 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(MakeOuterRef());
15492 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(),
15493 /*DirectInit=*/false);
15494 StmtResult InnerInit = new (Context)
15495 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15496 if (!InnerInit.isUsable())
15497 return StmtError();
15498
15499 // Inner For cond-expression:
15500 // \code
15501 // .unroll_inner.iv < .unrolled.iv + Factor &&
15502 // .unroll_inner.iv < NumIterations
15503 // \endcode
15504 // This conjunction of two conditions allows ScalarEvolution to derive the
15505 // maximum trip count of the inner loop.
15506 ExprResult EndOfTile =
15507 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15508 MakeOuterRef(), MakeFactorExpr());
15509 if (!EndOfTile.isUsable())
15510 return StmtError();
15511 ExprResult InnerCond1 =
15512 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15513 MakeInnerRef(), EndOfTile.get());
15514 if (!InnerCond1.isUsable())
15515 return StmtError();
15516 ExprResult InnerCond2 =
15517 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15518 MakeInnerRef(), MakeNumIterations());
15519 if (!InnerCond2.isUsable())
15520 return StmtError();
15521 ExprResult InnerCond =
15522 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15523 InnerCond1.get(), InnerCond2.get());
15524 if (!InnerCond.isUsable())
15525 return StmtError();
15526
15527 // Inner For incr-statement: ++.unroll_inner.iv
15528 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
15529 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
15530 if (!InnerIncr.isUsable())
15531 return StmtError();
15532
15533 // Inner For statement.
15534 SmallVector<Stmt *> InnerBodyStmts;
15535 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15536 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15537 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15538 InnerBodyStmts.push_back(Body);
15539 CompoundStmt *InnerBody =
15541 Body->getBeginLoc(), Body->getEndLoc());
15542 ForStmt *InnerFor = new (Context)
15543 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15544 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15545 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15546
15547 // Unroll metadata for the inner loop.
15548 // This needs to take into account the remainder portion of the unrolled loop,
15549 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15550 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15551 // the maximum trip count, which will also generate a remainder loop. Just
15552 // `unroll(enable)` (which could have been useful if the user has not
15553 // specified a concrete factor; even though the outer loop cannot be
15554 // influenced anymore, would avoid more code bloat than necessary) will refuse
15555 // the loop because "Won't unroll; remainder loop could not be generated when
15556 // assuming runtime trip count". Even if it did work, it must not choose a
15557 // larger unroll factor than the maximum loop length, or it would always just
15558 // execute the remainder loop.
15559 LoopHintAttr *UnrollHintAttr =
15560 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15561 LoopHintAttr::Numeric, MakeFactorExpr());
15562 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
15563 getASTContext(), StartLoc, {UnrollHintAttr}, InnerFor);
15564
15565 // Outer For init-statement: auto .unrolled.iv = 0
15566 SemaRef.AddInitializerToDecl(
15567 OuterIVDecl,
15568 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15569 /*DirectInit=*/false);
15570 StmtResult OuterInit = new (Context)
15571 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15572 if (!OuterInit.isUsable())
15573 return StmtError();
15574
15575 // Outer For cond-expression: .unrolled.iv < NumIterations
15576 ExprResult OuterConde =
15577 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15578 MakeOuterRef(), MakeNumIterations());
15579 if (!OuterConde.isUsable())
15580 return StmtError();
15581
15582 // Outer For incr-statement: .unrolled.iv += Factor
15583 ExprResult OuterIncr =
15584 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15585 MakeOuterRef(), MakeFactorExpr());
15586 if (!OuterIncr.isUsable())
15587 return StmtError();
15588
15589 // Outer For statement.
15590 ForStmt *OuterFor = new (Context)
15591 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15592 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15593 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15594
15595 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15596 NumGeneratedTopLevelLoops, OuterFor,
15597 buildPreInits(Context, PreInits));
15598}
15599
15601 SourceLocation StartLoc,
15602 SourceLocation EndLoc) {
15603 ASTContext &Context = getASTContext();
15604 Scope *CurScope = SemaRef.getCurScope();
15605
15606 // Empty statement should only be possible if there already was an error.
15607 if (!AStmt)
15608 return StmtError();
15609
15610 constexpr unsigned NumLoops = 1;
15611 Stmt *Body = nullptr;
15613 NumLoops);
15614 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
15615 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
15616 Body, OriginalInits))
15617 return StmtError();
15618
15619 // Delay applying the transformation to when template is completely
15620 // instantiated.
15621 if (SemaRef.CurContext->isDependentContext())
15622 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
15623 NumLoops, nullptr, nullptr);
15624
15625 assert(LoopHelpers.size() == NumLoops &&
15626 "Expecting a single-dimensional loop iteration space");
15627 assert(OriginalInits.size() == NumLoops &&
15628 "Expecting a single-dimensional loop iteration space");
15629 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15630
15631 // Find the loop statement.
15632 Stmt *LoopStmt = nullptr;
15633 collectLoopStmts(AStmt, {LoopStmt});
15634
15635 // Determine the PreInit declarations.
15636 SmallVector<Stmt *> PreInits;
15637 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15638
15639 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15640 QualType IVTy = IterationVarRef->getType();
15641 uint64_t IVWidth = Context.getTypeSize(IVTy);
15642 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15643
15644 // Iteration variable SourceLocations.
15645 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15646 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15647 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15648
15649 // Locations pointing to the transformation.
15650 SourceLocation TransformLoc = StartLoc;
15651 SourceLocation TransformLocBegin = StartLoc;
15652 SourceLocation TransformLocEnd = EndLoc;
15653
15654 // Internal variable names.
15655 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15656 SmallString<64> ForwardIVName(".forward.iv.");
15657 ForwardIVName += OrigVarName;
15658 SmallString<64> ReversedIVName(".reversed.iv.");
15659 ReversedIVName += OrigVarName;
15660
15661 // LoopHelper.Updates will read the logical iteration number from
15662 // LoopHelper.IterationVarRef, compute the value of the user loop counter of
15663 // that logical iteration from it, then assign it to the user loop counter
15664 // variable. We cannot directly use LoopHelper.IterationVarRef as the
15665 // induction variable of the generated loop because it may cause an underflow:
15666 // \code{.c}
15667 // for (unsigned i = 0; i < n; ++i)
15668 // body(i);
15669 // \endcode
15670 //
15671 // Naive reversal:
15672 // \code{.c}
15673 // for (unsigned i = n-1; i >= 0; --i)
15674 // body(i);
15675 // \endcode
15676 //
15677 // Instead, we introduce a new iteration variable representing the logical
15678 // iteration counter of the original loop, convert it to the logical iteration
15679 // number of the reversed loop, then let LoopHelper.Updates compute the user's
15680 // loop iteration variable from it.
15681 // \code{.cpp}
15682 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
15683 // auto .reversed.iv = n - .forward.iv - 1;
15684 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates
15685 // body(i); // Body
15686 // }
15687 // \endcode
15688
15689 // Subexpressions with more than one use. One of the constraints of an AST is
15690 // that every node object must appear at most once, hence we define a lambda
15691 // that creates a new AST node at every use.
15692 CaptureVars CopyTransformer(SemaRef);
15693 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15694 return AssertSuccess(
15695 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15696 };
15697
15698 // Create the iteration variable for the forward loop (from 0 to n-1).
15699 VarDecl *ForwardIVDecl =
15700 buildVarDecl(SemaRef, {}, IVTy, ForwardIVName, nullptr, OrigVar);
15701 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
15702 OrigVarLoc]() {
15703 return buildDeclRefExpr(SemaRef, ForwardIVDecl, IVTy, OrigVarLoc);
15704 };
15705
15706 // Iteration variable for the reversed induction variable (from n-1 downto 0):
15707 // Reuse the iteration variable created by checkOpenMPLoop.
15708 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15709 ReversedIVDecl->setDeclName(
15710 &SemaRef.PP.getIdentifierTable().get(ReversedIVName));
15711
15712 // For init-statement:
15713 // \code{.cpp}
15714 // auto .forward.iv = 0;
15715 // \endcode
15716 auto *Zero = IntegerLiteral::Create(Context, llvm::APInt::getZero(IVWidth),
15717 ForwardIVDecl->getType(), OrigVarLoc);
15718 SemaRef.AddInitializerToDecl(ForwardIVDecl, Zero, /*DirectInit=*/false);
15719 StmtResult Init = new (Context)
15720 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15721 if (!Init.isUsable())
15722 return StmtError();
15723
15724 // Forward iv cond-expression:
15725 // \code{.cpp}
15726 // .forward.iv < MakeNumIterations()
15727 // \endcode
15729 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15730 MakeForwardRef(), MakeNumIterations());
15731 if (!Cond.isUsable())
15732 return StmtError();
15733
15734 // Forward incr-statement:
15735 // \code{.c}
15736 // ++.forward.iv
15737 // \endcode
15738 ExprResult Incr = SemaRef.BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
15739 UO_PreInc, MakeForwardRef());
15740 if (!Incr.isUsable())
15741 return StmtError();
15742
15743 // Reverse the forward-iv:
15744 // \code{.cpp}
15745 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
15746 // \endcode
15747 auto *One = IntegerLiteral::Create(Context, llvm::APInt(IVWidth, 1), IVTy,
15748 TransformLoc);
15749 ExprResult Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub,
15750 MakeNumIterations(), One);
15751 if (!Minus.isUsable())
15752 return StmtError();
15753 Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.get(),
15754 MakeForwardRef());
15755 if (!Minus.isUsable())
15756 return StmtError();
15757 StmtResult InitReversed = new (Context) DeclStmt(
15758 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
15759 if (!InitReversed.isUsable())
15760 return StmtError();
15761 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.get(),
15762 /*DirectInit=*/false);
15763
15764 // The new loop body.
15765 SmallVector<Stmt *, 4> BodyStmts;
15766 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
15767 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
15768 BodyStmts.push_back(InitReversed.get());
15769 llvm::append_range(BodyStmts, LoopHelper.Updates);
15770 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15771 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15772 BodyStmts.push_back(Body);
15773 auto *ReversedBody =
15774 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
15775 Body->getBeginLoc(), Body->getEndLoc());
15776
15777 // Finally create the reversed For-statement.
15778 auto *ReversedFor = new (Context)
15779 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
15780 ReversedBody, LoopHelper.Init->getBeginLoc(),
15781 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15782 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt, NumLoops,
15783 ReversedFor,
15784 buildPreInits(Context, PreInits));
15785}
15786
15788 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15789 SourceLocation EndLoc) {
15790 ASTContext &Context = getASTContext();
15791 DeclContext *CurContext = SemaRef.CurContext;
15792 Scope *CurScope = SemaRef.getCurScope();
15793
15794 // Empty statement should only be possible if there already was an error.
15795 if (!AStmt)
15796 return StmtError();
15797
15798 // interchange without permutation clause swaps two loops.
15799 const OMPPermutationClause *PermutationClause =
15800 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
15801 size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2;
15802
15803 // Verify and diagnose loop nest.
15805 Stmt *Body = nullptr;
15806 SmallVector<SmallVector<Stmt *>, 2> OriginalInits;
15807 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
15808 LoopHelpers, Body, OriginalInits))
15809 return StmtError();
15810
15811 // Delay interchange to when template is completely instantiated.
15812 if (CurContext->isDependentContext())
15813 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15814 NumLoops, AStmt, nullptr, nullptr);
15815
15816 // An invalid expression in the permutation clause is set to nullptr in
15817 // ActOnOpenMPPermutationClause.
15818 if (PermutationClause &&
15819 llvm::is_contained(PermutationClause->getArgsRefs(), nullptr))
15820 return StmtError();
15821
15822 assert(LoopHelpers.size() == NumLoops &&
15823 "Expecting loop iteration space dimensionaly to match number of "
15824 "affected loops");
15825 assert(OriginalInits.size() == NumLoops &&
15826 "Expecting loop iteration space dimensionaly to match number of "
15827 "affected loops");
15828
15829 // Decode the permutation clause.
15830 SmallVector<uint64_t, 2> Permutation;
15831 if (!PermutationClause) {
15832 Permutation = {1, 0};
15833 } else {
15834 ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs();
15835 llvm::BitVector Flags(PermArgs.size());
15836 for (Expr *PermArg : PermArgs) {
15837 std::optional<llvm::APSInt> PermCstExpr =
15838 PermArg->getIntegerConstantExpr(Context);
15839 if (!PermCstExpr)
15840 continue;
15841 uint64_t PermInt = PermCstExpr->getZExtValue();
15842 assert(1 <= PermInt && PermInt <= NumLoops &&
15843 "Must be a permutation; diagnostic emitted in "
15844 "ActOnOpenMPPermutationClause");
15845 if (Flags[PermInt - 1]) {
15846 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
15847 Diag(PermArg->getExprLoc(),
15848 diag::err_omp_interchange_permutation_value_repeated)
15849 << PermInt << ExprRange;
15850 continue;
15851 }
15852 Flags[PermInt - 1] = true;
15853
15854 Permutation.push_back(PermInt - 1);
15855 }
15856
15857 if (Permutation.size() != NumLoops)
15858 return StmtError();
15859 }
15860
15861 // Nothing to transform with trivial permutation.
15862 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](auto P) {
15863 auto [Idx, Arg] = P;
15864 return Idx == Arg;
15865 }))
15866 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15867 NumLoops, AStmt, AStmt, nullptr);
15868
15869 // Find the affected loops.
15870 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15871 collectLoopStmts(AStmt, LoopStmts);
15872
15873 // Collect pre-init statements on the order before the permuation.
15874 SmallVector<Stmt *> PreInits;
15875 for (auto I : llvm::seq<int>(NumLoops)) {
15876 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15877
15878 assert(LoopHelper.Counters.size() == 1 &&
15879 "Single-dimensional loop iteration space expected");
15880
15881 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
15882 PreInits);
15883 }
15884
15885 SmallVector<VarDecl *> PermutedIndVars(NumLoops);
15886 CaptureVars CopyTransformer(SemaRef);
15887
15888 // Create the permuted loops from the inside to the outside of the
15889 // interchanged loop nest. Body of the innermost new loop is the original
15890 // innermost body.
15891 Stmt *Inner = Body;
15892 for (auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
15893 // Get the original loop that belongs to this new position.
15894 uint64_t SourceIdx = Permutation[TargetIdx];
15895 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
15896 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15897 assert(SourceHelper.Counters.size() == 1 &&
15898 "Single-dimensional loop iteration space expected");
15899 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.Counters.front());
15900
15901 // Normalized loop counter variable: From 0 to n-1, always an integer type.
15902 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(SourceHelper.IterationVarRef);
15903 QualType IVTy = IterVarRef->getType();
15904 assert(IVTy->isIntegerType() &&
15905 "Expected the logical iteration counter to be an integer");
15906
15907 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15908 SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
15909
15910 // Make a copy of the NumIterations expression for each use: By the AST
15911 // constraints, every expression object in a DeclContext must be unique.
15912 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
15913 return AssertSuccess(
15914 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
15915 };
15916
15917 // Iteration variable for the permuted loop. Reuse the one from
15918 // checkOpenMPLoop which will also be used to update the original loop
15919 // variable.
15920 SmallString<64> PermutedCntName(".permuted_");
15921 PermutedCntName.append({llvm::utostr(TargetIdx), ".iv.", OrigVarName});
15922 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15923 PermutedCntDecl->setDeclName(
15924 &SemaRef.PP.getIdentifierTable().get(PermutedCntName));
15925 PermutedIndVars[TargetIdx] = PermutedCntDecl;
15926 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
15927 return buildDeclRefExpr(SemaRef, PermutedCntDecl, IVTy, OrigVarLoc);
15928 };
15929
15930 // For init-statement:
15931 // \code
15932 // auto .permuted_{target}.iv = 0
15933 // \endcode
15934 ExprResult Zero = SemaRef.ActOnIntegerConstant(OrigVarLoc, 0);
15935 if (!Zero.isUsable())
15936 return StmtError();
15937 SemaRef.AddInitializerToDecl(PermutedCntDecl, Zero.get(),
15938 /*DirectInit=*/false);
15939 StmtResult InitStmt = new (Context)
15940 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
15941 OrigCntVar->getEndLoc());
15942 if (!InitStmt.isUsable())
15943 return StmtError();
15944
15945 // For cond-expression:
15946 // \code
15947 // .permuted_{target}.iv < MakeNumIterations()
15948 // \endcode
15949 ExprResult CondExpr =
15950 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
15951 MakePermutedRef(), MakeNumIterations());
15952 if (!CondExpr.isUsable())
15953 return StmtError();
15954
15955 // For incr-statement:
15956 // \code
15957 // ++.tile.iv
15958 // \endcode
15959 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15960 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
15961 if (!IncrStmt.isUsable())
15962 return StmtError();
15963
15964 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
15965 SourceHelper.Updates.end());
15966 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
15967 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15968 BodyParts.push_back(Inner);
15969 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15970 Inner->getBeginLoc(), Inner->getEndLoc());
15971 Inner = new (Context) ForStmt(
15972 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
15973 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
15974 SourceHelper.Inc->getEndLoc());
15975 }
15976
15977 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15978 NumLoops, AStmt, Inner,
15979 buildPreInits(Context, PreInits));
15980}
15981
15983 Stmt *AStmt,
15984 SourceLocation StartLoc,
15985 SourceLocation EndLoc) {
15986
15987 ASTContext &Context = getASTContext();
15988 DeclContext *CurrContext = SemaRef.CurContext;
15989 Scope *CurScope = SemaRef.getCurScope();
15990 CaptureVars CopyTransformer(SemaRef);
15991
15992 // Ensure the structured block is not empty
15993 if (!AStmt)
15994 return StmtError();
15995
15996 // Defer transformation in dependent contexts
15997 // The NumLoopNests argument is set to a placeholder 1 (even though
15998 // using looprange fuse could yield up to 3 top level loop nests)
15999 // because a dependent context could prevent determining its true value
16000 if (CurrContext->isDependentContext())
16001 return OMPFuseDirective::Create(Context, StartLoc, EndLoc, Clauses,
16002 /* NumLoops */ 1, AStmt, nullptr, nullptr);
16003
16004 // Validate that the potential loop sequence is transformable for fusion
16005 // Also collect the HelperExprs, Loop Stmts, Inits, and Number of loops
16006 LoopSequenceAnalysis SeqAnalysis;
16007 if (!checkTransformableLoopSequence(OMPD_fuse, AStmt, SeqAnalysis, Context))
16008 return StmtError();
16009
16010 // SeqAnalysis.LoopSeqSize exists mostly to handle dependent contexts,
16011 // otherwise it must be the same as SeqAnalysis.Loops.size().
16012 assert(SeqAnalysis.LoopSeqSize == SeqAnalysis.Loops.size() &&
16013 "Inconsistent size of the loop sequence and the number of loops "
16014 "found in the sequence");
16015
16016 // Handle clauses, which can be any of the following: [looprange, apply]
16017 const auto *LRC =
16018 OMPExecutableDirective::getSingleClause<OMPLoopRangeClause>(Clauses);
16019
16020 // The clause arguments are invalidated if any error arises
16021 // such as non-constant or non-positive arguments
16022 if (LRC && (!LRC->getFirst() || !LRC->getCount()))
16023 return StmtError();
16024
16025 // Delayed semantic check of LoopRange constraint
16026 // Evaluates the loop range arguments and returns the first and count values
16027 auto EvaluateLoopRangeArguments = [&Context](Expr *First, Expr *Count,
16028 uint64_t &FirstVal,
16029 uint64_t &CountVal) {
16030 llvm::APSInt FirstInt = First->EvaluateKnownConstInt(Context);
16031 llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Context);
16032 FirstVal = FirstInt.getZExtValue();
16033 CountVal = CountInt.getZExtValue();
16034 };
16035
16036 // OpenMP [6.0, Restrictions]
16037 // first + count - 1 must not evaluate to a value greater than the
16038 // loop sequence length of the associated canonical loop sequence.
16039 auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal,
16040 unsigned NumLoops) -> bool {
16041 return FirstVal + CountVal - 1 <= NumLoops;
16042 };
16043 uint64_t FirstVal = 1, CountVal = 0, LastVal = SeqAnalysis.LoopSeqSize;
16044
16045 // Validates the loop range after evaluating the semantic information
16046 // and ensures that the range is valid for the given loop sequence size.
16047 // Expressions are evaluated at compile time to obtain constant values.
16048 if (LRC) {
16049 EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal,
16050 CountVal);
16051 if (CountVal == 1)
16052 SemaRef.Diag(LRC->getCountLoc(), diag::warn_omp_redundant_fusion)
16053 << getOpenMPDirectiveName(OMPD_fuse);
16054
16055 if (!ValidLoopRange(FirstVal, CountVal, SeqAnalysis.LoopSeqSize)) {
16056 SemaRef.Diag(LRC->getFirstLoc(), diag::err_omp_invalid_looprange)
16057 << getOpenMPDirectiveName(OMPD_fuse) << FirstVal
16058 << (FirstVal + CountVal - 1) << SeqAnalysis.LoopSeqSize;
16059 return StmtError();
16060 }
16061
16062 LastVal = FirstVal + CountVal - 1;
16063 }
16064
16065 // Complete fusion generates a single canonical loop nest
16066 // However looprange clause may generate several loop nests
16067 unsigned NumGeneratedTopLevelLoops =
16068 LRC ? SeqAnalysis.LoopSeqSize - CountVal + 1 : 1;
16069
16070 // Emit a warning for redundant loop fusion when the sequence contains only
16071 // one loop.
16072 if (SeqAnalysis.LoopSeqSize == 1)
16073 SemaRef.Diag(AStmt->getBeginLoc(), diag::warn_omp_redundant_fusion)
16074 << getOpenMPDirectiveName(OMPD_fuse);
16075
16076 // Select the type with the largest bit width among all induction variables
16077 QualType IVType =
16078 SeqAnalysis.Loops[FirstVal - 1].HelperExprs.IterationVarRef->getType();
16079 for (unsigned I : llvm::seq<unsigned>(FirstVal, LastVal)) {
16080 QualType CurrentIVType =
16081 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef->getType();
16082 if (Context.getTypeSize(CurrentIVType) > Context.getTypeSize(IVType)) {
16083 IVType = CurrentIVType;
16084 }
16085 }
16086 uint64_t IVBitWidth = Context.getIntWidth(IVType);
16087
16088 // Create pre-init declarations for all loops lower bounds, upper bounds,
16089 // strides and num-iterations for every top level loop in the fusion
16090 SmallVector<VarDecl *, 4> LBVarDecls;
16091 SmallVector<VarDecl *, 4> STVarDecls;
16092 SmallVector<VarDecl *, 4> NIVarDecls;
16093 SmallVector<VarDecl *, 4> UBVarDecls;
16094 SmallVector<VarDecl *, 4> IVVarDecls;
16095
16096 // Helper lambda to create variables for bounds, strides, and other
16097 // expressions. Generates both the variable declaration and the corresponding
16098 // initialization statement.
16099 auto CreateHelperVarAndStmt =
16100 [&, &SemaRef = SemaRef](Expr *ExprToCopy, const std::string &BaseName,
16101 unsigned I, bool NeedsNewVD = false) {
16102 Expr *TransformedExpr =
16103 AssertSuccess(CopyTransformer.TransformExpr(ExprToCopy));
16104 if (!TransformedExpr)
16105 return std::pair<VarDecl *, StmtResult>(nullptr, StmtError());
16106
16107 auto Name = (Twine(".omp.") + BaseName + std::to_string(I)).str();
16108
16109 VarDecl *VD;
16110 if (NeedsNewVD) {
16111 VD = buildVarDecl(SemaRef, SourceLocation(), IVType, Name);
16112 SemaRef.AddInitializerToDecl(VD, TransformedExpr, false);
16113 } else {
16114 // Create a unique variable name
16115 DeclRefExpr *DRE = cast<DeclRefExpr>(TransformedExpr);
16116 VD = cast<VarDecl>(DRE->getDecl());
16117 VD->setDeclName(&SemaRef.PP.getIdentifierTable().get(Name));
16118 }
16119 // Create the corresponding declaration statement
16120 StmtResult DeclStmt = new (Context) class DeclStmt(
16122 return std::make_pair(VD, DeclStmt);
16123 };
16124
16125 // PreInits hold a sequence of variable declarations that must be executed
16126 // before the fused loop begins. These include bounds, strides, and other
16127 // helper variables required for the transformation. Other loop transforms
16128 // also contain their own preinits
16129 SmallVector<Stmt *> PreInits;
16130
16131 // Update the general preinits using the preinits generated by loop sequence
16132 // generating loop transformations. These preinits differ slightly from
16133 // single-loop transformation preinits, as they can be detached from a
16134 // specific loop inside multiple generated loop nests. This happens
16135 // because certain helper variables, like '.omp.fuse.max', are introduced to
16136 // handle fused iteration spaces and may not be directly tied to a single
16137 // original loop. The preinit structure must ensure that hidden variables
16138 // like '.omp.fuse.max' are still properly handled.
16139 // Transformations that apply this concept: Loopranged Fuse, Split
16140 llvm::append_range(PreInits, SeqAnalysis.LoopSequencePreInits);
16141
16142 // Process each single loop to generate and collect declarations
16143 // and statements for all helper expressions related to
16144 // particular single loop nests
16145
16146 // Also In the case of the fused loops, we keep track of their original
16147 // inits by appending them to their preinits statement, and in the case of
16148 // transformations, also append their preinits (which contain the original
16149 // loop initialization statement or other statements)
16150
16151 // Firstly we need to set TransformIndex to match the begining of the
16152 // looprange section
16153 unsigned int TransformIndex = 0;
16154 for (unsigned I : llvm::seq<unsigned>(FirstVal - 1)) {
16155 if (SeqAnalysis.Loops[I].isLoopTransformation())
16156 ++TransformIndex;
16157 }
16158
16159 for (unsigned int I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16160 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16161 addLoopPreInits(Context, SeqAnalysis.Loops[I].HelperExprs,
16162 SeqAnalysis.Loops[I].TheForStmt,
16163 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16164 } else if (SeqAnalysis.Loops[I].isLoopTransformation()) {
16165 // For transformed loops, insert both pre-inits and original inits.
16166 // Order matters: pre-inits may define variables used in the original
16167 // inits such as upper bounds...
16168 SmallVector<Stmt *> &TransformPreInit =
16169 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16170 llvm::append_range(PreInits, TransformPreInit);
16171
16172 addLoopPreInits(Context, SeqAnalysis.Loops[I].HelperExprs,
16173 SeqAnalysis.Loops[I].TheForStmt,
16174 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16175 }
16176 auto [UBVD, UBDStmt] =
16177 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.UB, "ub", J);
16178 auto [LBVD, LBDStmt] =
16179 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.LB, "lb", J);
16180 auto [STVD, STDStmt] =
16181 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.ST, "st", J);
16182 auto [NIVD, NIDStmt] = CreateHelperVarAndStmt(
16183 SeqAnalysis.Loops[I].HelperExprs.NumIterations, "ni", J, true);
16184 auto [IVVD, IVDStmt] = CreateHelperVarAndStmt(
16185 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef, "iv", J);
16186
16187 assert(LBVD && STVD && NIVD && IVVD &&
16188 "OpenMP Fuse Helper variables creation failed");
16189
16190 UBVarDecls.push_back(UBVD);
16191 LBVarDecls.push_back(LBVD);
16192 STVarDecls.push_back(STVD);
16193 NIVarDecls.push_back(NIVD);
16194 IVVarDecls.push_back(IVVD);
16195
16196 PreInits.push_back(LBDStmt.get());
16197 PreInits.push_back(STDStmt.get());
16198 PreInits.push_back(NIDStmt.get());
16199 PreInits.push_back(IVDStmt.get());
16200 }
16201
16202 auto MakeVarDeclRef = [&SemaRef = this->SemaRef](VarDecl *VD) {
16203 return buildDeclRefExpr(SemaRef, VD, VD->getType(), VD->getLocation(),
16204 false);
16205 };
16206
16207 // Following up the creation of the final fused loop will be performed
16208 // which has the following shape (considering the selected loops):
16209 //
16210 // for (fuse.index = 0; fuse.index < max(ni0, ni1..., nik); ++fuse.index) {
16211 // if (fuse.index < ni0){
16212 // iv0 = lb0 + st0 * fuse.index;
16213 // original.index0 = iv0
16214 // body(0);
16215 // }
16216 // if (fuse.index < ni1){
16217 // iv1 = lb1 + st1 * fuse.index;
16218 // original.index1 = iv1
16219 // body(1);
16220 // }
16221 //
16222 // ...
16223 //
16224 // if (fuse.index < nik){
16225 // ivk = lbk + stk * fuse.index;
16226 // original.indexk = ivk
16227 // body(k); Expr *InitVal = IntegerLiteral::Create(Context,
16228 // llvm::APInt(IVWidth, 0),
16229 // }
16230
16231 // 1. Create the initialized fuse index
16232 StringRef IndexName = ".omp.fuse.index";
16233 Expr *InitVal = IntegerLiteral::Create(Context, llvm::APInt(IVBitWidth, 0),
16234 IVType, SourceLocation());
16235 VarDecl *IndexDecl =
16236 buildVarDecl(SemaRef, {}, IVType, IndexName, nullptr, nullptr);
16237 SemaRef.AddInitializerToDecl(IndexDecl, InitVal, false);
16238 StmtResult InitStmt = new (Context)
16240
16241 if (!InitStmt.isUsable())
16242 return StmtError();
16243
16244 auto MakeIVRef = [&SemaRef = this->SemaRef, IndexDecl, IVType,
16245 Loc = InitVal->getExprLoc()]() {
16246 return buildDeclRefExpr(SemaRef, IndexDecl, IVType, Loc, false);
16247 };
16248
16249 // 2. Iteratively compute the max number of logical iterations Max(NI_1, NI_2,
16250 // ..., NI_k)
16251 //
16252 // This loop accumulates the maximum value across multiple expressions,
16253 // ensuring each step constructs a unique AST node for correctness. By using
16254 // intermediate temporary variables and conditional operators, we maintain
16255 // distinct nodes and avoid duplicating subtrees, For instance, max(a,b,c):
16256 // omp.temp0 = max(a, b)
16257 // omp.temp1 = max(omp.temp0, c)
16258 // omp.fuse.max = max(omp.temp1, omp.temp0)
16259
16260 ExprResult MaxExpr;
16261 // I is the range of loops in the sequence that we fuse.
16262 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16263 DeclRefExpr *NIRef = MakeVarDeclRef(NIVarDecls[J]);
16264 QualType NITy = NIRef->getType();
16265
16266 if (MaxExpr.isUnset()) {
16267 // Initialize MaxExpr with the first NI expression
16268 MaxExpr = NIRef;
16269 } else {
16270 // Create a new acummulator variable t_i = MaxExpr
16271 std::string TempName = (Twine(".omp.temp.") + Twine(J)).str();
16272 VarDecl *TempDecl =
16273 buildVarDecl(SemaRef, {}, NITy, TempName, nullptr, nullptr);
16274 TempDecl->setInit(MaxExpr.get());
16275 DeclRefExpr *TempRef =
16276 buildDeclRefExpr(SemaRef, TempDecl, NITy, SourceLocation(), false);
16277 DeclRefExpr *TempRef2 =
16278 buildDeclRefExpr(SemaRef, TempDecl, NITy, SourceLocation(), false);
16279 // Add a DeclStmt to PreInits to ensure the variable is declared.
16280 StmtResult TempStmt = new (Context)
16282
16283 if (!TempStmt.isUsable())
16284 return StmtError();
16285 PreInits.push_back(TempStmt.get());
16286
16287 // Build MaxExpr <-(MaxExpr > NIRef ? MaxExpr : NIRef)
16289 SemaRef.BuildBinOp(nullptr, SourceLocation(), BO_GT, TempRef, NIRef);
16290 // Handle any errors in Comparison creation
16291 if (!Comparison.isUsable())
16292 return StmtError();
16293
16294 DeclRefExpr *NIRef2 = MakeVarDeclRef(NIVarDecls[J]);
16295 // Update MaxExpr using a conditional expression to hold the max value
16296 MaxExpr = new (Context) ConditionalOperator(
16297 Comparison.get(), SourceLocation(), TempRef2, SourceLocation(),
16298 NIRef2->getExprStmt(), NITy, VK_LValue, OK_Ordinary);
16299
16300 if (!MaxExpr.isUsable())
16301 return StmtError();
16302 }
16303 }
16304 if (!MaxExpr.isUsable())
16305 return StmtError();
16306
16307 // 3. Declare the max variable
16308 const std::string MaxName = Twine(".omp.fuse.max").str();
16309 VarDecl *MaxDecl =
16310 buildVarDecl(SemaRef, {}, IVType, MaxName, nullptr, nullptr);
16311 MaxDecl->setInit(MaxExpr.get());
16312 DeclRefExpr *MaxRef = buildDeclRefExpr(SemaRef, MaxDecl, IVType, {}, false);
16313 StmtResult MaxStmt = new (Context)
16315
16316 if (MaxStmt.isInvalid())
16317 return StmtError();
16318 PreInits.push_back(MaxStmt.get());
16319
16320 // 4. Create condition Expr: index < n_max
16321 ExprResult CondExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_LT,
16322 MakeIVRef(), MaxRef);
16323 if (!CondExpr.isUsable())
16324 return StmtError();
16325
16326 // 5. Increment Expr: ++index
16327 ExprResult IncrExpr =
16328 SemaRef.BuildUnaryOp(CurScope, SourceLocation(), UO_PreInc, MakeIVRef());
16329 if (!IncrExpr.isUsable())
16330 return StmtError();
16331
16332 // 6. Build the Fused Loop Body
16333 // The final fused loop iterates over the maximum logical range. Inside the
16334 // loop, each original loop's index is calculated dynamically, and its body
16335 // is executed conditionally.
16336 //
16337 // Each sub-loop's body is guarded by a conditional statement to ensure
16338 // it executes only within its logical iteration range:
16339 //
16340 // if (fuse.index < ni_k){
16341 // iv_k = lb_k + st_k * fuse.index;
16342 // original.index = iv_k
16343 // body(k);
16344 // }
16345
16346 CompoundStmt *FusedBody = nullptr;
16347 SmallVector<Stmt *, 4> FusedBodyStmts;
16348 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16349 // Assingment of the original sub-loop index to compute the logical index
16350 // IV_k = LB_k + omp.fuse.index * ST_k
16351 ExprResult IdxExpr =
16352 SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Mul,
16353 MakeVarDeclRef(STVarDecls[J]), MakeIVRef());
16354 if (!IdxExpr.isUsable())
16355 return StmtError();
16356 IdxExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Add,
16357 MakeVarDeclRef(LBVarDecls[J]), IdxExpr.get());
16358
16359 if (!IdxExpr.isUsable())
16360 return StmtError();
16361 IdxExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Assign,
16362 MakeVarDeclRef(IVVarDecls[J]), IdxExpr.get());
16363 if (!IdxExpr.isUsable())
16364 return StmtError();
16365
16366 // Update the original i_k = IV_k
16367 SmallVector<Stmt *, 4> BodyStmts;
16368 BodyStmts.push_back(IdxExpr.get());
16369 llvm::append_range(BodyStmts, SeqAnalysis.Loops[I].HelperExprs.Updates);
16370
16371 // If the loop is a CXXForRangeStmt then the iterator variable is needed
16372 if (auto *SourceCXXFor =
16373 dyn_cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt))
16374 BodyStmts.push_back(SourceCXXFor->getLoopVarStmt());
16375
16376 Stmt *Body =
16377 (isa<ForStmt>(SeqAnalysis.Loops[I].TheForStmt))
16378 ? cast<ForStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody()
16379 : cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody();
16380 BodyStmts.push_back(Body);
16381
16382 CompoundStmt *CombinedBody =
16383 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
16386 SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_LT, MakeIVRef(),
16387 MakeVarDeclRef(NIVarDecls[J]));
16388
16389 if (!Condition.isUsable())
16390 return StmtError();
16391
16392 IfStmt *IfStatement = IfStmt::Create(
16393 Context, SourceLocation(), IfStatementKind::Ordinary, nullptr, nullptr,
16394 Condition.get(), SourceLocation(), SourceLocation(), CombinedBody,
16395 SourceLocation(), nullptr);
16396
16397 FusedBodyStmts.push_back(IfStatement);
16398 }
16399 FusedBody = CompoundStmt::Create(Context, FusedBodyStmts, FPOptionsOverride(),
16401
16402 // 7. Construct the final fused loop
16403 ForStmt *FusedForStmt = new (Context)
16404 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr, IncrExpr.get(),
16405 FusedBody, InitStmt.get()->getBeginLoc(), SourceLocation(),
16406 IncrExpr.get()->getEndLoc());
16407
16408 // In the case of looprange, the result of fuse won't simply
16409 // be a single loop (ForStmt), but rather a loop sequence
16410 // (CompoundStmt) of 3 parts: the pre-fusion loops, the fused loop
16411 // and the post-fusion loops, preserving its original order.
16412 //
16413 // Note: If looprange clause produces a single fused loop nest then
16414 // this compound statement wrapper is unnecessary (Therefore this
16415 // treatment is skipped)
16416
16417 Stmt *FusionStmt = FusedForStmt;
16418 if (LRC && CountVal != SeqAnalysis.LoopSeqSize) {
16419 SmallVector<Stmt *, 4> FinalLoops;
16420
16421 // Reset the transform index
16422 TransformIndex = 0;
16423
16424 // Collect all non-fused loops before and after the fused region.
16425 // Pre-fusion and post-fusion loops are inserted in order exploiting their
16426 // symmetry, along with their corresponding transformation pre-inits if
16427 // needed. The fused loop is added between the two regions.
16428 for (unsigned I : llvm::seq<unsigned>(SeqAnalysis.LoopSeqSize)) {
16429 if (I >= FirstVal - 1 && I < FirstVal + CountVal - 1) {
16430 // Update the Transformation counter to skip already treated
16431 // loop transformations
16432 if (!SeqAnalysis.Loops[I].isLoopTransformation())
16433 ++TransformIndex;
16434 continue;
16435 }
16436
16437 // No need to handle:
16438 // Regular loops: they are kept intact as-is.
16439 // Loop-sequence-generating transformations: already handled earlier.
16440 // Only TransformSingleLoop requires inserting pre-inits here
16441 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16442 const auto &TransformPreInit =
16443 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16444 if (!TransformPreInit.empty())
16445 llvm::append_range(PreInits, TransformPreInit);
16446 }
16447
16448 FinalLoops.push_back(SeqAnalysis.Loops[I].TheForStmt);
16449 }
16450
16451 FinalLoops.insert(FinalLoops.begin() + (FirstVal - 1), FusedForStmt);
16452 FusionStmt = CompoundStmt::Create(Context, FinalLoops, FPOptionsOverride(),
16454 }
16455 return OMPFuseDirective::Create(Context, StartLoc, EndLoc, Clauses,
16456 NumGeneratedTopLevelLoops, AStmt, FusionStmt,
16457 buildPreInits(Context, PreInits));
16458}
16459
16461 Expr *Expr,
16462 SourceLocation StartLoc,
16463 SourceLocation LParenLoc,
16464 SourceLocation EndLoc) {
16465 OMPClause *Res = nullptr;
16466 switch (Kind) {
16467 case OMPC_final:
16468 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
16469 break;
16470 case OMPC_safelen:
16471 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
16472 break;
16473 case OMPC_simdlen:
16474 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
16475 break;
16476 case OMPC_allocator:
16477 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
16478 break;
16479 case OMPC_collapse:
16480 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
16481 break;
16482 case OMPC_ordered:
16483 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
16484 break;
16485 case OMPC_nowait:
16486 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc, LParenLoc, Expr);
16487 break;
16488 case OMPC_priority:
16489 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
16490 break;
16491 case OMPC_hint:
16492 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
16493 break;
16494 case OMPC_depobj:
16495 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
16496 break;
16497 case OMPC_detach:
16498 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
16499 break;
16500 case OMPC_novariants:
16501 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
16502 break;
16503 case OMPC_nocontext:
16504 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
16505 break;
16506 case OMPC_filter:
16507 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
16508 break;
16509 case OMPC_partial:
16510 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
16511 break;
16512 case OMPC_message:
16513 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
16514 break;
16515 case OMPC_align:
16516 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
16517 break;
16518 case OMPC_ompx_dyn_cgroup_mem:
16519 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
16520 break;
16521 case OMPC_holds:
16522 Res = ActOnOpenMPHoldsClause(Expr, StartLoc, LParenLoc, EndLoc);
16523 break;
16524 case OMPC_dyn_groupprivate:
16525 case OMPC_grainsize:
16526 case OMPC_num_tasks:
16527 case OMPC_num_threads:
16528 case OMPC_device:
16529 case OMPC_if:
16530 case OMPC_default:
16531 case OMPC_proc_bind:
16532 case OMPC_schedule:
16533 case OMPC_private:
16534 case OMPC_firstprivate:
16535 case OMPC_lastprivate:
16536 case OMPC_shared:
16537 case OMPC_reduction:
16538 case OMPC_task_reduction:
16539 case OMPC_in_reduction:
16540 case OMPC_linear:
16541 case OMPC_aligned:
16542 case OMPC_copyin:
16543 case OMPC_copyprivate:
16544 case OMPC_untied:
16545 case OMPC_mergeable:
16546 case OMPC_threadprivate:
16547 case OMPC_groupprivate:
16548 case OMPC_sizes:
16549 case OMPC_allocate:
16550 case OMPC_flush:
16551 case OMPC_read:
16552 case OMPC_write:
16553 case OMPC_update:
16554 case OMPC_capture:
16555 case OMPC_compare:
16556 case OMPC_seq_cst:
16557 case OMPC_acq_rel:
16558 case OMPC_acquire:
16559 case OMPC_release:
16560 case OMPC_relaxed:
16561 case OMPC_depend:
16562 case OMPC_threads:
16563 case OMPC_simd:
16564 case OMPC_map:
16565 case OMPC_nogroup:
16566 case OMPC_dist_schedule:
16567 case OMPC_defaultmap:
16568 case OMPC_unknown:
16569 case OMPC_uniform:
16570 case OMPC_to:
16571 case OMPC_from:
16572 case OMPC_use_device_ptr:
16573 case OMPC_use_device_addr:
16574 case OMPC_is_device_ptr:
16575 case OMPC_unified_address:
16576 case OMPC_unified_shared_memory:
16577 case OMPC_reverse_offload:
16578 case OMPC_dynamic_allocators:
16579 case OMPC_atomic_default_mem_order:
16580 case OMPC_self_maps:
16581 case OMPC_device_type:
16582 case OMPC_match:
16583 case OMPC_nontemporal:
16584 case OMPC_order:
16585 case OMPC_at:
16586 case OMPC_severity:
16587 case OMPC_destroy:
16588 case OMPC_inclusive:
16589 case OMPC_exclusive:
16590 case OMPC_uses_allocators:
16591 case OMPC_affinity:
16592 case OMPC_when:
16593 case OMPC_bind:
16594 case OMPC_num_teams:
16595 case OMPC_thread_limit:
16596 default:
16597 llvm_unreachable("Clause is not allowed.");
16598 }
16599 return Res;
16600}
16601
16602// An OpenMP directive such as 'target parallel' has two captured regions:
16603// for the 'target' and 'parallel' respectively. This function returns
16604// the region in which to capture expressions associated with a clause.
16605// A return value of OMPD_unknown signifies that the expression should not
16606// be captured.
16608 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
16609 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
16610 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
16611 "Invalid directive with CKind-clause");
16612
16613 // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
16614 if (NameModifier != OMPD_unknown &&
16615 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
16616 return OMPD_unknown;
16617
16618 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(DKind);
16619
16620 // [5.2:341:24-30]
16621 // If the clauses have expressions on them, such as for various clauses where
16622 // the argument of the clause is an expression, or lower-bound, length, or
16623 // stride expressions inside array sections (or subscript and stride
16624 // expressions in subscript-triplet for Fortran), or linear-step or alignment
16625 // expressions, the expressions are evaluated immediately before the construct
16626 // to which the clause has been split or duplicated per the above rules
16627 // (therefore inside of the outer leaf constructs). However, the expressions
16628 // inside the num_teams and thread_limit clauses are always evaluated before
16629 // the outermost leaf construct.
16630
16631 // Process special cases first.
16632 switch (CKind) {
16633 case OMPC_if:
16634 switch (DKind) {
16635 case OMPD_teams_loop:
16636 case OMPD_target_teams_loop:
16637 // For [target] teams loop, assume capture region is 'teams' so it's
16638 // available for codegen later to use if/when necessary.
16639 return OMPD_teams;
16640 case OMPD_target_update:
16641 case OMPD_target_enter_data:
16642 case OMPD_target_exit_data:
16643 return OMPD_task;
16644 default:
16645 break;
16646 }
16647 break;
16648 case OMPC_num_teams:
16649 case OMPC_thread_limit:
16650 case OMPC_ompx_dyn_cgroup_mem:
16651 case OMPC_dyn_groupprivate:
16652 // TODO: This may need to consider teams too.
16653 if (Leafs[0] == OMPD_target)
16654 return OMPD_target;
16655 break;
16656 case OMPC_device:
16657 if (Leafs[0] == OMPD_target ||
16658 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
16659 OMPD_target_enter_data, OMPD_target_exit_data},
16660 DKind))
16661 return OMPD_task;
16662 break;
16663 case OMPC_novariants:
16664 case OMPC_nocontext:
16665 if (DKind == OMPD_dispatch)
16666 return OMPD_task;
16667 break;
16668 case OMPC_when:
16669 if (DKind == OMPD_metadirective)
16670 return OMPD_metadirective;
16671 break;
16672 case OMPC_filter:
16673 return OMPD_unknown;
16674 default:
16675 break;
16676 }
16677
16678 // If none of the special cases above applied, and DKind is a capturing
16679 // directive, find the innermost enclosing leaf construct that allows the
16680 // clause, and returns the corresponding capture region.
16681
16682 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
16683 // Find the index in "Leafs" of the last leaf that allows the given
16684 // clause. The search will only include indexes [0, EndIdx).
16685 // EndIdx may be set to the index of the NameModifier, if present.
16686 int InnermostIdx = [&]() {
16687 for (int I = EndIdx - 1; I >= 0; --I) {
16688 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
16689 return I;
16690 }
16691 return -1;
16692 }();
16693
16694 // Find the nearest enclosing capture region.
16696 for (int I = InnermostIdx - 1; I >= 0; --I) {
16697 if (!isOpenMPCapturingDirective(Leafs[I]))
16698 continue;
16699 Regions.clear();
16700 getOpenMPCaptureRegions(Regions, Leafs[I]);
16701 if (Regions[0] != OMPD_unknown)
16702 return Regions.back();
16703 }
16704 return OMPD_unknown;
16705 };
16706
16707 if (isOpenMPCapturingDirective(DKind)) {
16708 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
16709 for (int I = 0, E = Leafs.size(); I != E; ++I) {
16710 if (Leafs[I] == Dir)
16711 return I + 1;
16712 }
16713 return 0;
16714 };
16715
16716 int End = NameModifier == OMPD_unknown ? Leafs.size()
16717 : GetLeafIndex(NameModifier);
16718 return GetEnclosingRegion(End, CKind);
16719 }
16720
16721 return OMPD_unknown;
16722}
16723
16725 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
16726 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
16727 SourceLocation ColonLoc, SourceLocation EndLoc) {
16728 Expr *ValExpr = Condition;
16729 Stmt *HelperValStmt = nullptr;
16730 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16731 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16732 !Condition->isInstantiationDependent() &&
16733 !Condition->containsUnexpandedParameterPack()) {
16734 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
16735 if (Val.isInvalid())
16736 return nullptr;
16737
16738 ValExpr = Val.get();
16739
16740 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16741 CaptureRegion = getOpenMPCaptureRegionForClause(
16742 DKind, OMPC_if, getLangOpts().OpenMP, NameModifier);
16743 if (CaptureRegion != OMPD_unknown &&
16744 !SemaRef.CurContext->isDependentContext()) {
16745 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16746 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16747 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16748 HelperValStmt = buildPreInits(getASTContext(), Captures);
16749 }
16750 }
16751
16752 return new (getASTContext())
16753 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16754 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16755}
16756
16758 SourceLocation StartLoc,
16759 SourceLocation LParenLoc,
16760 SourceLocation EndLoc) {
16761 Expr *ValExpr = Condition;
16762 Stmt *HelperValStmt = nullptr;
16763 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16764 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16765 !Condition->isInstantiationDependent() &&
16766 !Condition->containsUnexpandedParameterPack()) {
16767 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
16768 if (Val.isInvalid())
16769 return nullptr;
16770
16771 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
16772
16773 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16774 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final,
16775 getLangOpts().OpenMP);
16776 if (CaptureRegion != OMPD_unknown &&
16777 !SemaRef.CurContext->isDependentContext()) {
16778 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16779 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16780 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16781 HelperValStmt = buildPreInits(getASTContext(), Captures);
16782 }
16783 }
16784
16785 return new (getASTContext()) OMPFinalClause(
16786 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16787}
16788
16791 Expr *Op) {
16792 if (!Op)
16793 return ExprError();
16794
16795 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
16796 public:
16797 IntConvertDiagnoser()
16798 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {}
16799 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
16800 QualType T) override {
16801 return S.Diag(Loc, diag::err_omp_not_integral) << T;
16802 }
16803 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
16804 QualType T) override {
16805 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
16806 }
16807 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
16808 QualType T,
16809 QualType ConvTy) override {
16810 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
16811 }
16812 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
16813 QualType ConvTy) override {
16814 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16815 << ConvTy->isEnumeralType() << ConvTy;
16816 }
16817 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
16818 QualType T) override {
16819 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
16820 }
16821 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
16822 QualType ConvTy) override {
16823 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16824 << ConvTy->isEnumeralType() << ConvTy;
16825 }
16826 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
16827 QualType) override {
16828 llvm_unreachable("conversion functions are permitted");
16829 }
16830 } ConvertDiagnoser;
16831 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16832}
16833
16834static bool
16836 bool StrictlyPositive, bool BuildCapture = false,
16837 OpenMPDirectiveKind DKind = OMPD_unknown,
16838 OpenMPDirectiveKind *CaptureRegion = nullptr,
16839 Stmt **HelperValStmt = nullptr) {
16840 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
16841 !ValExpr->isInstantiationDependent()) {
16842 SourceLocation Loc = ValExpr->getExprLoc();
16844 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
16845 if (Value.isInvalid())
16846 return false;
16847
16848 ValExpr = Value.get();
16849 // The expression must evaluate to a non-negative integer value.
16850 if (std::optional<llvm::APSInt> Result =
16851 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
16852 if (Result->isSigned() &&
16853 !((!StrictlyPositive && Result->isNonNegative()) ||
16854 (StrictlyPositive && Result->isStrictlyPositive()))) {
16855 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
16856 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
16857 << ValExpr->getSourceRange();
16858 return false;
16859 }
16860 }
16861 if (!BuildCapture)
16862 return true;
16863 *CaptureRegion =
16864 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
16865 if (*CaptureRegion != OMPD_unknown &&
16866 !SemaRef.CurContext->isDependentContext()) {
16867 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16868 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16869 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16870 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
16871 }
16872 }
16873 return true;
16874}
16875
16876static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First,
16877 unsigned Last,
16878 ArrayRef<unsigned> Exclude = {}) {
16879 SmallString<256> Buffer;
16880 llvm::raw_svector_ostream Out(Buffer);
16881 unsigned Skipped = Exclude.size();
16882 for (unsigned I = First; I < Last; ++I) {
16883 if (llvm::is_contained(Exclude, I)) {
16884 --Skipped;
16885 continue;
16886 }
16887 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
16888 if (I + Skipped + 2 == Last)
16889 Out << " or ";
16890 else if (I + Skipped + 1 != Last)
16891 Out << ", ";
16892 }
16893 return std::string(Out.str());
16894}
16895
16897 OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads,
16898 SourceLocation StartLoc, SourceLocation LParenLoc,
16899 SourceLocation ModifierLoc, SourceLocation EndLoc) {
16900 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 60) &&
16901 "Unexpected num_threads modifier in OpenMP < 60.");
16902
16903 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTHREADS_unknown) {
16904 std::string Values = getListOfPossibleValues(OMPC_num_threads, /*First=*/0,
16906 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
16907 << Values << getOpenMPClauseNameForDiag(OMPC_num_threads);
16908 return nullptr;
16909 }
16910
16911 Expr *ValExpr = NumThreads;
16912 Stmt *HelperValStmt = nullptr;
16913
16914 // OpenMP [2.5, Restrictions]
16915 // The num_threads expression must evaluate to a positive integer value.
16916 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads,
16917 /*StrictlyPositive=*/true))
16918 return nullptr;
16919
16920 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16922 DKind, OMPC_num_threads, getLangOpts().OpenMP);
16923 if (CaptureRegion != OMPD_unknown &&
16924 !SemaRef.CurContext->isDependentContext()) {
16925 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16926 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16927 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16928 HelperValStmt = buildPreInits(getASTContext(), Captures);
16929 }
16930
16931 return new (getASTContext())
16932 OMPNumThreadsClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
16933 StartLoc, LParenLoc, ModifierLoc, EndLoc);
16934}
16935
16937 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
16938 bool SuppressExprDiags) {
16939 if (!E)
16940 return ExprError();
16941 if (E->isValueDependent() || E->isTypeDependent() ||
16943 return E;
16944
16945 llvm::APSInt Result;
16946 ExprResult ICE;
16947 if (SuppressExprDiags) {
16948 // Use a custom diagnoser that suppresses 'note' diagnostics about the
16949 // expression.
16950 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
16951 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
16953 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
16954 llvm_unreachable("Diagnostic suppressed");
16955 }
16956 } Diagnoser;
16957 ICE = SemaRef.VerifyIntegerConstantExpression(E, &Result, Diagnoser,
16959 } else {
16960 ICE =
16961 SemaRef.VerifyIntegerConstantExpression(E, &Result,
16962 /*FIXME*/ AllowFoldKind::Allow);
16963 }
16964 if (ICE.isInvalid())
16965 return ExprError();
16966
16967 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
16968 (!StrictlyPositive && !Result.isNonNegative())) {
16969 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
16970 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
16971 << E->getSourceRange();
16972 return ExprError();
16973 }
16974 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
16975 CKind == OMPC_allocate) &&
16976 !Result.isPowerOf2()) {
16977 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
16978 << E->getSourceRange();
16979 return ExprError();
16980 }
16981
16982 if (!Result.isRepresentableByInt64()) {
16983 Diag(E->getExprLoc(), diag::err_omp_large_expression_in_clause)
16985 return ExprError();
16986 }
16987
16988 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
16989 DSAStack->setAssociatedLoops(Result.getExtValue());
16990 else if (CKind == OMPC_ordered)
16991 DSAStack->setAssociatedLoops(Result.getExtValue());
16992 return ICE;
16993}
16994
16995void SemaOpenMP::setOpenMPDeviceNum(int Num) { DeviceNum = Num; }
16996
16997void SemaOpenMP::setOpenMPDeviceNumID(StringRef ID) { DeviceNumID = ID; }
16998
16999int SemaOpenMP::getOpenMPDeviceNum() const { return DeviceNum; }
17000
17002 llvm::APSInt Result;
17003 Expr::EvalResult EvalResult;
17004 // Evaluate the expression to an integer value
17005 if (!DeviceNumExpr->isValueDependent() &&
17006 DeviceNumExpr->EvaluateAsInt(EvalResult, SemaRef.Context)) {
17007 // The device expression must evaluate to a non-negative integer value.
17008 Result = EvalResult.Val.getInt();
17009 if (Result.isNonNegative()) {
17010 setOpenMPDeviceNum(Result.getZExtValue());
17011 } else {
17012 Diag(DeviceNumExpr->getExprLoc(),
17013 diag::err_omp_negative_expression_in_clause)
17014 << "device_num" << 0 << DeviceNumExpr->getSourceRange();
17015 }
17016 } else if (auto *DeclRef = dyn_cast<DeclRefExpr>(DeviceNumExpr)) {
17017 // Check if the expression is an identifier
17018 IdentifierInfo *IdInfo = DeclRef->getDecl()->getIdentifier();
17019 if (IdInfo) {
17020 setOpenMPDeviceNumID(IdInfo->getName());
17021 }
17022 } else {
17023 Diag(DeviceNumExpr->getExprLoc(), diag::err_expected_expression);
17024 }
17025}
17026
17028 SourceLocation StartLoc,
17029 SourceLocation LParenLoc,
17030 SourceLocation EndLoc) {
17031 // OpenMP [2.8.1, simd construct, Description]
17032 // The parameter of the safelen clause must be a constant
17033 // positive integer expression.
17034 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
17035 if (Safelen.isInvalid())
17036 return nullptr;
17037 return new (getASTContext())
17038 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
17039}
17040
17042 SourceLocation StartLoc,
17043 SourceLocation LParenLoc,
17044 SourceLocation EndLoc) {
17045 // OpenMP [2.8.1, simd construct, Description]
17046 // The parameter of the simdlen clause must be a constant
17047 // positive integer expression.
17048 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
17049 if (Simdlen.isInvalid())
17050 return nullptr;
17051 return new (getASTContext())
17052 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
17053}
17054
17055/// Tries to find omp_allocator_handle_t type.
17057 DSAStackTy *Stack) {
17058 if (!Stack->getOMPAllocatorHandleT().isNull())
17059 return true;
17060
17061 // Set the allocator handle type.
17062 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
17063 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
17064 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
17065 S.Diag(Loc, diag::err_omp_implied_type_not_found)
17066 << "omp_allocator_handle_t";
17067 return false;
17068 }
17069 QualType AllocatorHandleEnumTy = PT.get();
17070 AllocatorHandleEnumTy.addConst();
17071 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
17072
17073 // Fill the predefined allocator map.
17074 bool ErrorFound = false;
17075 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
17076 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
17077 StringRef Allocator =
17078 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
17079 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
17080 auto *VD = dyn_cast_or_null<ValueDecl>(
17081 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
17082 if (!VD) {
17083 ErrorFound = true;
17084 break;
17085 }
17086 QualType AllocatorType =
17088 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
17089 if (!Res.isUsable()) {
17090 ErrorFound = true;
17091 break;
17092 }
17093 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
17095 /*AllowExplicit=*/true);
17096 if (!Res.isUsable()) {
17097 ErrorFound = true;
17098 break;
17099 }
17100 Stack->setAllocator(AllocatorKind, Res.get());
17101 }
17102 if (ErrorFound) {
17103 S.Diag(Loc, diag::err_omp_implied_type_not_found)
17104 << "omp_allocator_handle_t";
17105 return false;
17106 }
17107
17108 return true;
17109}
17110
17112 SourceLocation StartLoc,
17113 SourceLocation LParenLoc,
17114 SourceLocation EndLoc) {
17115 // OpenMP [2.11.3, allocate Directive, Description]
17116 // allocator is an expression of omp_allocator_handle_t type.
17118 return nullptr;
17119
17120 ExprResult Allocator = SemaRef.DefaultLvalueConversion(A);
17121 if (Allocator.isInvalid())
17122 return nullptr;
17123 Allocator = SemaRef.PerformImplicitConversion(
17124 Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
17126 /*AllowExplicit=*/true);
17127 if (Allocator.isInvalid())
17128 return nullptr;
17129 return new (getASTContext())
17130 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
17131}
17132
17134 SourceLocation StartLoc,
17135 SourceLocation LParenLoc,
17136 SourceLocation EndLoc) {
17137 // OpenMP [2.7.1, loop construct, Description]
17138 // OpenMP [2.8.1, simd construct, Description]
17139 // OpenMP [2.9.6, distribute construct, Description]
17140 // The parameter of the collapse clause must be a constant
17141 // positive integer expression.
17142 ExprResult NumForLoopsResult =
17143 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
17144 if (NumForLoopsResult.isInvalid())
17145 return nullptr;
17146 return new (getASTContext())
17147 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
17148}
17149
17151 SourceLocation EndLoc,
17152 SourceLocation LParenLoc,
17153 Expr *NumForLoops) {
17154 // OpenMP [2.7.1, loop construct, Description]
17155 // OpenMP [2.8.1, simd construct, Description]
17156 // OpenMP [2.9.6, distribute construct, Description]
17157 // The parameter of the ordered clause must be a constant
17158 // positive integer expression if any.
17159 if (NumForLoops && LParenLoc.isValid()) {
17160 ExprResult NumForLoopsResult =
17161 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
17162 if (NumForLoopsResult.isInvalid())
17163 return nullptr;
17164 NumForLoops = NumForLoopsResult.get();
17165 } else {
17166 NumForLoops = nullptr;
17167 }
17168 auto *Clause =
17170 NumForLoops ? DSAStack->getAssociatedLoops() : 0,
17171 StartLoc, LParenLoc, EndLoc);
17172 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
17173 return Clause;
17174}
17175
17177 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
17178 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17179 OMPClause *Res = nullptr;
17180 switch (Kind) {
17181 case OMPC_proc_bind:
17182 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
17183 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17184 break;
17185 case OMPC_atomic_default_mem_order:
17187 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
17188 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17189 break;
17190 case OMPC_fail:
17191 Res = ActOnOpenMPFailClause(static_cast<OpenMPClauseKind>(Argument),
17192 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17193 break;
17194 case OMPC_update:
17195 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
17196 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17197 break;
17198 case OMPC_bind:
17199 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
17200 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17201 break;
17202 case OMPC_at:
17203 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
17204 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17205 break;
17206 case OMPC_severity:
17208 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
17209 LParenLoc, EndLoc);
17210 break;
17211 case OMPC_threadset:
17212 Res = ActOnOpenMPThreadsetClause(static_cast<OpenMPThreadsetKind>(Argument),
17213 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17214 break;
17215 case OMPC_if:
17216 case OMPC_final:
17217 case OMPC_num_threads:
17218 case OMPC_safelen:
17219 case OMPC_simdlen:
17220 case OMPC_sizes:
17221 case OMPC_allocator:
17222 case OMPC_collapse:
17223 case OMPC_schedule:
17224 case OMPC_private:
17225 case OMPC_firstprivate:
17226 case OMPC_lastprivate:
17227 case OMPC_shared:
17228 case OMPC_reduction:
17229 case OMPC_task_reduction:
17230 case OMPC_in_reduction:
17231 case OMPC_linear:
17232 case OMPC_aligned:
17233 case OMPC_copyin:
17234 case OMPC_copyprivate:
17235 case OMPC_ordered:
17236 case OMPC_nowait:
17237 case OMPC_untied:
17238 case OMPC_mergeable:
17239 case OMPC_threadprivate:
17240 case OMPC_groupprivate:
17241 case OMPC_allocate:
17242 case OMPC_flush:
17243 case OMPC_depobj:
17244 case OMPC_read:
17245 case OMPC_write:
17246 case OMPC_capture:
17247 case OMPC_compare:
17248 case OMPC_seq_cst:
17249 case OMPC_acq_rel:
17250 case OMPC_acquire:
17251 case OMPC_release:
17252 case OMPC_relaxed:
17253 case OMPC_depend:
17254 case OMPC_device:
17255 case OMPC_threads:
17256 case OMPC_simd:
17257 case OMPC_map:
17258 case OMPC_num_teams:
17259 case OMPC_thread_limit:
17260 case OMPC_priority:
17261 case OMPC_grainsize:
17262 case OMPC_nogroup:
17263 case OMPC_num_tasks:
17264 case OMPC_hint:
17265 case OMPC_dist_schedule:
17266 case OMPC_default:
17267 case OMPC_defaultmap:
17268 case OMPC_unknown:
17269 case OMPC_uniform:
17270 case OMPC_to:
17271 case OMPC_from:
17272 case OMPC_use_device_ptr:
17273 case OMPC_use_device_addr:
17274 case OMPC_is_device_ptr:
17275 case OMPC_has_device_addr:
17276 case OMPC_unified_address:
17277 case OMPC_unified_shared_memory:
17278 case OMPC_reverse_offload:
17279 case OMPC_dynamic_allocators:
17280 case OMPC_self_maps:
17281 case OMPC_device_type:
17282 case OMPC_match:
17283 case OMPC_nontemporal:
17284 case OMPC_destroy:
17285 case OMPC_novariants:
17286 case OMPC_nocontext:
17287 case OMPC_detach:
17288 case OMPC_inclusive:
17289 case OMPC_exclusive:
17290 case OMPC_uses_allocators:
17291 case OMPC_affinity:
17292 case OMPC_when:
17293 case OMPC_message:
17294 default:
17295 llvm_unreachable("Clause is not allowed.");
17296 }
17297 return Res;
17298}
17299
17301 llvm::omp::DefaultKind M, SourceLocation MLoc,
17303 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17304 if (M == OMP_DEFAULT_unknown) {
17305 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17306 << getListOfPossibleValues(OMPC_default, /*First=*/0,
17307 /*Last=*/unsigned(OMP_DEFAULT_unknown))
17308 << getOpenMPClauseNameForDiag(OMPC_default);
17309 return nullptr;
17310 }
17311 if (VCKind == OMPC_DEFAULT_VC_unknown) {
17312 Diag(VCKindLoc, diag::err_omp_default_vc)
17313 << getOpenMPSimpleClauseTypeName(OMPC_default, unsigned(M));
17314 return nullptr;
17315 }
17316
17317 bool IsTargetDefault =
17318 getLangOpts().OpenMP >= 60 &&
17319 isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective());
17320
17321 // OpenMP 6.0, page 224, lines 3-4 default Clause, Semantics
17322 // If data-sharing-attribute is shared then the clause has no effect
17323 // on a target construct;
17324 if (IsTargetDefault && M == OMP_DEFAULT_shared)
17325 return nullptr;
17326
17327 auto SetDefaultClauseAttrs = [&](llvm::omp::DefaultKind M,
17330 OpenMPDefaultmapClauseKind DefMapKind;
17331 // default data-sharing-attribute
17332 switch (M) {
17333 case OMP_DEFAULT_none:
17334 if (IsTargetDefault)
17335 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_none;
17336 else
17337 DSAStack->setDefaultDSANone(MLoc);
17338 break;
17339 case OMP_DEFAULT_firstprivate:
17340 if (IsTargetDefault)
17341 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_firstprivate;
17342 else
17343 DSAStack->setDefaultDSAFirstPrivate(MLoc);
17344 break;
17345 case OMP_DEFAULT_private:
17346 if (IsTargetDefault)
17347 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_private;
17348 else
17349 DSAStack->setDefaultDSAPrivate(MLoc);
17350 break;
17351 case OMP_DEFAULT_shared:
17352 assert(!IsTargetDefault && "DSA shared invalid with target directive");
17353 DSAStack->setDefaultDSAShared(MLoc);
17354 break;
17355 default:
17356 llvm_unreachable("unexpected DSA in OpenMP default clause");
17357 }
17358 // default variable-category
17359 switch (VCKind) {
17360 case OMPC_DEFAULT_VC_aggregate:
17361 if (IsTargetDefault)
17362 DefMapKind = OMPC_DEFAULTMAP_aggregate;
17363 else
17364 DSAStack->setDefaultDSAVCAggregate(VCKindLoc);
17365 break;
17366 case OMPC_DEFAULT_VC_pointer:
17367 if (IsTargetDefault)
17368 DefMapKind = OMPC_DEFAULTMAP_pointer;
17369 else
17370 DSAStack->setDefaultDSAVCPointer(VCKindLoc);
17371 break;
17372 case OMPC_DEFAULT_VC_scalar:
17373 if (IsTargetDefault)
17374 DefMapKind = OMPC_DEFAULTMAP_scalar;
17375 else
17376 DSAStack->setDefaultDSAVCScalar(VCKindLoc);
17377 break;
17378 case OMPC_DEFAULT_VC_all:
17379 if (IsTargetDefault)
17380 DefMapKind = OMPC_DEFAULTMAP_all;
17381 else
17382 DSAStack->setDefaultDSAVCAll(VCKindLoc);
17383 break;
17384 default:
17385 llvm_unreachable("unexpected variable category in OpenMP default clause");
17386 }
17387 // OpenMP 6.0, page 224, lines 4-5 default Clause, Semantics
17388 // otherwise, its effect on a target construct is equivalent to
17389 // specifying the defaultmap clause with the same data-sharing-attribute
17390 // and variable-category.
17391 //
17392 // If earlier than OpenMP 6.0, or not a target directive, the default DSA
17393 // is/was set as before.
17394 if (IsTargetDefault) {
17395 if (DefMapKind == OMPC_DEFAULTMAP_all) {
17396 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_aggregate, MLoc);
17397 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_scalar, MLoc);
17398 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_pointer, MLoc);
17399 } else {
17400 DSAStack->setDefaultDMAAttr(DefMapMod, DefMapKind, MLoc);
17401 }
17402 }
17403 };
17404
17405 SetDefaultClauseAttrs(M, VCKind);
17406 return new (getASTContext())
17407 OMPDefaultClause(M, MLoc, VCKind, VCKindLoc, StartLoc, LParenLoc, EndLoc);
17408}
17409
17411 SourceLocation KindLoc,
17412 SourceLocation StartLoc,
17413 SourceLocation LParenLoc,
17414 SourceLocation EndLoc) {
17415 if (Kind == OMPC_THREADSET_unknown) {
17416 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17417 << getListOfPossibleValues(OMPC_threadset, /*First=*/0,
17418 /*Last=*/unsigned(OMPC_THREADSET_unknown))
17419 << getOpenMPClauseName(OMPC_threadset);
17420 return nullptr;
17421 }
17422
17423 return new (getASTContext())
17424 OMPThreadsetClause(Kind, KindLoc, StartLoc, LParenLoc, EndLoc);
17425}
17426
17428 SourceLocation KindKwLoc,
17429 SourceLocation StartLoc,
17430 SourceLocation LParenLoc,
17431 SourceLocation EndLoc) {
17432 if (Kind == OMP_PROC_BIND_unknown) {
17433 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17434 << getListOfPossibleValues(OMPC_proc_bind,
17435 /*First=*/unsigned(OMP_PROC_BIND_master),
17436 /*Last=*/
17437 unsigned(getLangOpts().OpenMP > 50
17438 ? OMP_PROC_BIND_primary
17439 : OMP_PROC_BIND_spread) +
17440 1)
17441 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
17442 return nullptr;
17443 }
17444 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
17445 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17446 << getListOfPossibleValues(OMPC_proc_bind,
17447 /*First=*/unsigned(OMP_PROC_BIND_master),
17448 /*Last=*/
17449 unsigned(OMP_PROC_BIND_spread) + 1)
17450 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
17451 return new (getASTContext())
17452 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17453}
17454
17457 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17459 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17461 OMPC_atomic_default_mem_order, /*First=*/0,
17463 << getOpenMPClauseNameForDiag(OMPC_atomic_default_mem_order);
17464 return nullptr;
17465 }
17467 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17468}
17469
17471 SourceLocation KindKwLoc,
17472 SourceLocation StartLoc,
17473 SourceLocation LParenLoc,
17474 SourceLocation EndLoc) {
17475 if (Kind == OMPC_AT_unknown) {
17476 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17477 << getListOfPossibleValues(OMPC_at, /*First=*/0,
17478 /*Last=*/OMPC_AT_unknown)
17479 << getOpenMPClauseNameForDiag(OMPC_at);
17480 return nullptr;
17481 }
17482 return new (getASTContext())
17483 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17484}
17485
17487 SourceLocation KindKwLoc,
17488 SourceLocation StartLoc,
17489 SourceLocation LParenLoc,
17490 SourceLocation EndLoc) {
17491 if (Kind == OMPC_SEVERITY_unknown) {
17492 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17493 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
17494 /*Last=*/OMPC_SEVERITY_unknown)
17495 << getOpenMPClauseNameForDiag(OMPC_severity);
17496 return nullptr;
17497 }
17498 return new (getASTContext())
17499 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17500}
17501
17503 SourceLocation StartLoc,
17504 SourceLocation LParenLoc,
17505 SourceLocation EndLoc) {
17506 assert(ME && "NULL expr in Message clause");
17507 QualType Type = ME->getType();
17508 if ((!Type->isPointerType() && !Type->isArrayType()) ||
17510 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
17511 << getOpenMPClauseNameForDiag(OMPC_message) << 0;
17512 return nullptr;
17513 }
17514
17515 Stmt *HelperValStmt = nullptr;
17516
17517 // Depending on whether this clause appears in an executable context or not,
17518 // we may or may not build a capture.
17519 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17520 OpenMPDirectiveKind CaptureRegion =
17521 DKind == OMPD_unknown ? OMPD_unknown
17523 DKind, OMPC_message, getLangOpts().OpenMP);
17524 if (CaptureRegion != OMPD_unknown &&
17525 !SemaRef.CurContext->isDependentContext()) {
17526 ME = SemaRef.MakeFullExpr(ME).get();
17527 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17528 ME = tryBuildCapture(SemaRef, ME, Captures).get();
17529 HelperValStmt = buildPreInits(getASTContext(), Captures);
17530 }
17531
17532 // Convert array type to pointer type if needed.
17533 ME = SemaRef.DefaultFunctionArrayLvalueConversion(ME).get();
17534
17535 return new (getASTContext()) OMPMessageClause(
17536 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17537}
17538
17541 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
17542 SourceLocation KindLoc, SourceLocation EndLoc) {
17543 if (Kind != OMPC_ORDER_concurrent ||
17544 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
17545 // Kind should be concurrent,
17546 // Modifiers introduced in OpenMP 5.1
17547 static_assert(OMPC_ORDER_unknown > 0,
17548 "OMPC_ORDER_unknown not greater than 0");
17549
17550 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17551 << getListOfPossibleValues(OMPC_order,
17552 /*First=*/0,
17553 /*Last=*/OMPC_ORDER_unknown)
17554 << getOpenMPClauseNameForDiag(OMPC_order);
17555 return nullptr;
17556 }
17557 if (getLangOpts().OpenMP >= 51 && Modifier == OMPC_ORDER_MODIFIER_unknown &&
17558 MLoc.isValid()) {
17559 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17560 << getListOfPossibleValues(OMPC_order,
17561 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
17562 /*Last=*/OMPC_ORDER_MODIFIER_last)
17563 << getOpenMPClauseNameForDiag(OMPC_order);
17564 } else if (getLangOpts().OpenMP >= 50) {
17565 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
17566 if (DSAStack->getCurScope()) {
17567 // mark the current scope with 'order' flag
17568 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
17569 DSAStack->getCurScope()->setFlags(existingFlags |
17571 }
17572 }
17573 return new (getASTContext()) OMPOrderClause(
17574 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
17575}
17576
17578 SourceLocation KindKwLoc,
17579 SourceLocation StartLoc,
17580 SourceLocation LParenLoc,
17581 SourceLocation EndLoc) {
17582 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
17583 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
17584 SmallVector<unsigned> Except = {
17585 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
17586 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
17587 if (getLangOpts().OpenMP < 51)
17588 Except.push_back(OMPC_DEPEND_inoutset);
17589 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17590 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
17591 /*Last=*/OMPC_DEPEND_unknown, Except)
17592 << getOpenMPClauseNameForDiag(OMPC_update);
17593 return nullptr;
17594 }
17595 return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc,
17596 KindKwLoc, Kind, EndLoc);
17597}
17598
17600 SourceLocation StartLoc,
17601 SourceLocation LParenLoc,
17602 SourceLocation EndLoc) {
17603 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
17604
17605 for (Expr *&SizeExpr : SanitizedSizeExprs) {
17606 // Skip if already sanitized, e.g. during a partial template instantiation.
17607 if (!SizeExpr)
17608 continue;
17609
17610 bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes,
17611 /*StrictlyPositive=*/true);
17612
17613 // isNonNegativeIntegerValue returns true for non-integral types (but still
17614 // emits error diagnostic), so check for the expected type explicitly.
17615 QualType SizeTy = SizeExpr->getType();
17616 if (!SizeTy->isIntegerType())
17617 IsValid = false;
17618
17619 // Handling in templates is tricky. There are four possibilities to
17620 // consider:
17621 //
17622 // 1a. The expression is valid and we are in a instantiated template or not
17623 // in a template:
17624 // Pass valid expression to be further analysed later in Sema.
17625 // 1b. The expression is valid and we are in a template (including partial
17626 // instantiation):
17627 // isNonNegativeIntegerValue skipped any checks so there is no
17628 // guarantee it will be correct after instantiation.
17629 // ActOnOpenMPSizesClause will be called again at instantiation when
17630 // it is not in a dependent context anymore. This may cause warnings
17631 // to be emitted multiple times.
17632 // 2a. The expression is invalid and we are in an instantiated template or
17633 // not in a template:
17634 // Invalidate the expression with a clearly wrong value (nullptr) so
17635 // later in Sema we do not have to do the same validity analysis again
17636 // or crash from unexpected data. Error diagnostics have already been
17637 // emitted.
17638 // 2b. The expression is invalid and we are in a template (including partial
17639 // instantiation):
17640 // Pass the invalid expression as-is, template instantiation may
17641 // replace unexpected types/values with valid ones. The directives
17642 // with this clause must not try to use these expressions in dependent
17643 // contexts, but delay analysis until full instantiation.
17644 if (!SizeExpr->isInstantiationDependent() && !IsValid)
17645 SizeExpr = nullptr;
17646 }
17647
17648 return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17649 SanitizedSizeExprs);
17650}
17651
17653 SourceLocation StartLoc,
17654 SourceLocation LParenLoc,
17655 SourceLocation EndLoc) {
17656 size_t NumLoops = PermExprs.size();
17657 SmallVector<Expr *> SanitizedPermExprs;
17658 llvm::append_range(SanitizedPermExprs, PermExprs);
17659
17660 for (Expr *&PermExpr : SanitizedPermExprs) {
17661 // Skip if template-dependent or already sanitized, e.g. during a partial
17662 // template instantiation.
17663 if (!PermExpr || PermExpr->isInstantiationDependent())
17664 continue;
17665
17666 llvm::APSInt PermVal;
17667 ExprResult PermEvalExpr = SemaRef.VerifyIntegerConstantExpression(
17668 PermExpr, &PermVal, AllowFoldKind::Allow);
17669 bool IsValid = PermEvalExpr.isUsable();
17670 if (IsValid)
17671 PermExpr = PermEvalExpr.get();
17672
17673 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
17674 SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
17675 PermEvalExpr.get()->getEndLoc());
17676 Diag(PermEvalExpr.get()->getExprLoc(),
17677 diag::err_omp_interchange_permutation_value_range)
17678 << NumLoops << ExprRange;
17679 IsValid = false;
17680 }
17681
17682 if (!PermExpr->isInstantiationDependent() && !IsValid)
17683 PermExpr = nullptr;
17684 }
17685
17686 return OMPPermutationClause::Create(getASTContext(), StartLoc, LParenLoc,
17687 EndLoc, SanitizedPermExprs);
17688}
17689
17691 SourceLocation EndLoc) {
17692 return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc);
17693}
17694
17696 SourceLocation StartLoc,
17697 SourceLocation LParenLoc,
17698 SourceLocation EndLoc) {
17699 if (FactorExpr) {
17700 // If an argument is specified, it must be a constant (or an unevaluated
17701 // template expression).
17703 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
17704 if (FactorResult.isInvalid())
17705 return nullptr;
17706 FactorExpr = FactorResult.get();
17707 }
17708
17709 return OMPPartialClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17710 FactorExpr);
17711}
17712
17714 Expr *First, Expr *Count, SourceLocation StartLoc, SourceLocation LParenLoc,
17715 SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc) {
17716
17717 // OpenMP [6.0, Restrictions]
17718 // First and Count must be integer expressions with positive value
17719 ExprResult FirstVal =
17721 if (FirstVal.isInvalid())
17722 First = nullptr;
17723
17724 ExprResult CountVal =
17725 VerifyPositiveIntegerConstantInClause(Count, OMPC_looprange);
17726 if (CountVal.isInvalid())
17727 Count = nullptr;
17728
17729 // OpenMP [6.0, Restrictions]
17730 // first + count - 1 must not evaluate to a value greater than the
17731 // loop sequence length of the associated canonical loop sequence.
17732 // This check must be performed afterwards due to the delayed
17733 // parsing and computation of the associated loop sequence
17734 return OMPLoopRangeClause::Create(getASTContext(), StartLoc, LParenLoc,
17735 FirstLoc, CountLoc, EndLoc, First, Count);
17736}
17737
17739 SourceLocation LParenLoc,
17740 SourceLocation EndLoc) {
17741 ExprResult AlignVal;
17742 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
17743 if (AlignVal.isInvalid())
17744 return nullptr;
17745 return OMPAlignClause::Create(getASTContext(), AlignVal.get(), StartLoc,
17746 LParenLoc, EndLoc);
17747}
17748
17751 SourceLocation StartLoc, SourceLocation LParenLoc,
17752 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
17753 SourceLocation EndLoc) {
17754 OMPClause *Res = nullptr;
17755 switch (Kind) {
17756 case OMPC_schedule: {
17757 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
17758 assert(Argument.size() == NumberOfElements &&
17759 ArgumentLoc.size() == NumberOfElements);
17761 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
17762 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
17763 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
17764 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
17765 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
17766 break;
17767 }
17768 case OMPC_if:
17769 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17770 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
17771 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
17772 DelimLoc, EndLoc);
17773 break;
17774 case OMPC_dist_schedule:
17776 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
17777 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
17778 break;
17779 case OMPC_default:
17780 enum { DefaultModifier, DefaultVarCategory };
17782 static_cast<llvm::omp::DefaultKind>(Argument[DefaultModifier]),
17783 ArgumentLoc[DefaultModifier],
17785 Argument[DefaultVarCategory]),
17786 ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc);
17787 break;
17788 case OMPC_defaultmap:
17789 enum { Modifier, DefaultmapKind };
17791 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
17792 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
17793 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
17794 EndLoc);
17795 break;
17796 case OMPC_order:
17797 enum { OrderModifier, OrderKind };
17799 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
17800 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
17801 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
17802 break;
17803 case OMPC_device:
17804 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17806 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
17807 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17808 break;
17809 case OMPC_grainsize:
17810 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17811 "Modifier for grainsize clause and its location are expected.");
17813 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
17814 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17815 break;
17816 case OMPC_num_tasks:
17817 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17818 "Modifier for num_tasks clause and its location are expected.");
17820 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
17821 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17822 break;
17823 case OMPC_dyn_groupprivate: {
17824 enum { Modifier1, Modifier2, NumberOfElements };
17825 assert(Argument.size() == NumberOfElements &&
17826 ArgumentLoc.size() == NumberOfElements &&
17827 "Modifiers for dyn_groupprivate clause and their locations are "
17828 "expected.");
17830 static_cast<OpenMPDynGroupprivateClauseModifier>(Argument[Modifier1]),
17832 Argument[Modifier2]),
17833 Expr, StartLoc, LParenLoc, ArgumentLoc[Modifier1],
17834 ArgumentLoc[Modifier2], EndLoc);
17835 break;
17836 }
17837 case OMPC_num_threads:
17838 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17839 "Modifier for num_threads clause and its location are expected.");
17841 static_cast<OpenMPNumThreadsClauseModifier>(Argument.back()), Expr,
17842 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17843 break;
17844 case OMPC_final:
17845 case OMPC_safelen:
17846 case OMPC_simdlen:
17847 case OMPC_sizes:
17848 case OMPC_allocator:
17849 case OMPC_collapse:
17850 case OMPC_proc_bind:
17851 case OMPC_private:
17852 case OMPC_firstprivate:
17853 case OMPC_lastprivate:
17854 case OMPC_shared:
17855 case OMPC_reduction:
17856 case OMPC_task_reduction:
17857 case OMPC_in_reduction:
17858 case OMPC_linear:
17859 case OMPC_aligned:
17860 case OMPC_copyin:
17861 case OMPC_copyprivate:
17862 case OMPC_ordered:
17863 case OMPC_nowait:
17864 case OMPC_untied:
17865 case OMPC_mergeable:
17866 case OMPC_threadprivate:
17867 case OMPC_groupprivate:
17868 case OMPC_allocate:
17869 case OMPC_flush:
17870 case OMPC_depobj:
17871 case OMPC_read:
17872 case OMPC_write:
17873 case OMPC_update:
17874 case OMPC_capture:
17875 case OMPC_compare:
17876 case OMPC_seq_cst:
17877 case OMPC_acq_rel:
17878 case OMPC_acquire:
17879 case OMPC_release:
17880 case OMPC_relaxed:
17881 case OMPC_depend:
17882 case OMPC_threads:
17883 case OMPC_simd:
17884 case OMPC_map:
17885 case OMPC_num_teams:
17886 case OMPC_thread_limit:
17887 case OMPC_priority:
17888 case OMPC_nogroup:
17889 case OMPC_hint:
17890 case OMPC_unknown:
17891 case OMPC_uniform:
17892 case OMPC_to:
17893 case OMPC_from:
17894 case OMPC_use_device_ptr:
17895 case OMPC_use_device_addr:
17896 case OMPC_is_device_ptr:
17897 case OMPC_has_device_addr:
17898 case OMPC_unified_address:
17899 case OMPC_unified_shared_memory:
17900 case OMPC_reverse_offload:
17901 case OMPC_dynamic_allocators:
17902 case OMPC_atomic_default_mem_order:
17903 case OMPC_self_maps:
17904 case OMPC_device_type:
17905 case OMPC_match:
17906 case OMPC_nontemporal:
17907 case OMPC_at:
17908 case OMPC_severity:
17909 case OMPC_message:
17910 case OMPC_destroy:
17911 case OMPC_novariants:
17912 case OMPC_nocontext:
17913 case OMPC_detach:
17914 case OMPC_inclusive:
17915 case OMPC_exclusive:
17916 case OMPC_uses_allocators:
17917 case OMPC_affinity:
17918 case OMPC_when:
17919 case OMPC_bind:
17920 default:
17921 llvm_unreachable("Clause is not allowed.");
17922 }
17923 return Res;
17924}
17925
17928 SourceLocation M1Loc, SourceLocation M2Loc) {
17929 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
17930 SmallVector<unsigned, 2> Excluded;
17932 Excluded.push_back(M2);
17933 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
17934 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
17935 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
17936 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
17937 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
17938 << getListOfPossibleValues(OMPC_schedule,
17939 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
17941 Excluded)
17942 << getOpenMPClauseNameForDiag(OMPC_schedule);
17943 return true;
17944 }
17945 return false;
17946}
17947
17950 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
17951 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
17952 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
17953 if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) ||
17954 checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc))
17955 return nullptr;
17956 // OpenMP, 2.7.1, Loop Construct, Restrictions
17957 // Either the monotonic modifier or the nonmonotonic modifier can be specified
17958 // but not both.
17959 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
17960 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
17961 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
17962 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
17963 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
17964 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
17965 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
17966 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
17967 return nullptr;
17968 }
17969 if (Kind == OMPC_SCHEDULE_unknown) {
17970 std::string Values;
17971 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
17972 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
17973 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17975 Exclude);
17976 } else {
17977 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17978 /*Last=*/OMPC_SCHEDULE_unknown);
17979 }
17980 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17981 << Values << getOpenMPClauseNameForDiag(OMPC_schedule);
17982 return nullptr;
17983 }
17984 // OpenMP, 2.7.1, Loop Construct, Restrictions
17985 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
17986 // schedule(guided).
17987 // OpenMP 5.0 does not have this restriction.
17988 if (getLangOpts().OpenMP < 50 &&
17989 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
17990 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
17991 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
17992 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
17993 diag::err_omp_schedule_nonmonotonic_static);
17994 return nullptr;
17995 }
17996 Expr *ValExpr = ChunkSize;
17997 Stmt *HelperValStmt = nullptr;
17998 if (ChunkSize) {
17999 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
18000 !ChunkSize->isInstantiationDependent() &&
18001 !ChunkSize->containsUnexpandedParameterPack()) {
18002 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
18003 ExprResult Val =
18004 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
18005 if (Val.isInvalid())
18006 return nullptr;
18007
18008 ValExpr = Val.get();
18009
18010 // OpenMP [2.7.1, Restrictions]
18011 // chunk_size must be a loop invariant integer expression with a positive
18012 // value.
18013 if (std::optional<llvm::APSInt> Result =
18015 if (Result->isSigned() && !Result->isStrictlyPositive()) {
18016 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
18017 << "schedule" << 1 << ChunkSize->getSourceRange();
18018 return nullptr;
18019 }
18021 DSAStack->getCurrentDirective(), OMPC_schedule,
18022 getLangOpts().OpenMP) != OMPD_unknown &&
18023 !SemaRef.CurContext->isDependentContext()) {
18024 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18025 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18026 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18027 HelperValStmt = buildPreInits(getASTContext(), Captures);
18028 }
18029 }
18030 }
18031
18032 return new (getASTContext())
18033 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
18034 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
18035}
18036
18038 SourceLocation StartLoc,
18039 SourceLocation EndLoc) {
18040 OMPClause *Res = nullptr;
18041 switch (Kind) {
18042 case OMPC_ordered:
18043 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
18044 break;
18045 case OMPC_nowait:
18046 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc,
18047 /*LParenLoc=*/SourceLocation(),
18048 /*Condition=*/nullptr);
18049 break;
18050 case OMPC_untied:
18051 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
18052 break;
18053 case OMPC_mergeable:
18054 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
18055 break;
18056 case OMPC_read:
18057 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
18058 break;
18059 case OMPC_write:
18060 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
18061 break;
18062 case OMPC_update:
18063 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
18064 break;
18065 case OMPC_capture:
18066 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
18067 break;
18068 case OMPC_compare:
18069 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
18070 break;
18071 case OMPC_fail:
18072 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
18073 break;
18074 case OMPC_seq_cst:
18075 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
18076 break;
18077 case OMPC_acq_rel:
18078 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
18079 break;
18080 case OMPC_acquire:
18081 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
18082 break;
18083 case OMPC_release:
18084 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
18085 break;
18086 case OMPC_relaxed:
18087 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
18088 break;
18089 case OMPC_weak:
18090 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
18091 break;
18092 case OMPC_threads:
18093 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
18094 break;
18095 case OMPC_simd:
18096 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
18097 break;
18098 case OMPC_nogroup:
18099 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
18100 break;
18101 case OMPC_unified_address:
18102 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
18103 break;
18104 case OMPC_unified_shared_memory:
18105 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
18106 break;
18107 case OMPC_reverse_offload:
18108 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
18109 break;
18110 case OMPC_dynamic_allocators:
18111 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
18112 break;
18113 case OMPC_self_maps:
18114 Res = ActOnOpenMPSelfMapsClause(StartLoc, EndLoc);
18115 break;
18116 case OMPC_destroy:
18117 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
18118 /*LParenLoc=*/SourceLocation(),
18119 /*VarLoc=*/SourceLocation(), EndLoc);
18120 break;
18121 case OMPC_full:
18122 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
18123 break;
18124 case OMPC_partial:
18125 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
18126 break;
18127 case OMPC_ompx_bare:
18128 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
18129 break;
18130 case OMPC_if:
18131 case OMPC_final:
18132 case OMPC_num_threads:
18133 case OMPC_safelen:
18134 case OMPC_simdlen:
18135 case OMPC_sizes:
18136 case OMPC_allocator:
18137 case OMPC_collapse:
18138 case OMPC_schedule:
18139 case OMPC_private:
18140 case OMPC_firstprivate:
18141 case OMPC_lastprivate:
18142 case OMPC_shared:
18143 case OMPC_reduction:
18144 case OMPC_task_reduction:
18145 case OMPC_in_reduction:
18146 case OMPC_linear:
18147 case OMPC_aligned:
18148 case OMPC_copyin:
18149 case OMPC_copyprivate:
18150 case OMPC_default:
18151 case OMPC_proc_bind:
18152 case OMPC_threadprivate:
18153 case OMPC_groupprivate:
18154 case OMPC_allocate:
18155 case OMPC_flush:
18156 case OMPC_depobj:
18157 case OMPC_depend:
18158 case OMPC_device:
18159 case OMPC_map:
18160 case OMPC_num_teams:
18161 case OMPC_thread_limit:
18162 case OMPC_priority:
18163 case OMPC_grainsize:
18164 case OMPC_num_tasks:
18165 case OMPC_hint:
18166 case OMPC_dist_schedule:
18167 case OMPC_defaultmap:
18168 case OMPC_unknown:
18169 case OMPC_uniform:
18170 case OMPC_to:
18171 case OMPC_from:
18172 case OMPC_use_device_ptr:
18173 case OMPC_use_device_addr:
18174 case OMPC_is_device_ptr:
18175 case OMPC_has_device_addr:
18176 case OMPC_atomic_default_mem_order:
18177 case OMPC_device_type:
18178 case OMPC_match:
18179 case OMPC_nontemporal:
18180 case OMPC_order:
18181 case OMPC_at:
18182 case OMPC_severity:
18183 case OMPC_message:
18184 case OMPC_novariants:
18185 case OMPC_nocontext:
18186 case OMPC_detach:
18187 case OMPC_inclusive:
18188 case OMPC_exclusive:
18189 case OMPC_uses_allocators:
18190 case OMPC_affinity:
18191 case OMPC_when:
18192 case OMPC_ompx_dyn_cgroup_mem:
18193 case OMPC_dyn_groupprivate:
18194 default:
18195 llvm_unreachable("Clause is not allowed.");
18196 }
18197 return Res;
18198}
18199
18201 SourceLocation EndLoc,
18202 SourceLocation LParenLoc,
18203 Expr *Condition) {
18204 Expr *ValExpr = Condition;
18205 if (Condition && LParenLoc.isValid()) {
18206 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18207 !Condition->isInstantiationDependent() &&
18208 !Condition->containsUnexpandedParameterPack()) {
18209 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
18210 if (Val.isInvalid())
18211 return nullptr;
18212
18213 ValExpr = Val.get();
18214 }
18215 }
18216 DSAStack->setNowaitRegion();
18217 return new (getASTContext())
18218 OMPNowaitClause(ValExpr, StartLoc, LParenLoc, EndLoc);
18219}
18220
18222 SourceLocation EndLoc) {
18223 DSAStack->setUntiedRegion();
18224 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
18225}
18226
18228 SourceLocation EndLoc) {
18229 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
18230}
18231
18233 SourceLocation EndLoc) {
18234 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
18235}
18236
18238 SourceLocation EndLoc) {
18239 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
18240}
18241
18243 SourceLocation EndLoc) {
18244 return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc);
18245}
18246
18248 SourceLocation EndLoc) {
18249 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
18250}
18251
18253 SourceLocation EndLoc) {
18254 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
18255}
18256
18258 SourceLocation EndLoc) {
18259 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
18260}
18261
18263 SourceLocation KindLoc,
18264 SourceLocation StartLoc,
18265 SourceLocation LParenLoc,
18266 SourceLocation EndLoc) {
18267
18269 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
18270 return nullptr;
18271 }
18272 return new (getASTContext())
18273 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
18274}
18275
18277 SourceLocation EndLoc) {
18278 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
18279}
18280
18282 SourceLocation EndLoc) {
18283 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
18284}
18285
18287 SourceLocation EndLoc) {
18288 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
18289}
18290
18292 SourceLocation EndLoc) {
18293 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
18294}
18295
18297 SourceLocation EndLoc) {
18298 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
18299}
18300
18302 SourceLocation EndLoc) {
18303 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
18304}
18305
18307 SourceLocation EndLoc) {
18308 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
18309}
18310
18312 SourceLocation EndLoc) {
18313 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
18314}
18315
18317 SourceLocation EndLoc) {
18318 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
18319}
18320
18322 SourceLocation EndLoc) {
18323 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
18324}
18325
18326OMPClause *
18331
18333 SourceLocation EndLoc) {
18334 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
18335}
18336
18337OMPClause *
18339 SourceLocation EndLoc) {
18340 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
18341}
18342
18344 SourceLocation EndLoc) {
18345 return new (getASTContext()) OMPSelfMapsClause(StartLoc, EndLoc);
18346}
18347
18350 SourceLocation StartLoc,
18351 SourceLocation EndLoc) {
18352
18353 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18354 // At least one action-clause must appear on a directive.
18355 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
18356 unsigned OMPVersion = getLangOpts().OpenMP;
18357 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
18358 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
18359 << Expected << getOpenMPDirectiveName(OMPD_interop, OMPVersion);
18360 return StmtError();
18361 }
18362
18363 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18364 // A depend clause can only appear on the directive if a targetsync
18365 // interop-type is present or the interop-var was initialized with
18366 // the targetsync interop-type.
18367
18368 // If there is any 'init' clause diagnose if there is no 'init' clause with
18369 // interop-type of 'targetsync'. Cases involving other directives cannot be
18370 // diagnosed.
18371 const OMPDependClause *DependClause = nullptr;
18372 bool HasInitClause = false;
18373 bool IsTargetSync = false;
18374 for (const OMPClause *C : Clauses) {
18375 if (IsTargetSync)
18376 break;
18377 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
18378 HasInitClause = true;
18379 if (InitClause->getIsTargetSync())
18380 IsTargetSync = true;
18381 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
18382 DependClause = DC;
18383 }
18384 }
18385 if (DependClause && HasInitClause && !IsTargetSync) {
18386 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
18387 return StmtError();
18388 }
18389
18390 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18391 // Each interop-var may be specified for at most one action-clause of each
18392 // interop construct.
18394 for (OMPClause *C : Clauses) {
18395 OpenMPClauseKind ClauseKind = C->getClauseKind();
18396 std::pair<ValueDecl *, bool> DeclResult;
18397 SourceLocation ELoc;
18398 SourceRange ERange;
18399
18400 if (ClauseKind == OMPC_init) {
18401 auto *E = cast<OMPInitClause>(C)->getInteropVar();
18402 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18403 } else if (ClauseKind == OMPC_use) {
18404 auto *E = cast<OMPUseClause>(C)->getInteropVar();
18405 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18406 } else if (ClauseKind == OMPC_destroy) {
18407 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
18408 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18409 }
18410
18411 if (DeclResult.first) {
18412 if (!InteropVars.insert(DeclResult.first).second) {
18413 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
18414 << DeclResult.first;
18415 return StmtError();
18416 }
18417 }
18418 }
18419
18420 return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc,
18421 Clauses);
18422}
18423
18424static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
18425 SourceLocation VarLoc,
18426 OpenMPClauseKind Kind) {
18427 SourceLocation ELoc;
18428 SourceRange ERange;
18429 Expr *RefExpr = InteropVarExpr;
18430 auto Res = getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
18431 /*AllowArraySection=*/false,
18432 /*AllowAssumedSizeArray=*/false,
18433 /*DiagType=*/"omp_interop_t");
18434
18435 if (Res.second) {
18436 // It will be analyzed later.
18437 return true;
18438 }
18439
18440 if (!Res.first)
18441 return false;
18442
18443 // Interop variable should be of type omp_interop_t.
18444 bool HasError = false;
18445 QualType InteropType;
18446 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
18447 VarLoc, Sema::LookupOrdinaryName);
18448 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
18449 NamedDecl *ND = Result.getFoundDecl();
18450 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
18451 InteropType = QualType(TD->getTypeForDecl(), 0);
18452 } else {
18453 HasError = true;
18454 }
18455 } else {
18456 HasError = true;
18457 }
18458
18459 if (HasError) {
18460 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
18461 << "omp_interop_t";
18462 return false;
18463 }
18464
18465 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
18466 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
18467 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
18468 return false;
18469 }
18470
18471 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18472 // The interop-var passed to init or destroy must be non-const.
18473 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
18474 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
18475 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
18476 << /*non-const*/ 1;
18477 return false;
18478 }
18479 return true;
18480}
18481
18483 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
18484 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
18485
18486 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init))
18487 return nullptr;
18488
18489 // Check prefer_type values. These foreign-runtime-id values are either
18490 // string literals or constant integral expressions.
18491 for (const Expr *E : InteropInfo.PreferTypes) {
18492 if (E->isValueDependent() || E->isTypeDependent() ||
18494 continue;
18496 continue;
18497 if (isa<StringLiteral>(E))
18498 continue;
18499 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
18500 return nullptr;
18501 }
18502
18503 return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo,
18504 StartLoc, LParenLoc, VarLoc, EndLoc);
18505}
18506
18508 SourceLocation StartLoc,
18509 SourceLocation LParenLoc,
18510 SourceLocation VarLoc,
18511 SourceLocation EndLoc) {
18512
18513 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use))
18514 return nullptr;
18515
18516 return new (getASTContext())
18517 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18518}
18519
18521 SourceLocation StartLoc,
18522 SourceLocation LParenLoc,
18523 SourceLocation VarLoc,
18524 SourceLocation EndLoc) {
18525 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
18526 DSAStack->getCurrentDirective() == OMPD_depobj) {
18527 unsigned OMPVersion = getLangOpts().OpenMP;
18528 Diag(StartLoc, diag::err_omp_expected_clause_argument)
18529 << getOpenMPClauseNameForDiag(OMPC_destroy)
18530 << getOpenMPDirectiveName(OMPD_depobj, OMPVersion);
18531 return nullptr;
18532 }
18533 if (InteropVar &&
18534 !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy))
18535 return nullptr;
18536
18537 return new (getASTContext())
18538 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18539}
18540
18542 SourceLocation StartLoc,
18543 SourceLocation LParenLoc,
18544 SourceLocation EndLoc) {
18545 Expr *ValExpr = Condition;
18546 Stmt *HelperValStmt = nullptr;
18547 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18548 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18549 !Condition->isInstantiationDependent() &&
18550 !Condition->containsUnexpandedParameterPack()) {
18551 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
18552 if (Val.isInvalid())
18553 return nullptr;
18554
18555 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
18556
18557 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18558 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
18559 getLangOpts().OpenMP);
18560 if (CaptureRegion != OMPD_unknown &&
18561 !SemaRef.CurContext->isDependentContext()) {
18562 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18563 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18564 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18565 HelperValStmt = buildPreInits(getASTContext(), Captures);
18566 }
18567 }
18568
18569 return new (getASTContext()) OMPNovariantsClause(
18570 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18571}
18572
18574 SourceLocation StartLoc,
18575 SourceLocation LParenLoc,
18576 SourceLocation EndLoc) {
18577 Expr *ValExpr = Condition;
18578 Stmt *HelperValStmt = nullptr;
18579 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18580 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18581 !Condition->isInstantiationDependent() &&
18582 !Condition->containsUnexpandedParameterPack()) {
18583 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
18584 if (Val.isInvalid())
18585 return nullptr;
18586
18587 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
18588
18589 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18590 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext,
18591 getLangOpts().OpenMP);
18592 if (CaptureRegion != OMPD_unknown &&
18593 !SemaRef.CurContext->isDependentContext()) {
18594 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18595 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18596 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18597 HelperValStmt = buildPreInits(getASTContext(), Captures);
18598 }
18599 }
18600
18601 return new (getASTContext()) OMPNocontextClause(
18602 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18603}
18604
18606 SourceLocation StartLoc,
18607 SourceLocation LParenLoc,
18608 SourceLocation EndLoc) {
18609 Expr *ValExpr = ThreadID;
18610 Stmt *HelperValStmt = nullptr;
18611
18612 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18613 OpenMPDirectiveKind CaptureRegion =
18614 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP);
18615 if (CaptureRegion != OMPD_unknown &&
18616 !SemaRef.CurContext->isDependentContext()) {
18617 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18618 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18619 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18620 HelperValStmt = buildPreInits(getASTContext(), Captures);
18621 }
18622
18623 return new (getASTContext()) OMPFilterClause(
18624 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18625}
18626
18628 ArrayRef<Expr *> VarList,
18629 const OMPVarListLocTy &Locs,
18631 SourceLocation StartLoc = Locs.StartLoc;
18632 SourceLocation LParenLoc = Locs.LParenLoc;
18633 SourceLocation EndLoc = Locs.EndLoc;
18634 OMPClause *Res = nullptr;
18635 int ExtraModifier = Data.ExtraModifier;
18636 int OriginalSharingModifier = Data.OriginalSharingModifier;
18637 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
18638 SourceLocation ColonLoc = Data.ColonLoc;
18639 switch (Kind) {
18640 case OMPC_private:
18641 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18642 break;
18643 case OMPC_firstprivate:
18644 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18645 break;
18646 case OMPC_lastprivate:
18647 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
18648 "Unexpected lastprivate modifier.");
18650 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
18651 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
18652 break;
18653 case OMPC_shared:
18654 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
18655 break;
18656 case OMPC_reduction:
18657 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
18658 "Unexpected lastprivate modifier.");
18660 VarList,
18662 ExtraModifier, OriginalSharingModifier),
18663 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
18664 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18665 break;
18666 case OMPC_task_reduction:
18668 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18669 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18670 break;
18671 case OMPC_in_reduction:
18673 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18674 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18675 break;
18676 case OMPC_linear:
18677 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
18678 "Unexpected linear modifier.");
18680 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
18681 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
18682 ColonLoc, Data.StepModifierLoc, EndLoc);
18683 break;
18684 case OMPC_aligned:
18685 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
18686 LParenLoc, ColonLoc, EndLoc);
18687 break;
18688 case OMPC_copyin:
18689 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
18690 break;
18691 case OMPC_copyprivate:
18692 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18693 break;
18694 case OMPC_flush:
18695 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
18696 break;
18697 case OMPC_depend:
18698 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
18699 "Unexpected depend modifier.");
18701 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
18702 ColonLoc, Data.OmpAllMemoryLoc},
18703 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
18704 break;
18705 case OMPC_map:
18706 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
18707 "Unexpected map modifier.");
18709 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
18710 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
18711 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
18712 ExtraModifierLoc, ColonLoc, VarList, Locs);
18713 break;
18714 case OMPC_to:
18715 Res = ActOnOpenMPToClause(
18716 Data.MotionModifiers, Data.MotionModifiersLoc, Data.IteratorExpr,
18717 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, ColonLoc,
18718 VarList, Locs);
18719 break;
18720 case OMPC_from:
18722 Data.MotionModifiers, Data.MotionModifiersLoc, Data.IteratorExpr,
18723 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, ColonLoc,
18724 VarList, Locs);
18725 break;
18726 case OMPC_use_device_ptr:
18727 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
18728 break;
18729 case OMPC_use_device_addr:
18730 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
18731 break;
18732 case OMPC_is_device_ptr:
18733 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
18734 break;
18735 case OMPC_has_device_addr:
18736 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
18737 break;
18738 case OMPC_allocate: {
18741 SourceLocation Modifier1Loc, Modifier2Loc;
18742 if (!Data.AllocClauseModifiers.empty()) {
18743 assert(Data.AllocClauseModifiers.size() <= 2 &&
18744 "More allocate modifiers than expected");
18745 Modifier1 = Data.AllocClauseModifiers[0];
18746 Modifier1Loc = Data.AllocClauseModifiersLoc[0];
18747 if (Data.AllocClauseModifiers.size() == 2) {
18748 Modifier2 = Data.AllocClauseModifiers[1];
18749 Modifier2Loc = Data.AllocClauseModifiersLoc[1];
18750 }
18751 }
18753 Data.DepModOrTailExpr, Data.AllocateAlignment, Modifier1, Modifier1Loc,
18754 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
18755 EndLoc);
18756 break;
18757 }
18758 case OMPC_nontemporal:
18759 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
18760 break;
18761 case OMPC_inclusive:
18762 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18763 break;
18764 case OMPC_exclusive:
18765 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18766 break;
18767 case OMPC_affinity:
18768 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
18769 Data.DepModOrTailExpr, VarList);
18770 break;
18771 case OMPC_doacross:
18773 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
18774 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
18775 break;
18776 case OMPC_num_teams:
18777 Res = ActOnOpenMPNumTeamsClause(VarList, StartLoc, LParenLoc, EndLoc);
18778 break;
18779 case OMPC_thread_limit:
18780 Res = ActOnOpenMPThreadLimitClause(VarList, StartLoc, LParenLoc, EndLoc);
18781 break;
18782 case OMPC_if:
18783 case OMPC_depobj:
18784 case OMPC_final:
18785 case OMPC_num_threads:
18786 case OMPC_safelen:
18787 case OMPC_simdlen:
18788 case OMPC_sizes:
18789 case OMPC_allocator:
18790 case OMPC_collapse:
18791 case OMPC_default:
18792 case OMPC_proc_bind:
18793 case OMPC_schedule:
18794 case OMPC_ordered:
18795 case OMPC_nowait:
18796 case OMPC_untied:
18797 case OMPC_mergeable:
18798 case OMPC_threadprivate:
18799 case OMPC_groupprivate:
18800 case OMPC_read:
18801 case OMPC_write:
18802 case OMPC_update:
18803 case OMPC_capture:
18804 case OMPC_compare:
18805 case OMPC_seq_cst:
18806 case OMPC_acq_rel:
18807 case OMPC_acquire:
18808 case OMPC_release:
18809 case OMPC_relaxed:
18810 case OMPC_device:
18811 case OMPC_threads:
18812 case OMPC_simd:
18813 case OMPC_priority:
18814 case OMPC_grainsize:
18815 case OMPC_nogroup:
18816 case OMPC_num_tasks:
18817 case OMPC_hint:
18818 case OMPC_dist_schedule:
18819 case OMPC_defaultmap:
18820 case OMPC_unknown:
18821 case OMPC_uniform:
18822 case OMPC_unified_address:
18823 case OMPC_unified_shared_memory:
18824 case OMPC_reverse_offload:
18825 case OMPC_dynamic_allocators:
18826 case OMPC_atomic_default_mem_order:
18827 case OMPC_self_maps:
18828 case OMPC_device_type:
18829 case OMPC_match:
18830 case OMPC_order:
18831 case OMPC_at:
18832 case OMPC_severity:
18833 case OMPC_message:
18834 case OMPC_destroy:
18835 case OMPC_novariants:
18836 case OMPC_nocontext:
18837 case OMPC_detach:
18838 case OMPC_uses_allocators:
18839 case OMPC_when:
18840 case OMPC_bind:
18841 default:
18842 llvm_unreachable("Clause is not allowed.");
18843 }
18844 return Res;
18845}
18846
18848 ExprObjectKind OK,
18849 SourceLocation Loc) {
18850 ExprResult Res = SemaRef.BuildDeclRefExpr(
18851 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
18852 if (!Res.isUsable())
18853 return ExprError();
18854 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
18855 Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
18856 if (!Res.isUsable())
18857 return ExprError();
18858 }
18859 if (VK != VK_LValue && Res.get()->isGLValue()) {
18860 Res = SemaRef.DefaultLvalueConversion(Res.get());
18861 if (!Res.isUsable())
18862 return ExprError();
18863 }
18864 return Res;
18865}
18866
18868 SourceLocation StartLoc,
18869 SourceLocation LParenLoc,
18870 SourceLocation EndLoc) {
18872 SmallVector<Expr *, 8> PrivateCopies;
18873 unsigned OMPVersion = getLangOpts().OpenMP;
18874 bool IsImplicitClause =
18875 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18876 for (Expr *RefExpr : VarList) {
18877 assert(RefExpr && "NULL expr in OpenMP private clause.");
18878 SourceLocation ELoc;
18879 SourceRange ERange;
18880 Expr *SimpleRefExpr = RefExpr;
18881 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
18882 if (Res.second) {
18883 // It will be analyzed later.
18884 Vars.push_back(RefExpr);
18885 PrivateCopies.push_back(nullptr);
18886 }
18887 ValueDecl *D = Res.first;
18888 if (!D)
18889 continue;
18890
18891 QualType Type = D->getType();
18892 auto *VD = dyn_cast<VarDecl>(D);
18893
18894 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18895 // A variable that appears in a private clause must not have an incomplete
18896 // type or a reference type.
18897 if (SemaRef.RequireCompleteType(ELoc, Type,
18898 diag::err_omp_private_incomplete_type))
18899 continue;
18900 Type = Type.getNonReferenceType();
18901
18902 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18903 // A variable that is privatized must not have a const-qualified type
18904 // unless it is of class type with a mutable member. This restriction does
18905 // not apply to the firstprivate clause.
18906 //
18907 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
18908 // A variable that appears in a private clause must not have a
18909 // const-qualified type unless it is of class type with a mutable member.
18910 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc))
18911 continue;
18912
18913 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18914 // in a Construct]
18915 // Variables with the predetermined data-sharing attributes may not be
18916 // listed in data-sharing attributes clauses, except for the cases
18917 // listed below. For these exceptions only, listing a predetermined
18918 // variable in a data-sharing attribute clause is allowed and overrides
18919 // the variable's predetermined data-sharing attributes.
18920 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18921 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
18922 Diag(ELoc, diag::err_omp_wrong_dsa)
18923 << getOpenMPClauseNameForDiag(DVar.CKind)
18924 << getOpenMPClauseNameForDiag(OMPC_private);
18926 continue;
18927 }
18928
18929 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18930 // Variably modified types are not supported for tasks.
18932 isOpenMPTaskingDirective(CurrDir)) {
18933 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18934 << getOpenMPClauseNameForDiag(OMPC_private) << Type
18935 << getOpenMPDirectiveName(CurrDir, OMPVersion);
18936 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
18938 Diag(D->getLocation(),
18939 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18940 << D;
18941 continue;
18942 }
18943
18944 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18945 // A list item cannot appear in both a map clause and a data-sharing
18946 // attribute clause on the same construct
18947 //
18948 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18949 // A list item cannot appear in both a map clause and a data-sharing
18950 // attribute clause on the same construct unless the construct is a
18951 // combined construct.
18952 if ((getLangOpts().OpenMP <= 45 &&
18954 CurrDir == OMPD_target) {
18955 OpenMPClauseKind ConflictKind;
18956 if (DSAStack->checkMappableExprComponentListsForDecl(
18957 VD, /*CurrentRegionOnly=*/true,
18959 OpenMPClauseKind WhereFoundClauseKind) -> bool {
18960 ConflictKind = WhereFoundClauseKind;
18961 return true;
18962 })) {
18963 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18964 << getOpenMPClauseNameForDiag(OMPC_private)
18965 << getOpenMPClauseNameForDiag(ConflictKind)
18966 << getOpenMPDirectiveName(CurrDir, OMPVersion);
18968 continue;
18969 }
18970 }
18971
18972 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
18973 // A variable of class type (or array thereof) that appears in a private
18974 // clause requires an accessible, unambiguous default constructor for the
18975 // class type.
18976 // Generate helper private variable and initialize it with the default
18977 // value. The address of the original variable is replaced by the address of
18978 // the new private variable in CodeGen. This new variable is not added to
18979 // IdResolver, so the code in the OpenMP region uses original variable for
18980 // proper diagnostics.
18981 Type = Type.getUnqualifiedType();
18982 VarDecl *VDPrivate =
18983 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
18984 D->hasAttrs() ? &D->getAttrs() : nullptr,
18985 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18986 SemaRef.ActOnUninitializedDecl(VDPrivate);
18987 if (VDPrivate->isInvalidDecl())
18988 continue;
18989 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18990 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
18991
18992 DeclRefExpr *Ref = nullptr;
18993 if (!VD && !SemaRef.CurContext->isDependentContext()) {
18994 auto *FD = dyn_cast<FieldDecl>(D);
18995 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18996 if (VD)
18998 RefExpr->getExprLoc());
18999 else
19000 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19001 }
19002 if (!IsImplicitClause)
19003 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
19004 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19005 ? RefExpr->IgnoreParens()
19006 : Ref);
19007 PrivateCopies.push_back(VDPrivateRefExpr);
19008 }
19009
19010 if (Vars.empty())
19011 return nullptr;
19012
19013 return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19014 Vars, PrivateCopies);
19015}
19016
19018 SourceLocation StartLoc,
19019 SourceLocation LParenLoc,
19020 SourceLocation EndLoc) {
19022 SmallVector<Expr *, 8> PrivateCopies;
19024 SmallVector<Decl *, 4> ExprCaptures;
19025 bool IsImplicitClause =
19026 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
19027 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
19028 unsigned OMPVersion = getLangOpts().OpenMP;
19029
19030 for (Expr *RefExpr : VarList) {
19031 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
19032 SourceLocation ELoc;
19033 SourceRange ERange;
19034 Expr *SimpleRefExpr = RefExpr;
19035 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19036 if (Res.second) {
19037 // It will be analyzed later.
19038 Vars.push_back(RefExpr);
19039 PrivateCopies.push_back(nullptr);
19040 Inits.push_back(nullptr);
19041 }
19042 ValueDecl *D = Res.first;
19043 if (!D)
19044 continue;
19045
19046 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
19047 QualType Type = D->getType();
19048 auto *VD = dyn_cast<VarDecl>(D);
19049
19050 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19051 // A variable that appears in a private clause must not have an incomplete
19052 // type or a reference type.
19053 if (SemaRef.RequireCompleteType(ELoc, Type,
19054 diag::err_omp_firstprivate_incomplete_type))
19055 continue;
19056 Type = Type.getNonReferenceType();
19057
19058 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
19059 // A variable of class type (or array thereof) that appears in a private
19060 // clause requires an accessible, unambiguous copy constructor for the
19061 // class type.
19062 QualType ElemType =
19064
19065 // If an implicit firstprivate variable found it was checked already.
19066 DSAStackTy::DSAVarData TopDVar;
19067 if (!IsImplicitClause) {
19068 DSAStackTy::DSAVarData DVar =
19069 DSAStack->getTopDSA(D, /*FromParent=*/false);
19070 TopDVar = DVar;
19071 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19072 bool IsConstant = ElemType.isConstant(getASTContext());
19073 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
19074 // A list item that specifies a given variable may not appear in more
19075 // than one clause on the same directive, except that a variable may be
19076 // specified in both firstprivate and lastprivate clauses.
19077 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
19078 // A list item may appear in a firstprivate or lastprivate clause but not
19079 // both.
19080 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
19081 (isOpenMPDistributeDirective(CurrDir) ||
19082 DVar.CKind != OMPC_lastprivate) &&
19083 DVar.RefExpr) {
19084 Diag(ELoc, diag::err_omp_wrong_dsa)
19085 << getOpenMPClauseNameForDiag(DVar.CKind)
19086 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
19088 continue;
19089 }
19090
19091 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19092 // in a Construct]
19093 // Variables with the predetermined data-sharing attributes may not be
19094 // listed in data-sharing attributes clauses, except for the cases
19095 // listed below. For these exceptions only, listing a predetermined
19096 // variable in a data-sharing attribute clause is allowed and overrides
19097 // the variable's predetermined data-sharing attributes.
19098 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19099 // in a Construct, C/C++, p.2]
19100 // Variables with const-qualified type having no mutable member may be
19101 // listed in a firstprivate clause, even if they are static data members.
19102 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
19103 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
19104 Diag(ELoc, diag::err_omp_wrong_dsa)
19105 << getOpenMPClauseNameForDiag(DVar.CKind)
19106 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
19108 continue;
19109 }
19110
19111 // OpenMP [2.9.3.4, Restrictions, p.2]
19112 // A list item that is private within a parallel region must not appear
19113 // in a firstprivate clause on a worksharing construct if any of the
19114 // worksharing regions arising from the worksharing construct ever bind
19115 // to any of the parallel regions arising from the parallel construct.
19116 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
19117 // A list item that is private within a teams region must not appear in a
19118 // firstprivate clause on a distribute construct if any of the distribute
19119 // regions arising from the distribute construct ever bind to any of the
19120 // teams regions arising from the teams construct.
19121 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
19122 // A list item that appears in a reduction clause of a teams construct
19123 // must not appear in a firstprivate clause on a distribute construct if
19124 // any of the distribute regions arising from the distribute construct
19125 // ever bind to any of the teams regions arising from the teams construct.
19126 if ((isOpenMPWorksharingDirective(CurrDir) ||
19127 isOpenMPDistributeDirective(CurrDir)) &&
19128 !isOpenMPParallelDirective(CurrDir) &&
19129 !isOpenMPTeamsDirective(CurrDir)) {
19130 DVar = DSAStack->getImplicitDSA(D, true);
19131 if (DVar.CKind != OMPC_shared &&
19132 (isOpenMPParallelDirective(DVar.DKind) ||
19133 isOpenMPTeamsDirective(DVar.DKind) ||
19134 DVar.DKind == OMPD_unknown)) {
19135 Diag(ELoc, diag::err_omp_required_access)
19136 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
19137 << getOpenMPClauseNameForDiag(OMPC_shared);
19139 continue;
19140 }
19141 }
19142 // OpenMP [2.9.3.4, Restrictions, p.3]
19143 // A list item that appears in a reduction clause of a parallel construct
19144 // must not appear in a firstprivate clause on a worksharing or task
19145 // construct if any of the worksharing or task regions arising from the
19146 // worksharing or task construct ever bind to any of the parallel regions
19147 // arising from the parallel construct.
19148 // OpenMP [2.9.3.4, Restrictions, p.4]
19149 // A list item that appears in a reduction clause in worksharing
19150 // construct must not appear in a firstprivate clause in a task construct
19151 // encountered during execution of any of the worksharing regions arising
19152 // from the worksharing construct.
19153 if (isOpenMPTaskingDirective(CurrDir)) {
19154 DVar = DSAStack->hasInnermostDSA(
19155 D,
19156 [](OpenMPClauseKind C, bool AppliedToPointee) {
19157 return C == OMPC_reduction && !AppliedToPointee;
19158 },
19159 [](OpenMPDirectiveKind K) {
19160 return isOpenMPParallelDirective(K) ||
19163 },
19164 /*FromParent=*/true);
19165 if (DVar.CKind == OMPC_reduction &&
19166 (isOpenMPParallelDirective(DVar.DKind) ||
19167 isOpenMPWorksharingDirective(DVar.DKind) ||
19168 isOpenMPTeamsDirective(DVar.DKind))) {
19169 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
19170 << getOpenMPDirectiveName(DVar.DKind, OMPVersion);
19172 continue;
19173 }
19174 }
19175
19176 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
19177 // A list item cannot appear in both a map clause and a data-sharing
19178 // attribute clause on the same construct
19179 //
19180 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
19181 // A list item cannot appear in both a map clause and a data-sharing
19182 // attribute clause on the same construct unless the construct is a
19183 // combined construct.
19184 if ((getLangOpts().OpenMP <= 45 &&
19186 CurrDir == OMPD_target) {
19187 OpenMPClauseKind ConflictKind;
19188 if (DSAStack->checkMappableExprComponentListsForDecl(
19189 VD, /*CurrentRegionOnly=*/true,
19190 [&ConflictKind](
19192 OpenMPClauseKind WhereFoundClauseKind) {
19193 ConflictKind = WhereFoundClauseKind;
19194 return true;
19195 })) {
19196 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
19197 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
19198 << getOpenMPClauseNameForDiag(ConflictKind)
19199 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
19200 OMPVersion);
19202 continue;
19203 }
19204 }
19205 }
19206
19207 // Variably modified types are not supported for tasks.
19209 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
19210 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19211 << getOpenMPClauseNameForDiag(OMPC_firstprivate) << Type
19212 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
19213 OMPVersion);
19214 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19216 Diag(D->getLocation(),
19217 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19218 << D;
19219 continue;
19220 }
19221
19222 Type = Type.getUnqualifiedType();
19223 VarDecl *VDPrivate =
19224 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
19225 D->hasAttrs() ? &D->getAttrs() : nullptr,
19226 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19227 // Generate helper private variable and initialize it with the value of the
19228 // original variable. The address of the original variable is replaced by
19229 // the address of the new private variable in the CodeGen. This new variable
19230 // is not added to IdResolver, so the code in the OpenMP region uses
19231 // original variable for proper diagnostics and variable capturing.
19232 Expr *VDInitRefExpr = nullptr;
19233 // For arrays generate initializer for single element and replace it by the
19234 // original array element in CodeGen.
19235 if (Type->isArrayType()) {
19236 VarDecl *VDInit =
19237 buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName());
19238 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc);
19239 Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get();
19240 ElemType = ElemType.getUnqualifiedType();
19241 VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(),
19242 ElemType, ".firstprivate.temp");
19243 InitializedEntity Entity =
19246
19247 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
19248 ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init);
19249 if (Result.isInvalid())
19250 VDPrivate->setInvalidDecl();
19251 else
19252 VDPrivate->setInit(Result.getAs<Expr>());
19253 // Remove temp variable declaration.
19254 getASTContext().Deallocate(VDInitTemp);
19255 } else {
19256 VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type,
19257 ".firstprivate.temp");
19258 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(),
19259 RefExpr->getExprLoc());
19260 SemaRef.AddInitializerToDecl(
19261 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
19262 /*DirectInit=*/false);
19263 }
19264 if (VDPrivate->isInvalidDecl()) {
19265 if (IsImplicitClause) {
19266 Diag(RefExpr->getExprLoc(),
19267 diag::note_omp_task_predetermined_firstprivate_here);
19268 }
19269 continue;
19270 }
19271 SemaRef.CurContext->addDecl(VDPrivate);
19272 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
19273 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(),
19274 RefExpr->getExprLoc());
19275 DeclRefExpr *Ref = nullptr;
19276 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19277 if (TopDVar.CKind == OMPC_lastprivate) {
19278 Ref = TopDVar.PrivateCopy;
19279 } else {
19280 auto *FD = dyn_cast<FieldDecl>(D);
19281 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
19282 if (VD)
19283 Ref =
19285 RefExpr->getExprLoc());
19286 else
19287 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19288 if (VD || !isOpenMPCapturedDecl(D))
19289 ExprCaptures.push_back(Ref->getDecl());
19290 }
19291 }
19292 if (!IsImplicitClause)
19293 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
19294 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19295 ? RefExpr->IgnoreParens()
19296 : Ref);
19297 PrivateCopies.push_back(VDPrivateRefExpr);
19298 Inits.push_back(VDInitRefExpr);
19299 }
19300
19301 if (Vars.empty())
19302 return nullptr;
19303
19305 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
19306 buildPreInits(getASTContext(), ExprCaptures));
19307}
19308
19311 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
19312 SourceLocation LParenLoc, SourceLocation EndLoc) {
19313 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
19314 assert(ColonLoc.isValid() && "Colon location must be valid.");
19315 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
19316 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
19317 /*Last=*/OMPC_LASTPRIVATE_unknown)
19318 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
19319 return nullptr;
19320 }
19321
19323 SmallVector<Expr *, 8> SrcExprs;
19324 SmallVector<Expr *, 8> DstExprs;
19325 SmallVector<Expr *, 8> AssignmentOps;
19326 SmallVector<Decl *, 4> ExprCaptures;
19327 SmallVector<Expr *, 4> ExprPostUpdates;
19328 for (Expr *RefExpr : VarList) {
19329 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
19330 SourceLocation ELoc;
19331 SourceRange ERange;
19332 Expr *SimpleRefExpr = RefExpr;
19333 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19334 if (Res.second) {
19335 // It will be analyzed later.
19336 Vars.push_back(RefExpr);
19337 SrcExprs.push_back(nullptr);
19338 DstExprs.push_back(nullptr);
19339 AssignmentOps.push_back(nullptr);
19340 }
19341 ValueDecl *D = Res.first;
19342 if (!D)
19343 continue;
19344
19345 QualType Type = D->getType();
19346 auto *VD = dyn_cast<VarDecl>(D);
19347
19348 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
19349 // A variable that appears in a lastprivate clause must not have an
19350 // incomplete type or a reference type.
19351 if (SemaRef.RequireCompleteType(ELoc, Type,
19352 diag::err_omp_lastprivate_incomplete_type))
19353 continue;
19354 Type = Type.getNonReferenceType();
19355
19356 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19357 // A variable that is privatized must not have a const-qualified type
19358 // unless it is of class type with a mutable member. This restriction does
19359 // not apply to the firstprivate clause.
19360 //
19361 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
19362 // A variable that appears in a lastprivate clause must not have a
19363 // const-qualified type unless it is of class type with a mutable member.
19364 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc))
19365 continue;
19366
19367 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
19368 // A list item that appears in a lastprivate clause with the conditional
19369 // modifier must be a scalar variable.
19370 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
19371 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
19372 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19374 Diag(D->getLocation(),
19375 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19376 << D;
19377 continue;
19378 }
19379
19380 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19381 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19382 // in a Construct]
19383 // Variables with the predetermined data-sharing attributes may not be
19384 // listed in data-sharing attributes clauses, except for the cases
19385 // listed below.
19386 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
19387 // A list item may appear in a firstprivate or lastprivate clause but not
19388 // both.
19389 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19390 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
19391 (isOpenMPDistributeDirective(CurrDir) ||
19392 DVar.CKind != OMPC_firstprivate) &&
19393 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
19394 Diag(ELoc, diag::err_omp_wrong_dsa)
19395 << getOpenMPClauseNameForDiag(DVar.CKind)
19396 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
19398 continue;
19399 }
19400
19401 // OpenMP [2.14.3.5, Restrictions, p.2]
19402 // A list item that is private within a parallel region, or that appears in
19403 // the reduction clause of a parallel construct, must not appear in a
19404 // lastprivate clause on a worksharing construct if any of the corresponding
19405 // worksharing regions ever binds to any of the corresponding parallel
19406 // regions.
19407 DSAStackTy::DSAVarData TopDVar = DVar;
19408 if (isOpenMPWorksharingDirective(CurrDir) &&
19409 !isOpenMPParallelDirective(CurrDir) &&
19410 !isOpenMPTeamsDirective(CurrDir)) {
19411 DVar = DSAStack->getImplicitDSA(D, true);
19412 if (DVar.CKind != OMPC_shared) {
19413 Diag(ELoc, diag::err_omp_required_access)
19414 << getOpenMPClauseNameForDiag(OMPC_lastprivate)
19415 << getOpenMPClauseNameForDiag(OMPC_shared);
19417 continue;
19418 }
19419 }
19420
19421 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
19422 // A variable of class type (or array thereof) that appears in a
19423 // lastprivate clause requires an accessible, unambiguous default
19424 // constructor for the class type, unless the list item is also specified
19425 // in a firstprivate clause.
19426 // A variable of class type (or array thereof) that appears in a
19427 // lastprivate clause requires an accessible, unambiguous copy assignment
19428 // operator for the class type.
19430 VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(),
19431 Type.getUnqualifiedType(), ".lastprivate.src",
19432 D->hasAttrs() ? &D->getAttrs() : nullptr);
19433 DeclRefExpr *PseudoSrcExpr =
19434 buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc);
19435 VarDecl *DstVD =
19436 buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst",
19437 D->hasAttrs() ? &D->getAttrs() : nullptr);
19438 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
19439 // For arrays generate assignment operation for single element and replace
19440 // it by the original array element in CodeGen.
19441 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
19442 PseudoDstExpr, PseudoSrcExpr);
19443 if (AssignmentOp.isInvalid())
19444 continue;
19445 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
19446 /*DiscardedValue=*/false);
19447 if (AssignmentOp.isInvalid())
19448 continue;
19449
19450 DeclRefExpr *Ref = nullptr;
19451 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19452 if (TopDVar.CKind == OMPC_firstprivate) {
19453 Ref = TopDVar.PrivateCopy;
19454 } else {
19455 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19456 if (!isOpenMPCapturedDecl(D))
19457 ExprCaptures.push_back(Ref->getDecl());
19458 }
19459 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
19460 (!isOpenMPCapturedDecl(D) &&
19461 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
19462 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
19463 if (!RefRes.isUsable())
19464 continue;
19465 ExprResult PostUpdateRes =
19466 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
19467 SimpleRefExpr, RefRes.get());
19468 if (!PostUpdateRes.isUsable())
19469 continue;
19470 ExprPostUpdates.push_back(
19471 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
19472 }
19473 }
19474 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
19475 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19476 ? RefExpr->IgnoreParens()
19477 : Ref);
19478 SrcExprs.push_back(PseudoSrcExpr);
19479 DstExprs.push_back(PseudoDstExpr);
19480 AssignmentOps.push_back(AssignmentOp.get());
19481 }
19482
19483 if (Vars.empty())
19484 return nullptr;
19485
19487 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
19488 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
19489 buildPreInits(getASTContext(), ExprCaptures),
19490 buildPostUpdate(SemaRef, ExprPostUpdates));
19491}
19492
19494 SourceLocation StartLoc,
19495 SourceLocation LParenLoc,
19496 SourceLocation EndLoc) {
19498 for (Expr *RefExpr : VarList) {
19499 assert(RefExpr && "NULL expr in OpenMP shared clause.");
19500 SourceLocation ELoc;
19501 SourceRange ERange;
19502 Expr *SimpleRefExpr = RefExpr;
19503 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19504 if (Res.second) {
19505 // It will be analyzed later.
19506 Vars.push_back(RefExpr);
19507 }
19508 ValueDecl *D = Res.first;
19509 if (!D)
19510 continue;
19511
19512 auto *VD = dyn_cast<VarDecl>(D);
19513 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19514 // in a Construct]
19515 // Variables with the predetermined data-sharing attributes may not be
19516 // listed in data-sharing attributes clauses, except for the cases
19517 // listed below. For these exceptions only, listing a predetermined
19518 // variable in a data-sharing attribute clause is allowed and overrides
19519 // the variable's predetermined data-sharing attributes.
19520 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19521 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
19522 DVar.RefExpr) {
19523 Diag(ELoc, diag::err_omp_wrong_dsa)
19524 << getOpenMPClauseNameForDiag(DVar.CKind)
19525 << getOpenMPClauseNameForDiag(OMPC_shared);
19527 continue;
19528 }
19529
19530 DeclRefExpr *Ref = nullptr;
19531 if (!VD && isOpenMPCapturedDecl(D) &&
19532 !SemaRef.CurContext->isDependentContext())
19533 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19534 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
19535 Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext())
19536 ? RefExpr->IgnoreParens()
19537 : Ref);
19538 }
19539
19540 if (Vars.empty())
19541 return nullptr;
19542
19543 return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19544 Vars);
19545}
19546
19547namespace {
19548class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
19549 DSAStackTy *Stack;
19550
19551public:
19552 bool VisitDeclRefExpr(DeclRefExpr *E) {
19553 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
19554 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
19555 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
19556 return false;
19557 if (DVar.CKind != OMPC_unknown)
19558 return true;
19559 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
19560 VD,
19561 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
19562 return isOpenMPPrivate(C) && !AppliedToPointee;
19563 },
19564 [](OpenMPDirectiveKind) { return true; },
19565 /*FromParent=*/true);
19566 return DVarPrivate.CKind != OMPC_unknown;
19567 }
19568 return false;
19569 }
19570 bool VisitStmt(Stmt *S) {
19571 for (Stmt *Child : S->children()) {
19572 if (Child && Visit(Child))
19573 return true;
19574 }
19575 return false;
19576 }
19577 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
19578};
19579} // namespace
19580
19581namespace {
19582// Transform MemberExpression for specified FieldDecl of current class to
19583// DeclRefExpr to specified OMPCapturedExprDecl.
19584class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
19585 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
19586 ValueDecl *Field = nullptr;
19587 DeclRefExpr *CapturedExpr = nullptr;
19588
19589public:
19590 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
19591 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
19592
19593 ExprResult TransformMemberExpr(MemberExpr *E) {
19595 E->getMemberDecl() == Field) {
19596 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
19597 return CapturedExpr;
19598 }
19599 return BaseTransform::TransformMemberExpr(E);
19600 }
19601 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
19602};
19603} // namespace
19604
19605template <typename T, typename U>
19607 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
19608 for (U &Set : Lookups) {
19609 for (auto *D : Set) {
19610 if (T Res = Gen(cast<ValueDecl>(D)))
19611 return Res;
19612 }
19613 }
19614 return T();
19615}
19616
19618 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
19619
19620 for (auto *RD : D->redecls()) {
19621 // Don't bother with extra checks if we already know this one isn't visible.
19622 if (RD == D)
19623 continue;
19624
19625 auto ND = cast<NamedDecl>(RD);
19626 if (LookupResult::isVisible(SemaRef, ND))
19627 return ND;
19628 }
19629
19630 return nullptr;
19631}
19632
19633static void
19635 SourceLocation Loc, QualType Ty,
19637 // Find all of the associated namespaces and classes based on the
19638 // arguments we have.
19639 Sema::AssociatedNamespaceSet AssociatedNamespaces;
19640 Sema::AssociatedClassSet AssociatedClasses;
19641 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
19642 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
19643 AssociatedClasses);
19644
19645 // C++ [basic.lookup.argdep]p3:
19646 // Let X be the lookup set produced by unqualified lookup (3.4.1)
19647 // and let Y be the lookup set produced by argument dependent
19648 // lookup (defined as follows). If X contains [...] then Y is
19649 // empty. Otherwise Y is the set of declarations found in the
19650 // namespaces associated with the argument types as described
19651 // below. The set of declarations found by the lookup of the name
19652 // is the union of X and Y.
19653 //
19654 // Here, we compute Y and add its members to the overloaded
19655 // candidate set.
19656 for (auto *NS : AssociatedNamespaces) {
19657 // When considering an associated namespace, the lookup is the
19658 // same as the lookup performed when the associated namespace is
19659 // used as a qualifier (3.4.3.2) except that:
19660 //
19661 // -- Any using-directives in the associated namespace are
19662 // ignored.
19663 //
19664 // -- Any namespace-scope friend functions declared in
19665 // associated classes are visible within their respective
19666 // namespaces even if they are not visible during an ordinary
19667 // lookup (11.4).
19668 DeclContext::lookup_result R = NS->lookup(Id.getName());
19669 for (auto *D : R) {
19670 auto *Underlying = D;
19671 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19672 Underlying = USD->getTargetDecl();
19673
19674 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
19675 !isa<OMPDeclareMapperDecl>(Underlying))
19676 continue;
19677
19678 if (!SemaRef.isVisible(D)) {
19679 D = findAcceptableDecl(SemaRef, D);
19680 if (!D)
19681 continue;
19682 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19683 Underlying = USD->getTargetDecl();
19684 }
19685 Lookups.emplace_back();
19686 Lookups.back().addDecl(Underlying);
19687 }
19688 }
19689}
19690
19691static ExprResult
19693 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
19694 const DeclarationNameInfo &ReductionId, QualType Ty,
19695 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
19696 if (ReductionIdScopeSpec.isInvalid())
19697 return ExprError();
19698 SmallVector<UnresolvedSet<8>, 4> Lookups;
19699 if (S) {
19700 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19701 Lookup.suppressDiagnostics();
19702 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec,
19703 /*ObjectType=*/QualType())) {
19704 NamedDecl *D = Lookup.getRepresentativeDecl();
19705 do {
19706 S = S->getParent();
19707 } while (S && !S->isDeclScope(D));
19708 if (S)
19709 S = S->getParent();
19710 Lookups.emplace_back();
19711 Lookups.back().append(Lookup.begin(), Lookup.end());
19712 Lookup.clear();
19713 }
19714 } else if (auto *ULE =
19715 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
19716 Lookups.push_back(UnresolvedSet<8>());
19717 Decl *PrevD = nullptr;
19718 for (NamedDecl *D : ULE->decls()) {
19719 if (D == PrevD)
19720 Lookups.push_back(UnresolvedSet<8>());
19721 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
19722 Lookups.back().addDecl(DRD);
19723 PrevD = D;
19724 }
19725 }
19726 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
19730 return !D->isInvalidDecl() &&
19731 (D->getType()->isDependentType() ||
19732 D->getType()->isInstantiationDependentType() ||
19733 D->getType()->containsUnexpandedParameterPack());
19734 })) {
19735 UnresolvedSet<8> ResSet;
19736 for (const UnresolvedSet<8> &Set : Lookups) {
19737 if (Set.empty())
19738 continue;
19739 ResSet.append(Set.begin(), Set.end());
19740 // The last item marks the end of all declarations at the specified scope.
19741 ResSet.addDecl(Set[Set.size() - 1]);
19742 }
19744 SemaRef.Context, /*NamingClass=*/nullptr,
19745 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
19746 /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false,
19747 /*KnownInstantiationDependent=*/false);
19748 }
19749 // Lookup inside the classes.
19750 // C++ [over.match.oper]p3:
19751 // For a unary operator @ with an operand of a type whose
19752 // cv-unqualified version is T1, and for a binary operator @ with
19753 // a left operand of a type whose cv-unqualified version is T1 and
19754 // a right operand of a type whose cv-unqualified version is T2,
19755 // three sets of candidate functions, designated member
19756 // candidates, non-member candidates and built-in candidates, are
19757 // constructed as follows:
19758 // -- If T1 is a complete class type or a class currently being
19759 // defined, the set of member candidates is the result of the
19760 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
19761 // the set of member candidates is empty.
19762 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19763 Lookup.suppressDiagnostics();
19764 if (Ty->isRecordType()) {
19765 // Complete the type if it can be completed.
19766 // If the type is neither complete nor being defined, bail out now.
19767 bool IsComplete = SemaRef.isCompleteType(Loc, Ty);
19768 auto *RD = Ty->castAsRecordDecl();
19769 if (IsComplete || RD->isBeingDefined()) {
19770 Lookup.clear();
19771 SemaRef.LookupQualifiedName(Lookup, RD);
19772 if (Lookup.empty()) {
19773 Lookups.emplace_back();
19774 Lookups.back().append(Lookup.begin(), Lookup.end());
19775 }
19776 }
19777 }
19778 // Perform ADL.
19779 if (SemaRef.getLangOpts().CPlusPlus)
19780 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
19782 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
19783 if (!D->isInvalidDecl() &&
19784 SemaRef.Context.hasSameType(D->getType(), Ty))
19785 return D;
19786 return nullptr;
19787 }))
19788 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
19789 VK_LValue, Loc);
19790 if (SemaRef.getLangOpts().CPlusPlus) {
19792 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
19793 if (!D->isInvalidDecl() &&
19794 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
19796 SemaRef.getASTContext()))
19797 return D;
19798 return nullptr;
19799 })) {
19800 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
19801 /*DetectVirtual=*/false);
19802 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
19803 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
19804 VD->getType().getUnqualifiedType()))) {
19805 if (SemaRef.CheckBaseClassAccess(
19806 Loc, VD->getType(), Ty, Paths.front(),
19807 /*DiagID=*/0) != Sema::AR_inaccessible) {
19808 SemaRef.BuildBasePathArray(Paths, BasePath);
19809 return SemaRef.BuildDeclRefExpr(
19810 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc);
19811 }
19812 }
19813 }
19814 }
19815 }
19816 if (ReductionIdScopeSpec.isSet()) {
19817 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
19818 << Ty << Range;
19819 return ExprError();
19820 }
19821 return ExprEmpty();
19822}
19823
19824namespace {
19825/// Data for the reduction-based clauses.
19826struct ReductionData {
19827 /// List of original reduction items.
19828 SmallVector<Expr *, 8> Vars;
19829 /// List of private copies of the reduction items.
19830 SmallVector<Expr *, 8> Privates;
19831 /// LHS expressions for the reduction_op expressions.
19832 SmallVector<Expr *, 8> LHSs;
19833 /// RHS expressions for the reduction_op expressions.
19834 SmallVector<Expr *, 8> RHSs;
19835 /// Reduction operation expression.
19836 SmallVector<Expr *, 8> ReductionOps;
19837 /// inscan copy operation expressions.
19838 SmallVector<Expr *, 8> InscanCopyOps;
19839 /// inscan copy temp array expressions for prefix sums.
19840 SmallVector<Expr *, 8> InscanCopyArrayTemps;
19841 /// inscan copy temp array element expressions for prefix sums.
19842 SmallVector<Expr *, 8> InscanCopyArrayElems;
19843 /// Taskgroup descriptors for the corresponding reduction items in
19844 /// in_reduction clauses.
19845 SmallVector<Expr *, 8> TaskgroupDescriptors;
19846 /// List of captures for clause.
19847 SmallVector<Decl *, 4> ExprCaptures;
19848 /// List of postupdate expressions.
19849 SmallVector<Expr *, 4> ExprPostUpdates;
19850 /// Reduction modifier.
19851 unsigned RedModifier = 0;
19852 /// Original modifier.
19853 unsigned OrigSharingModifier = 0;
19854 /// Private Variable Reduction
19855 SmallVector<bool, 8> IsPrivateVarReduction;
19856 ReductionData() = delete;
19857 /// Reserves required memory for the reduction data.
19858 ReductionData(unsigned Size, unsigned Modifier = 0, unsigned OrgModifier = 0)
19859 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
19860 Vars.reserve(Size);
19861 Privates.reserve(Size);
19862 LHSs.reserve(Size);
19863 RHSs.reserve(Size);
19864 ReductionOps.reserve(Size);
19865 IsPrivateVarReduction.reserve(Size);
19866 if (RedModifier == OMPC_REDUCTION_inscan) {
19867 InscanCopyOps.reserve(Size);
19868 InscanCopyArrayTemps.reserve(Size);
19869 InscanCopyArrayElems.reserve(Size);
19870 }
19871 TaskgroupDescriptors.reserve(Size);
19872 ExprCaptures.reserve(Size);
19873 ExprPostUpdates.reserve(Size);
19874 }
19875 /// Stores reduction item and reduction operation only (required for dependent
19876 /// reduction item).
19877 void push(Expr *Item, Expr *ReductionOp) {
19878 Vars.emplace_back(Item);
19879 Privates.emplace_back(nullptr);
19880 LHSs.emplace_back(nullptr);
19881 RHSs.emplace_back(nullptr);
19882 ReductionOps.emplace_back(ReductionOp);
19883 IsPrivateVarReduction.emplace_back(false);
19884 TaskgroupDescriptors.emplace_back(nullptr);
19885 if (RedModifier == OMPC_REDUCTION_inscan) {
19886 InscanCopyOps.push_back(nullptr);
19887 InscanCopyArrayTemps.push_back(nullptr);
19888 InscanCopyArrayElems.push_back(nullptr);
19889 }
19890 }
19891 /// Stores reduction data.
19892 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
19893 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
19894 Expr *CopyArrayElem, bool IsPrivate) {
19895 Vars.emplace_back(Item);
19896 Privates.emplace_back(Private);
19897 LHSs.emplace_back(LHS);
19898 RHSs.emplace_back(RHS);
19899 ReductionOps.emplace_back(ReductionOp);
19900 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
19901 if (RedModifier == OMPC_REDUCTION_inscan) {
19902 InscanCopyOps.push_back(CopyOp);
19903 InscanCopyArrayTemps.push_back(CopyArrayTemp);
19904 InscanCopyArrayElems.push_back(CopyArrayElem);
19905 } else {
19906 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
19907 CopyArrayElem == nullptr &&
19908 "Copy operation must be used for inscan reductions only.");
19909 }
19910 IsPrivateVarReduction.emplace_back(IsPrivate);
19911 }
19912};
19913} // namespace
19914
19916 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
19917 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
19918 const Expr *Length = OASE->getLength();
19919 if (Length == nullptr) {
19920 // For array sections of the form [1:] or [:], we would need to analyze
19921 // the lower bound...
19922 if (OASE->getColonLocFirst().isValid())
19923 return false;
19924
19925 // This is an array subscript which has implicit length 1!
19926 SingleElement = true;
19927 ArraySizes.push_back(llvm::APSInt::get(1));
19928 } else {
19929 Expr::EvalResult Result;
19930 if (!Length->EvaluateAsInt(Result, Context))
19931 return false;
19932
19933 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19934 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
19935 ArraySizes.push_back(ConstantLengthValue);
19936 }
19937
19938 // Get the base of this array section and walk up from there.
19939 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
19940
19941 // We require length = 1 for all array sections except the right-most to
19942 // guarantee that the memory region is contiguous and has no holes in it.
19943 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) {
19944 Length = TempOASE->getLength();
19945 if (Length == nullptr) {
19946 // For array sections of the form [1:] or [:], we would need to analyze
19947 // the lower bound...
19948 if (OASE->getColonLocFirst().isValid())
19949 return false;
19950
19951 // This is an array subscript which has implicit length 1!
19952 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
19953 ArraySizes.push_back(ConstantOne);
19954 } else {
19955 Expr::EvalResult Result;
19956 if (!Length->EvaluateAsInt(Result, Context))
19957 return false;
19958
19959 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19960 if (ConstantLengthValue.getSExtValue() != 1)
19961 return false;
19962
19963 ArraySizes.push_back(ConstantLengthValue);
19964 }
19965 Base = TempOASE->getBase()->IgnoreParenImpCasts();
19966 }
19967
19968 // If we have a single element, we don't need to add the implicit lengths.
19969 if (!SingleElement) {
19970 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
19971 // Has implicit length 1!
19972 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
19973 ArraySizes.push_back(ConstantOne);
19974 Base = TempASE->getBase()->IgnoreParenImpCasts();
19975 }
19976 }
19977
19978 // This array section can be privatized as a single value or as a constant
19979 // sized array.
19980 return true;
19981}
19982
19983static BinaryOperatorKind
19985 if (BOK == BO_Add)
19986 return BO_AddAssign;
19987 if (BOK == BO_Mul)
19988 return BO_MulAssign;
19989 if (BOK == BO_And)
19990 return BO_AndAssign;
19991 if (BOK == BO_Or)
19992 return BO_OrAssign;
19993 if (BOK == BO_Xor)
19994 return BO_XorAssign;
19995 return BOK;
19996}
19997
19999 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
20000 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20001 SourceLocation ColonLoc, SourceLocation EndLoc,
20002 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20003 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
20004 DeclarationName DN = ReductionId.getName();
20006 BinaryOperatorKind BOK = BO_Comma;
20007
20008 ASTContext &Context = S.Context;
20009 // OpenMP [2.14.3.6, reduction clause]
20010 // C
20011 // reduction-identifier is either an identifier or one of the following
20012 // operators: +, -, *, &, |, ^, && and ||
20013 // C++
20014 // reduction-identifier is either an id-expression or one of the following
20015 // operators: +, -, *, &, |, ^, && and ||
20016 switch (OOK) {
20017 case OO_Plus:
20018 BOK = BO_Add;
20019 break;
20020 case OO_Minus:
20021 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
20022 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
20023 // reduction identifier.
20024 if (S.LangOpts.OpenMP > 52)
20025 BOK = BO_Comma;
20026 else
20027 BOK = BO_Add;
20028 break;
20029 case OO_Star:
20030 BOK = BO_Mul;
20031 break;
20032 case OO_Amp:
20033 BOK = BO_And;
20034 break;
20035 case OO_Pipe:
20036 BOK = BO_Or;
20037 break;
20038 case OO_Caret:
20039 BOK = BO_Xor;
20040 break;
20041 case OO_AmpAmp:
20042 BOK = BO_LAnd;
20043 break;
20044 case OO_PipePipe:
20045 BOK = BO_LOr;
20046 break;
20047 case OO_New:
20048 case OO_Delete:
20049 case OO_Array_New:
20050 case OO_Array_Delete:
20051 case OO_Slash:
20052 case OO_Percent:
20053 case OO_Tilde:
20054 case OO_Exclaim:
20055 case OO_Equal:
20056 case OO_Less:
20057 case OO_Greater:
20058 case OO_LessEqual:
20059 case OO_GreaterEqual:
20060 case OO_PlusEqual:
20061 case OO_MinusEqual:
20062 case OO_StarEqual:
20063 case OO_SlashEqual:
20064 case OO_PercentEqual:
20065 case OO_CaretEqual:
20066 case OO_AmpEqual:
20067 case OO_PipeEqual:
20068 case OO_LessLess:
20069 case OO_GreaterGreater:
20070 case OO_LessLessEqual:
20071 case OO_GreaterGreaterEqual:
20072 case OO_EqualEqual:
20073 case OO_ExclaimEqual:
20074 case OO_Spaceship:
20075 case OO_PlusPlus:
20076 case OO_MinusMinus:
20077 case OO_Comma:
20078 case OO_ArrowStar:
20079 case OO_Arrow:
20080 case OO_Call:
20081 case OO_Subscript:
20082 case OO_Conditional:
20083 case OO_Coawait:
20085 llvm_unreachable("Unexpected reduction identifier");
20086 case OO_None:
20087 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
20088 if (II->isStr("max"))
20089 BOK = BO_GT;
20090 else if (II->isStr("min"))
20091 BOK = BO_LT;
20092 }
20093 break;
20094 }
20095
20096 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
20097 // A reduction clause with the minus (-) operator was deprecated
20098 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
20099 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
20100
20101 SourceRange ReductionIdRange;
20102 if (ReductionIdScopeSpec.isValid())
20103 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
20104 else
20105 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
20106 ReductionIdRange.setEnd(ReductionId.getEndLoc());
20107
20108 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
20109 bool FirstIter = true;
20110 for (Expr *RefExpr : VarList) {
20111 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
20112 // OpenMP [2.1, C/C++]
20113 // A list item is a variable or array section, subject to the restrictions
20114 // specified in Section 2.4 on page 42 and in each of the sections
20115 // describing clauses and directives for which a list appears.
20116 // OpenMP [2.14.3.3, Restrictions, p.1]
20117 // A variable that is part of another variable (as an array or
20118 // structure element) cannot appear in a private clause.
20119 if (!FirstIter && IR != ER)
20120 ++IR;
20121 FirstIter = false;
20122 SourceLocation ELoc;
20123 SourceRange ERange;
20124 bool IsPrivate = false;
20125 Expr *SimpleRefExpr = RefExpr;
20126 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
20127 /*AllowArraySection=*/true);
20128 if (Res.second) {
20129 // Try to find 'declare reduction' corresponding construct before using
20130 // builtin/overloaded operators.
20131 QualType Type = Context.DependentTy;
20132 CXXCastPath BasePath;
20133 ExprResult DeclareReductionRef = buildDeclareReductionRef(
20134 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20135 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
20136 Expr *ReductionOp = nullptr;
20137 if (S.CurContext->isDependentContext() &&
20138 (DeclareReductionRef.isUnset() ||
20139 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
20140 ReductionOp = DeclareReductionRef.get();
20141 // It will be analyzed later.
20142 RD.push(RefExpr, ReductionOp);
20143 }
20144 ValueDecl *D = Res.first;
20145 if (!D)
20146 continue;
20147
20148 Expr *TaskgroupDescriptor = nullptr;
20149 QualType Type;
20150 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
20151 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
20152 if (ASE) {
20153 Type = ASE->getType().getNonReferenceType();
20154 } else if (OASE) {
20155 QualType BaseType =
20157 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20158 Type = ATy->getElementType();
20159 else
20160 Type = BaseType->getPointeeType();
20161 Type = Type.getNonReferenceType();
20162 } else {
20163 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
20164 }
20165 auto *VD = dyn_cast<VarDecl>(D);
20166
20167 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
20168 // A variable that appears in a private clause must not have an incomplete
20169 // type or a reference type.
20170 if (S.RequireCompleteType(ELoc, D->getType(),
20171 diag::err_omp_reduction_incomplete_type))
20172 continue;
20173 // OpenMP [2.14.3.6, reduction clause, Restrictions]
20174 // A list item that appears in a reduction clause must not be
20175 // const-qualified.
20176 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
20177 /*AcceptIfMutable=*/false, ASE || OASE))
20178 continue;
20179
20180 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
20181 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
20182 // If a list-item is a reference type then it must bind to the same object
20183 // for all threads of the team.
20184 if (!ASE && !OASE) {
20185 if (VD) {
20186 VarDecl *VDDef = VD->getDefinition();
20187 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
20188 DSARefChecker Check(Stack);
20189 if (Check.Visit(VDDef->getInit())) {
20190 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
20191 << getOpenMPClauseNameForDiag(ClauseKind) << ERange;
20192 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
20193 continue;
20194 }
20195 }
20196 }
20197
20198 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
20199 // in a Construct]
20200 // Variables with the predetermined data-sharing attributes may not be
20201 // listed in data-sharing attributes clauses, except for the cases
20202 // listed below. For these exceptions only, listing a predetermined
20203 // variable in a data-sharing attribute clause is allowed and overrides
20204 // the variable's predetermined data-sharing attributes.
20205 // OpenMP [2.14.3.6, Restrictions, p.3]
20206 // Any number of reduction clauses can be specified on the directive,
20207 // but a list item can appear only once in the reduction clauses for that
20208 // directive.
20209 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
20210 if (DVar.CKind == OMPC_reduction) {
20211 S.Diag(ELoc, diag::err_omp_once_referenced)
20212 << getOpenMPClauseNameForDiag(ClauseKind);
20213 if (DVar.RefExpr)
20214 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
20215 continue;
20216 }
20217 if (DVar.CKind != OMPC_unknown) {
20218 S.Diag(ELoc, diag::err_omp_wrong_dsa)
20219 << getOpenMPClauseNameForDiag(DVar.CKind)
20220 << getOpenMPClauseNameForDiag(OMPC_reduction);
20221 reportOriginalDsa(S, Stack, D, DVar);
20222 continue;
20223 }
20224
20225 // OpenMP [2.14.3.6, Restrictions, p.1]
20226 // A list item that appears in a reduction clause of a worksharing
20227 // construct must be shared in the parallel regions to which any of the
20228 // worksharing regions arising from the worksharing construct bind.
20229
20230 if (S.getLangOpts().OpenMP <= 52 &&
20232 !isOpenMPParallelDirective(CurrDir) &&
20233 !isOpenMPTeamsDirective(CurrDir)) {
20234 DVar = Stack->getImplicitDSA(D, true);
20235 if (DVar.CKind != OMPC_shared) {
20236 S.Diag(ELoc, diag::err_omp_required_access)
20237 << getOpenMPClauseNameForDiag(OMPC_reduction)
20238 << getOpenMPClauseNameForDiag(OMPC_shared);
20239 reportOriginalDsa(S, Stack, D, DVar);
20240 continue;
20241 }
20242 } else if (isOpenMPWorksharingDirective(CurrDir) &&
20243 !isOpenMPParallelDirective(CurrDir) &&
20244 !isOpenMPTeamsDirective(CurrDir)) {
20245 // OpenMP 6.0 [ 7.6.10 ]
20246 // Support Reduction over private variables with reduction clause.
20247 // A list item in a reduction clause can now be private in the enclosing
20248 // context. For orphaned constructs it is assumed to be shared unless
20249 // the original(private) modifier appears in the clause.
20250 DVar = Stack->getImplicitDSA(D, true);
20251 // Determine if the variable should be considered private
20252 IsPrivate = DVar.CKind != OMPC_shared;
20253 bool IsOrphaned = false;
20254 OpenMPDirectiveKind ParentDir = Stack->getParentDirective();
20255 IsOrphaned = ParentDir == OMPD_unknown;
20256 if ((IsOrphaned &&
20257 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
20258 IsPrivate = true;
20259 }
20260 } else {
20261 // Threadprivates cannot be shared between threads, so dignose if the base
20262 // is a threadprivate variable.
20263 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
20264 if (DVar.CKind == OMPC_threadprivate) {
20265 S.Diag(ELoc, diag::err_omp_wrong_dsa)
20266 << getOpenMPClauseNameForDiag(DVar.CKind)
20267 << getOpenMPClauseNameForDiag(OMPC_reduction);
20268 reportOriginalDsa(S, Stack, D, DVar);
20269 continue;
20270 }
20271 }
20272
20273 // Try to find 'declare reduction' corresponding construct before using
20274 // builtin/overloaded operators.
20275 CXXCastPath BasePath;
20276 ExprResult DeclareReductionRef = buildDeclareReductionRef(
20277 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20278 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
20279 if (DeclareReductionRef.isInvalid())
20280 continue;
20281 if (S.CurContext->isDependentContext() &&
20282 (DeclareReductionRef.isUnset() ||
20283 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
20284 RD.push(RefExpr, DeclareReductionRef.get());
20285 continue;
20286 }
20287 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
20288 // Not allowed reduction identifier is found.
20289 if (S.LangOpts.OpenMP > 52)
20290 S.Diag(ReductionId.getBeginLoc(),
20291 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
20292 << Type << ReductionIdRange;
20293 else
20294 S.Diag(ReductionId.getBeginLoc(),
20295 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
20296 << Type << ReductionIdRange;
20297 continue;
20298 }
20299
20300 // OpenMP [2.14.3.6, reduction clause, Restrictions]
20301 // The type of a list item that appears in a reduction clause must be valid
20302 // for the reduction-identifier. For a max or min reduction in C, the type
20303 // of the list item must be an allowed arithmetic data type: char, int,
20304 // float, double, or _Bool, possibly modified with long, short, signed, or
20305 // unsigned. For a max or min reduction in C++, the type of the list item
20306 // must be an allowed arithmetic data type: char, wchar_t, int, float,
20307 // double, or bool, possibly modified with long, short, signed, or unsigned.
20308 if (DeclareReductionRef.isUnset()) {
20309 if ((BOK == BO_GT || BOK == BO_LT) &&
20310 !(Type->isScalarType() ||
20311 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
20312 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
20313 << getOpenMPClauseNameForDiag(ClauseKind)
20314 << S.getLangOpts().CPlusPlus;
20315 if (!ASE && !OASE) {
20316 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20318 S.Diag(D->getLocation(),
20319 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20320 << D;
20321 }
20322 continue;
20323 }
20324 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
20325 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
20326 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
20327 << getOpenMPClauseNameForDiag(ClauseKind);
20328 if (!ASE && !OASE) {
20329 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20331 S.Diag(D->getLocation(),
20332 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20333 << D;
20334 }
20335 continue;
20336 }
20337 }
20338
20339 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
20340 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
20341 D->hasAttrs() ? &D->getAttrs() : nullptr);
20342 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
20343 D->hasAttrs() ? &D->getAttrs() : nullptr);
20344 QualType PrivateTy = Type;
20345
20346 // Try if we can determine constant lengths for all array sections and avoid
20347 // the VLA.
20348 bool ConstantLengthOASE = false;
20349 if (OASE) {
20350 bool SingleElement;
20352 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
20353 Context, OASE, SingleElement, ArraySizes);
20354
20355 // If we don't have a single element, we must emit a constant array type.
20356 if (ConstantLengthOASE && !SingleElement) {
20357 for (llvm::APSInt &Size : ArraySizes)
20358 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
20360 /*IndexTypeQuals=*/0);
20361 }
20362 }
20363
20364 if ((OASE && !ConstantLengthOASE) ||
20365 (!OASE && !ASE &&
20367 if (!Context.getTargetInfo().isVLASupported()) {
20368 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
20369 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20370 S.Diag(ELoc, diag::note_vla_unsupported);
20371 continue;
20372 } else {
20373 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20374 S.targetDiag(ELoc, diag::note_vla_unsupported);
20375 }
20376 }
20377 // For arrays/array sections only:
20378 // Create pseudo array type for private copy. The size for this array will
20379 // be generated during codegen.
20380 // For array subscripts or single variables Private Ty is the same as Type
20381 // (type of the variable or single array element).
20382 PrivateTy = Context.getVariableArrayType(
20383 Type,
20384 new (Context)
20385 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
20386 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0);
20387 } else if (!ASE && !OASE &&
20388 Context.getAsArrayType(D->getType().getNonReferenceType())) {
20389 PrivateTy = D->getType().getNonReferenceType();
20390 }
20391 // Private copy.
20392 VarDecl *PrivateVD =
20393 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
20394 D->hasAttrs() ? &D->getAttrs() : nullptr,
20395 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
20396 // Add initializer for private variable.
20397 Expr *Init = nullptr;
20398 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
20399 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
20400 if (DeclareReductionRef.isUsable()) {
20401 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
20402 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
20403 if (DRD->getInitializer()) {
20404 Init = DRDRef;
20405 RHSVD->setInit(DRDRef);
20407 }
20408 } else {
20409 switch (BOK) {
20410 case BO_Add:
20411 case BO_Xor:
20412 case BO_Or:
20413 case BO_LOr:
20414 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
20416 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
20417 break;
20418 case BO_Mul:
20419 case BO_LAnd:
20420 if (Type->isScalarType() || Type->isAnyComplexType()) {
20421 // '*' and '&&' reduction ops - initializer is '1'.
20422 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
20423 }
20424 break;
20425 case BO_And: {
20426 // '&' reduction op - initializer is '~0'.
20427 QualType OrigType = Type;
20428 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
20429 Type = ComplexTy->getElementType();
20430 if (Type->isRealFloatingType()) {
20431 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
20432 Context.getFloatTypeSemantics(Type));
20433 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
20434 Type, ELoc);
20435 } else if (Type->isScalarType()) {
20436 uint64_t Size = Context.getTypeSize(Type);
20437 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
20438 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
20439 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
20440 }
20441 if (Init && OrigType->isAnyComplexType()) {
20442 // Init = 0xFFFF + 0xFFFFi;
20443 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
20444 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
20445 }
20446 Type = OrigType;
20447 break;
20448 }
20449 case BO_LT:
20450 case BO_GT: {
20451 // 'min' reduction op - initializer is 'Largest representable number in
20452 // the reduction list item type'.
20453 // 'max' reduction op - initializer is 'Least representable number in
20454 // the reduction list item type'.
20455 if (Type->isIntegerType() || Type->isPointerType()) {
20456 bool IsSigned = Type->hasSignedIntegerRepresentation();
20457 uint64_t Size = Context.getTypeSize(Type);
20458 QualType IntTy =
20459 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
20460 llvm::APInt InitValue =
20461 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
20462 : llvm::APInt::getMinValue(Size)
20463 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
20464 : llvm::APInt::getMaxValue(Size);
20465 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
20466 if (Type->isPointerType()) {
20467 // Cast to pointer type.
20469 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
20470 if (CastExpr.isInvalid())
20471 continue;
20472 Init = CastExpr.get();
20473 }
20474 } else if (Type->isRealFloatingType()) {
20475 llvm::APFloat InitValue = llvm::APFloat::getLargest(
20476 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
20477 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
20478 Type, ELoc);
20479 }
20480 break;
20481 }
20482 case BO_PtrMemD:
20483 case BO_PtrMemI:
20484 case BO_MulAssign:
20485 case BO_Div:
20486 case BO_Rem:
20487 case BO_Sub:
20488 case BO_Shl:
20489 case BO_Shr:
20490 case BO_LE:
20491 case BO_GE:
20492 case BO_EQ:
20493 case BO_NE:
20494 case BO_Cmp:
20495 case BO_AndAssign:
20496 case BO_XorAssign:
20497 case BO_OrAssign:
20498 case BO_Assign:
20499 case BO_AddAssign:
20500 case BO_SubAssign:
20501 case BO_DivAssign:
20502 case BO_RemAssign:
20503 case BO_ShlAssign:
20504 case BO_ShrAssign:
20505 case BO_Comma:
20506 llvm_unreachable("Unexpected reduction operation");
20507 }
20508 }
20509 if (Init && DeclareReductionRef.isUnset()) {
20510 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
20511 // Store initializer for single element in private copy. Will be used
20512 // during codegen.
20513 PrivateVD->setInit(RHSVD->getInit());
20514 PrivateVD->setInitStyle(RHSVD->getInitStyle());
20515 } else if (!Init) {
20516 S.ActOnUninitializedDecl(RHSVD);
20517 // Store initializer for single element in private copy. Will be used
20518 // during codegen.
20519 PrivateVD->setInit(RHSVD->getInit());
20520 PrivateVD->setInitStyle(RHSVD->getInitStyle());
20521 }
20522 if (RHSVD->isInvalidDecl())
20523 continue;
20524 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
20525 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
20526 << Type << ReductionIdRange;
20527 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20529 S.Diag(D->getLocation(),
20530 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20531 << D;
20532 continue;
20533 }
20534 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
20535 ExprResult ReductionOp;
20536 if (DeclareReductionRef.isUsable()) {
20537 QualType RedTy = DeclareReductionRef.get()->getType();
20538 QualType PtrRedTy = Context.getPointerType(RedTy);
20539 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
20540 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
20541 if (!BasePath.empty()) {
20542 LHS = S.DefaultLvalueConversion(LHS.get());
20543 RHS = S.DefaultLvalueConversion(RHS.get());
20545 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
20546 LHS.get()->getValueKind(), FPOptionsOverride());
20548 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
20549 RHS.get()->getValueKind(), FPOptionsOverride());
20550 }
20552 QualType Params[] = {PtrRedTy, PtrRedTy};
20553 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
20554 auto *OVE = new (Context) OpaqueValueExpr(
20555 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
20556 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
20557 Expr *Args[] = {LHS.get(), RHS.get()};
20558 ReductionOp =
20559 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
20561 } else {
20563 if (Type->isRecordType() && CombBOK != BOK) {
20565 ReductionOp =
20566 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20567 CombBOK, LHSDRE, RHSDRE);
20568 }
20569 if (!ReductionOp.isUsable()) {
20570 ReductionOp =
20571 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
20572 LHSDRE, RHSDRE);
20573 if (ReductionOp.isUsable()) {
20574 if (BOK != BO_LT && BOK != BO_GT) {
20575 ReductionOp =
20576 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20577 BO_Assign, LHSDRE, ReductionOp.get());
20578 } else {
20579 auto *ConditionalOp = new (Context)
20580 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
20581 RHSDRE, Type, VK_LValue, OK_Ordinary);
20582 ReductionOp =
20583 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20584 BO_Assign, LHSDRE, ConditionalOp);
20585 }
20586 }
20587 }
20588 if (ReductionOp.isUsable())
20589 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
20590 /*DiscardedValue=*/false);
20591 if (!ReductionOp.isUsable())
20592 continue;
20593 }
20594
20595 // Add copy operations for inscan reductions.
20596 // LHS = RHS;
20597 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
20598 if (ClauseKind == OMPC_reduction &&
20599 RD.RedModifier == OMPC_REDUCTION_inscan) {
20600 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
20601 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
20602 RHS.get());
20603 if (!CopyOpRes.isUsable())
20604 continue;
20605 CopyOpRes =
20606 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
20607 if (!CopyOpRes.isUsable())
20608 continue;
20609 // For simd directive and simd-based directives in simd mode no need to
20610 // construct temp array, need just a single temp element.
20611 if (Stack->getCurrentDirective() == OMPD_simd ||
20612 (S.getLangOpts().OpenMPSimd &&
20613 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
20614 VarDecl *TempArrayVD =
20615 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
20616 D->hasAttrs() ? &D->getAttrs() : nullptr);
20617 // Add a constructor to the temp decl.
20618 S.ActOnUninitializedDecl(TempArrayVD);
20619 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
20620 } else {
20621 // Build temp array for prefix sum.
20622 auto *Dim = new (S.Context)
20625 PrivateTy, Dim, ArraySizeModifier::Normal,
20626 /*IndexTypeQuals=*/0);
20627 VarDecl *TempArrayVD =
20628 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
20629 D->hasAttrs() ? &D->getAttrs() : nullptr);
20630 // Add a constructor to the temp decl.
20631 S.ActOnUninitializedDecl(TempArrayVD);
20632 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
20633 TempArrayElem =
20634 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
20635 auto *Idx = new (S.Context)
20637 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
20638 ELoc, Idx, ELoc);
20639 }
20640 }
20641
20642 // OpenMP [2.15.4.6, Restrictions, p.2]
20643 // A list item that appears in an in_reduction clause of a task construct
20644 // must appear in a task_reduction clause of a construct associated with a
20645 // taskgroup region that includes the participating task in its taskgroup
20646 // set. The construct associated with the innermost region that meets this
20647 // condition must specify the same reduction-identifier as the in_reduction
20648 // clause.
20649 if (ClauseKind == OMPC_in_reduction) {
20650 SourceRange ParentSR;
20651 BinaryOperatorKind ParentBOK;
20652 const Expr *ParentReductionOp = nullptr;
20653 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
20654 DSAStackTy::DSAVarData ParentBOKDSA =
20655 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
20656 ParentBOKTD);
20657 DSAStackTy::DSAVarData ParentReductionOpDSA =
20658 Stack->getTopMostTaskgroupReductionData(
20659 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
20660 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
20661 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
20662 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
20663 (DeclareReductionRef.isUsable() && IsParentBOK) ||
20664 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
20665 bool EmitError = true;
20666 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
20667 llvm::FoldingSetNodeID RedId, ParentRedId;
20668 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
20669 DeclareReductionRef.get()->Profile(RedId, Context,
20670 /*Canonical=*/true);
20671 EmitError = RedId != ParentRedId;
20672 }
20673 if (EmitError) {
20674 S.Diag(ReductionId.getBeginLoc(),
20675 diag::err_omp_reduction_identifier_mismatch)
20676 << ReductionIdRange << RefExpr->getSourceRange();
20677 S.Diag(ParentSR.getBegin(),
20678 diag::note_omp_previous_reduction_identifier)
20679 << ParentSR
20680 << (IsParentBOK ? ParentBOKDSA.RefExpr
20681 : ParentReductionOpDSA.RefExpr)
20682 ->getSourceRange();
20683 continue;
20684 }
20685 }
20686 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
20687 }
20688
20689 DeclRefExpr *Ref = nullptr;
20690 Expr *VarsExpr = RefExpr->IgnoreParens();
20691 if (!VD && !S.CurContext->isDependentContext()) {
20692 if (ASE || OASE) {
20693 TransformExprToCaptures RebuildToCapture(S, D);
20694 VarsExpr =
20695 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
20696 Ref = RebuildToCapture.getCapturedExpr();
20697 } else {
20698 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
20699 }
20700 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
20701 RD.ExprCaptures.emplace_back(Ref->getDecl());
20702 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20703 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
20704 if (!RefRes.isUsable())
20705 continue;
20706 ExprResult PostUpdateRes =
20707 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
20708 RefRes.get());
20709 if (!PostUpdateRes.isUsable())
20710 continue;
20711 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
20712 Stack->getCurrentDirective() == OMPD_taskgroup) {
20713 S.Diag(RefExpr->getExprLoc(),
20714 diag::err_omp_reduction_non_addressable_expression)
20715 << RefExpr->getSourceRange();
20716 continue;
20717 }
20718 RD.ExprPostUpdates.emplace_back(
20719 S.IgnoredValueConversions(PostUpdateRes.get()).get());
20720 }
20721 }
20722 }
20723 // All reduction items are still marked as reduction (to do not increase
20724 // code base size).
20725 unsigned Modifier = RD.RedModifier;
20726 // Consider task_reductions as reductions with task modifier. Required for
20727 // correct analysis of in_reduction clauses.
20728 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
20729 Modifier = OMPC_REDUCTION_task;
20730 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
20731 ASE || OASE);
20732 if (Modifier == OMPC_REDUCTION_task &&
20733 (CurrDir == OMPD_taskgroup ||
20734 ((isOpenMPParallelDirective(CurrDir) ||
20735 isOpenMPWorksharingDirective(CurrDir)) &&
20736 !isOpenMPSimdDirective(CurrDir)))) {
20737 if (DeclareReductionRef.isUsable())
20738 Stack->addTaskgroupReductionData(D, ReductionIdRange,
20739 DeclareReductionRef.get());
20740 else
20741 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
20742 }
20743 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
20744 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
20745 TempArrayElem.get(), IsPrivate);
20746 }
20747 return RD.Vars.empty();
20748}
20749
20751 ArrayRef<Expr *> VarList,
20753 SourceLocation StartLoc, SourceLocation LParenLoc,
20754 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
20755 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20756 ArrayRef<Expr *> UnresolvedReductions) {
20758 static_cast<OpenMPReductionClauseModifier>(Modifiers.ExtraModifier);
20759 OpenMPOriginalSharingModifier OriginalSharingModifier =
20760 static_cast<OpenMPOriginalSharingModifier>(
20761 Modifiers.OriginalSharingModifier);
20762 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
20763 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
20764 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
20765 /*Last=*/OMPC_REDUCTION_unknown)
20766 << getOpenMPClauseNameForDiag(OMPC_reduction);
20767 return nullptr;
20768 }
20769 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
20770 // A reduction clause with the inscan reduction-modifier may only appear on a
20771 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
20772 // construct, a parallel worksharing-loop construct or a parallel
20773 // worksharing-loop SIMD construct.
20774 if (Modifier == OMPC_REDUCTION_inscan &&
20775 (DSAStack->getCurrentDirective() != OMPD_for &&
20776 DSAStack->getCurrentDirective() != OMPD_for_simd &&
20777 DSAStack->getCurrentDirective() != OMPD_simd &&
20778 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
20779 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
20780 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
20781 return nullptr;
20782 }
20783 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
20784 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
20785 StartLoc, LParenLoc, ColonLoc, EndLoc,
20786 ReductionIdScopeSpec, ReductionId,
20787 UnresolvedReductions, RD))
20788 return nullptr;
20789
20791 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
20792 Modifier, RD.Vars,
20793 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20794 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
20795 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
20796 buildPreInits(getASTContext(), RD.ExprCaptures),
20797 buildPostUpdate(SemaRef, RD.ExprPostUpdates), RD.IsPrivateVarReduction,
20798 OriginalSharingModifier);
20799}
20800
20802 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20803 SourceLocation ColonLoc, SourceLocation EndLoc,
20804 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20805 ArrayRef<Expr *> UnresolvedReductions) {
20806 ReductionData RD(VarList.size());
20807 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction,
20808 VarList, StartLoc, LParenLoc, ColonLoc,
20809 EndLoc, ReductionIdScopeSpec, ReductionId,
20810 UnresolvedReductions, RD))
20811 return nullptr;
20812
20814 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20815 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20816 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
20817 buildPreInits(getASTContext(), RD.ExprCaptures),
20818 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
20819}
20820
20822 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20823 SourceLocation ColonLoc, SourceLocation EndLoc,
20824 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20825 ArrayRef<Expr *> UnresolvedReductions) {
20826 ReductionData RD(VarList.size());
20827 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList,
20828 StartLoc, LParenLoc, ColonLoc, EndLoc,
20829 ReductionIdScopeSpec, ReductionId,
20830 UnresolvedReductions, RD))
20831 return nullptr;
20832
20834 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20835 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20836 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
20837 buildPreInits(getASTContext(), RD.ExprCaptures),
20838 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
20839}
20840
20842 SourceLocation LinLoc) {
20843 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
20844 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
20845 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
20846 << getLangOpts().CPlusPlus;
20847 return true;
20848 }
20849 return false;
20850}
20851
20853 OpenMPLinearClauseKind LinKind,
20854 QualType Type, bool IsDeclareSimd) {
20855 const auto *VD = dyn_cast_or_null<VarDecl>(D);
20856 // A variable must not have an incomplete type or a reference type.
20857 if (SemaRef.RequireCompleteType(ELoc, Type,
20858 diag::err_omp_linear_incomplete_type))
20859 return true;
20860 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
20861 !Type->isReferenceType()) {
20862 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
20863 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
20864 return true;
20865 }
20866 Type = Type.getNonReferenceType();
20867
20868 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
20869 // A variable that is privatized must not have a const-qualified type
20870 // unless it is of class type with a mutable member. This restriction does
20871 // not apply to the firstprivate clause, nor to the linear clause on
20872 // declarative directives (like declare simd).
20873 if (!IsDeclareSimd &&
20874 rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc))
20875 return true;
20876
20877 // A list item must be of integral or pointer type.
20878 Type = Type.getUnqualifiedType().getCanonicalType();
20879 const auto *Ty = Type.getTypePtrOrNull();
20880 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
20881 !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) {
20882 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
20883 if (D) {
20884 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20886 Diag(D->getLocation(),
20887 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20888 << D;
20889 }
20890 return true;
20891 }
20892 return false;
20893}
20894
20896 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
20897 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
20898 SourceLocation LinLoc, SourceLocation ColonLoc,
20899 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
20901 SmallVector<Expr *, 8> Privates;
20903 SmallVector<Decl *, 4> ExprCaptures;
20904 SmallVector<Expr *, 4> ExprPostUpdates;
20905 // OpenMP 5.2 [Section 5.4.6, linear clause]
20906 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
20907 // 'ref'
20908 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
20909 getLangOpts().OpenMP >= 52)
20910 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
20911 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
20912 LinKind = OMPC_LINEAR_val;
20913 for (Expr *RefExpr : VarList) {
20914 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20915 SourceLocation ELoc;
20916 SourceRange ERange;
20917 Expr *SimpleRefExpr = RefExpr;
20918 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20919 if (Res.second) {
20920 // It will be analyzed later.
20921 Vars.push_back(RefExpr);
20922 Privates.push_back(nullptr);
20923 Inits.push_back(nullptr);
20924 }
20925 ValueDecl *D = Res.first;
20926 if (!D)
20927 continue;
20928
20929 QualType Type = D->getType();
20930 auto *VD = dyn_cast<VarDecl>(D);
20931
20932 // OpenMP [2.14.3.7, linear clause]
20933 // A list-item cannot appear in more than one linear clause.
20934 // A list-item that appears in a linear clause cannot appear in any
20935 // other data-sharing attribute clause.
20936 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
20937 if (DVar.RefExpr) {
20938 Diag(ELoc, diag::err_omp_wrong_dsa)
20939 << getOpenMPClauseNameForDiag(DVar.CKind)
20940 << getOpenMPClauseNameForDiag(OMPC_linear);
20942 continue;
20943 }
20944
20945 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
20946 continue;
20947 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20948
20949 // Build private copy of original var.
20950 VarDecl *Private =
20951 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
20952 D->hasAttrs() ? &D->getAttrs() : nullptr,
20953 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
20954 DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc);
20955 // Build var to save initial value.
20956 VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start");
20957 Expr *InitExpr;
20958 DeclRefExpr *Ref = nullptr;
20959 if (!VD && !SemaRef.CurContext->isDependentContext()) {
20960 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
20961 if (!isOpenMPCapturedDecl(D)) {
20962 ExprCaptures.push_back(Ref->getDecl());
20963 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20964 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
20965 if (!RefRes.isUsable())
20966 continue;
20967 ExprResult PostUpdateRes =
20968 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
20969 SimpleRefExpr, RefRes.get());
20970 if (!PostUpdateRes.isUsable())
20971 continue;
20972 ExprPostUpdates.push_back(
20973 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
20974 }
20975 }
20976 }
20977 if (LinKind == OMPC_LINEAR_uval)
20978 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
20979 else
20980 InitExpr = VD ? SimpleRefExpr : Ref;
20981 SemaRef.AddInitializerToDecl(
20982 Init, SemaRef.DefaultLvalueConversion(InitExpr).get(),
20983 /*DirectInit=*/false);
20984 DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc);
20985
20986 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
20987 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
20988 ? RefExpr->IgnoreParens()
20989 : Ref);
20990 Privates.push_back(PrivateRef);
20991 Inits.push_back(InitRef);
20992 }
20993
20994 if (Vars.empty())
20995 return nullptr;
20996
20997 Expr *StepExpr = Step;
20998 Expr *CalcStepExpr = nullptr;
20999 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
21000 !Step->isInstantiationDependent() &&
21002 SourceLocation StepLoc = Step->getBeginLoc();
21004 if (Val.isInvalid())
21005 return nullptr;
21006 StepExpr = Val.get();
21007
21008 // Build var to save the step value.
21009 VarDecl *SaveVar =
21010 buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step");
21011 ExprResult SaveRef =
21012 buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc);
21013 ExprResult CalcStep = SemaRef.BuildBinOp(
21014 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr);
21015 CalcStep =
21016 SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue=*/false);
21017
21018 // Warn about zero linear step (it would be probably better specified as
21019 // making corresponding variables 'const').
21020 if (std::optional<llvm::APSInt> Result =
21022 if (!Result->isNegative() && !Result->isStrictlyPositive())
21023 Diag(StepLoc, diag::warn_omp_linear_step_zero)
21024 << Vars[0] << (Vars.size() > 1);
21025 } else if (CalcStep.isUsable()) {
21026 // Calculate the step beforehand instead of doing this on each iteration.
21027 // (This is not used if the number of iterations may be kfold-ed).
21028 CalcStepExpr = CalcStep.get();
21029 }
21030 }
21031
21032 return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind,
21033 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
21034 Vars, Privates, Inits, StepExpr, CalcStepExpr,
21035 buildPreInits(getASTContext(), ExprCaptures),
21036 buildPostUpdate(SemaRef, ExprPostUpdates));
21037}
21038
21040 Expr *NumIterations, Sema &SemaRef,
21041 Scope *S, DSAStackTy *Stack) {
21042 // Walk the vars and build update/final expressions for the CodeGen.
21043 SmallVector<Expr *, 8> Updates;
21045 SmallVector<Expr *, 8> UsedExprs;
21046 Expr *Step = Clause.getStep();
21047 Expr *CalcStep = Clause.getCalcStep();
21048 // OpenMP [2.14.3.7, linear clause]
21049 // If linear-step is not specified it is assumed to be 1.
21050 if (!Step)
21051 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
21052 else if (CalcStep)
21053 Step = cast<BinaryOperator>(CalcStep)->getLHS();
21054 bool HasErrors = false;
21055 auto CurInit = Clause.inits().begin();
21056 auto CurPrivate = Clause.privates().begin();
21057 OpenMPLinearClauseKind LinKind = Clause.getModifier();
21058 for (Expr *RefExpr : Clause.varlist()) {
21059 SourceLocation ELoc;
21060 SourceRange ERange;
21061 Expr *SimpleRefExpr = RefExpr;
21062 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21063 ValueDecl *D = Res.first;
21064 if (Res.second || !D) {
21065 Updates.push_back(nullptr);
21066 Finals.push_back(nullptr);
21067 HasErrors = true;
21068 continue;
21069 }
21070 auto &&Info = Stack->isLoopControlVariable(D);
21071 // OpenMP [2.15.11, distribute simd Construct]
21072 // A list item may not appear in a linear clause, unless it is the loop
21073 // iteration variable.
21074 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
21075 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
21076 SemaRef.Diag(ELoc,
21077 diag::err_omp_linear_distribute_var_non_loop_iteration);
21078 Updates.push_back(nullptr);
21079 Finals.push_back(nullptr);
21080 HasErrors = true;
21081 continue;
21082 }
21083 Expr *InitExpr = *CurInit;
21084
21085 // Build privatized reference to the current linear var.
21086 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
21087 Expr *CapturedRef;
21088 if (LinKind == OMPC_LINEAR_uval)
21089 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
21090 else
21091 CapturedRef =
21092 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
21093 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
21094 /*RefersToCapture=*/true);
21095
21096 // Build update: Var = InitExpr + IV * Step
21098 if (!Info.first)
21100 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
21101 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
21102 else
21103 Update = *CurPrivate;
21104 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
21105 /*DiscardedValue=*/false);
21106
21107 // Build final: Var = PrivCopy;
21108 ExprResult Final;
21109 if (!Info.first)
21110 Final = SemaRef.BuildBinOp(
21111 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
21112 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
21113 else
21114 Final = *CurPrivate;
21115 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
21116 /*DiscardedValue=*/false);
21117
21118 if (!Update.isUsable() || !Final.isUsable()) {
21119 Updates.push_back(nullptr);
21120 Finals.push_back(nullptr);
21121 UsedExprs.push_back(nullptr);
21122 HasErrors = true;
21123 } else {
21124 Updates.push_back(Update.get());
21125 Finals.push_back(Final.get());
21126 if (!Info.first)
21127 UsedExprs.push_back(SimpleRefExpr);
21128 }
21129 ++CurInit;
21130 ++CurPrivate;
21131 }
21132 if (Expr *S = Clause.getStep())
21133 UsedExprs.push_back(S);
21134 // Fill the remaining part with the nullptr.
21135 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
21136 Clause.setUpdates(Updates);
21137 Clause.setFinals(Finals);
21138 Clause.setUsedExprs(UsedExprs);
21139 return HasErrors;
21140}
21141
21143 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
21144 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
21146 for (Expr *RefExpr : VarList) {
21147 assert(RefExpr && "NULL expr in OpenMP aligned clause.");
21148 SourceLocation ELoc;
21149 SourceRange ERange;
21150 Expr *SimpleRefExpr = RefExpr;
21151 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21152 if (Res.second) {
21153 // It will be analyzed later.
21154 Vars.push_back(RefExpr);
21155 }
21156 ValueDecl *D = Res.first;
21157 if (!D)
21158 continue;
21159
21160 QualType QType = D->getType();
21161 auto *VD = dyn_cast<VarDecl>(D);
21162
21163 // OpenMP [2.8.1, simd construct, Restrictions]
21164 // The type of list items appearing in the aligned clause must be
21165 // array, pointer, reference to array, or reference to pointer.
21167 const Type *Ty = QType.getTypePtrOrNull();
21168 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
21169 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
21170 << QType << getLangOpts().CPlusPlus << ERange;
21171 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21173 Diag(D->getLocation(),
21174 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21175 << D;
21176 continue;
21177 }
21178
21179 // OpenMP [2.8.1, simd construct, Restrictions]
21180 // A list-item cannot appear in more than one aligned clause.
21181 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
21182 Diag(ELoc, diag::err_omp_used_in_clause_twice)
21183 << 0 << getOpenMPClauseNameForDiag(OMPC_aligned) << ERange;
21184 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
21185 << getOpenMPClauseNameForDiag(OMPC_aligned);
21186 continue;
21187 }
21188
21189 DeclRefExpr *Ref = nullptr;
21190 if (!VD && isOpenMPCapturedDecl(D))
21191 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
21192 Vars.push_back(SemaRef
21193 .DefaultFunctionArrayConversion(
21194 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
21195 .get());
21196 }
21197
21198 // OpenMP [2.8.1, simd construct, Description]
21199 // The parameter of the aligned clause, alignment, must be a constant
21200 // positive integer expression.
21201 // If no optional parameter is specified, implementation-defined default
21202 // alignments for SIMD instructions on the target platforms are assumed.
21203 if (Alignment != nullptr) {
21204 ExprResult AlignResult =
21205 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
21206 if (AlignResult.isInvalid())
21207 return nullptr;
21208 Alignment = AlignResult.get();
21209 }
21210 if (Vars.empty())
21211 return nullptr;
21212
21213 return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc,
21214 ColonLoc, EndLoc, Vars, Alignment);
21215}
21216
21218 SourceLocation StartLoc,
21219 SourceLocation LParenLoc,
21220 SourceLocation EndLoc) {
21222 SmallVector<Expr *, 8> SrcExprs;
21223 SmallVector<Expr *, 8> DstExprs;
21224 SmallVector<Expr *, 8> AssignmentOps;
21225 for (Expr *RefExpr : VarList) {
21226 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
21227 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21228 // It will be analyzed later.
21229 Vars.push_back(RefExpr);
21230 SrcExprs.push_back(nullptr);
21231 DstExprs.push_back(nullptr);
21232 AssignmentOps.push_back(nullptr);
21233 continue;
21234 }
21235
21236 SourceLocation ELoc = RefExpr->getExprLoc();
21237 // OpenMP [2.1, C/C++]
21238 // A list item is a variable name.
21239 // OpenMP [2.14.4.1, Restrictions, p.1]
21240 // A list item that appears in a copyin clause must be threadprivate.
21241 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
21242 if (!DE || !isa<VarDecl>(DE->getDecl())) {
21243 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
21244 << 0 << RefExpr->getSourceRange();
21245 continue;
21246 }
21247
21248 Decl *D = DE->getDecl();
21249 auto *VD = cast<VarDecl>(D);
21250
21251 QualType Type = VD->getType();
21253 // It will be analyzed later.
21254 Vars.push_back(DE);
21255 SrcExprs.push_back(nullptr);
21256 DstExprs.push_back(nullptr);
21257 AssignmentOps.push_back(nullptr);
21258 continue;
21259 }
21260
21261 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
21262 // A list item that appears in a copyin clause must be threadprivate.
21263 if (!DSAStack->isThreadPrivate(VD)) {
21264 unsigned OMPVersion = getLangOpts().OpenMP;
21265 Diag(ELoc, diag::err_omp_required_access)
21266 << getOpenMPClauseNameForDiag(OMPC_copyin)
21267 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion);
21268 continue;
21269 }
21270
21271 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
21272 // A variable of class type (or array thereof) that appears in a
21273 // copyin clause requires an accessible, unambiguous copy assignment
21274 // operator for the class type.
21275 QualType ElemType =
21277 VarDecl *SrcVD =
21278 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
21279 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
21280 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
21281 SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
21282 VarDecl *DstVD =
21283 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst",
21284 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
21285 DeclRefExpr *PseudoDstExpr =
21286 buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc());
21287 // For arrays generate assignment operation for single element and replace
21288 // it by the original array element in CodeGen.
21289 ExprResult AssignmentOp =
21290 SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
21291 PseudoDstExpr, PseudoSrcExpr);
21292 if (AssignmentOp.isInvalid())
21293 continue;
21294 AssignmentOp =
21295 SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
21296 /*DiscardedValue=*/false);
21297 if (AssignmentOp.isInvalid())
21298 continue;
21299
21300 DSAStack->addDSA(VD, DE, OMPC_copyin);
21301 Vars.push_back(DE);
21302 SrcExprs.push_back(PseudoSrcExpr);
21303 DstExprs.push_back(PseudoDstExpr);
21304 AssignmentOps.push_back(AssignmentOp.get());
21305 }
21306
21307 if (Vars.empty())
21308 return nullptr;
21309
21310 return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21311 Vars, SrcExprs, DstExprs, AssignmentOps);
21312}
21313
21315 SourceLocation StartLoc,
21316 SourceLocation LParenLoc,
21317 SourceLocation EndLoc) {
21319 SmallVector<Expr *, 8> SrcExprs;
21320 SmallVector<Expr *, 8> DstExprs;
21321 SmallVector<Expr *, 8> AssignmentOps;
21322 for (Expr *RefExpr : VarList) {
21323 assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");
21324 SourceLocation ELoc;
21325 SourceRange ERange;
21326 Expr *SimpleRefExpr = RefExpr;
21327 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21328 if (Res.second) {
21329 // It will be analyzed later.
21330 Vars.push_back(RefExpr);
21331 SrcExprs.push_back(nullptr);
21332 DstExprs.push_back(nullptr);
21333 AssignmentOps.push_back(nullptr);
21334 }
21335 ValueDecl *D = Res.first;
21336 if (!D)
21337 continue;
21338
21339 QualType Type = D->getType();
21340 auto *VD = dyn_cast<VarDecl>(D);
21341
21342 // OpenMP [2.14.4.2, Restrictions, p.2]
21343 // A list item that appears in a copyprivate clause may not appear in a
21344 // private or firstprivate clause on the single construct.
21345 if (!VD || !DSAStack->isThreadPrivate(VD)) {
21346 DSAStackTy::DSAVarData DVar =
21347 DSAStack->getTopDSA(D, /*FromParent=*/false);
21348 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
21349 DVar.RefExpr) {
21350 Diag(ELoc, diag::err_omp_wrong_dsa)
21351 << getOpenMPClauseNameForDiag(DVar.CKind)
21352 << getOpenMPClauseNameForDiag(OMPC_copyprivate);
21354 continue;
21355 }
21356
21357 // OpenMP [2.11.4.2, Restrictions, p.1]
21358 // All list items that appear in a copyprivate clause must be either
21359 // threadprivate or private in the enclosing context.
21360 if (DVar.CKind == OMPC_unknown) {
21361 DVar = DSAStack->getImplicitDSA(D, false);
21362 if (DVar.CKind == OMPC_shared) {
21363 Diag(ELoc, diag::err_omp_required_access)
21364 << getOpenMPClauseNameForDiag(OMPC_copyprivate)
21365 << "threadprivate or private in the enclosing context";
21367 continue;
21368 }
21369 }
21370 }
21371
21372 // Variably modified types are not supported.
21374 unsigned OMPVersion = getLangOpts().OpenMP;
21375 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
21376 << getOpenMPClauseNameForDiag(OMPC_copyprivate) << Type
21377 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
21378 OMPVersion);
21379 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21381 Diag(D->getLocation(),
21382 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21383 << D;
21384 continue;
21385 }
21386
21387 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
21388 // A variable of class type (or array thereof) that appears in a
21389 // copyin clause requires an accessible, unambiguous copy assignment
21390 // operator for the class type.
21392 .getBaseElementType(Type.getNonReferenceType())
21394 VarDecl *SrcVD =
21395 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
21396 D->hasAttrs() ? &D->getAttrs() : nullptr);
21397 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc);
21398 VarDecl *DstVD =
21399 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
21400 D->hasAttrs() ? &D->getAttrs() : nullptr);
21401 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
21402 ExprResult AssignmentOp = SemaRef.BuildBinOp(
21403 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
21404 if (AssignmentOp.isInvalid())
21405 continue;
21406 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
21407 /*DiscardedValue=*/false);
21408 if (AssignmentOp.isInvalid())
21409 continue;
21410
21411 // No need to mark vars as copyprivate, they are already threadprivate or
21412 // implicitly private.
21413 assert(VD || isOpenMPCapturedDecl(D));
21414 Vars.push_back(
21415 VD ? RefExpr->IgnoreParens()
21416 : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false));
21417 SrcExprs.push_back(PseudoSrcExpr);
21418 DstExprs.push_back(PseudoDstExpr);
21419 AssignmentOps.push_back(AssignmentOp.get());
21420 }
21421
21422 if (Vars.empty())
21423 return nullptr;
21424
21425 return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc,
21426 EndLoc, Vars, SrcExprs, DstExprs,
21427 AssignmentOps);
21428}
21429
21431 SourceLocation StartLoc,
21432 SourceLocation LParenLoc,
21433 SourceLocation EndLoc) {
21434 if (VarList.empty())
21435 return nullptr;
21436
21437 return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21438 VarList);
21439}
21440
21441/// Tries to find omp_depend_t. type.
21442static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
21443 bool Diagnose = true) {
21444 QualType OMPDependT = Stack->getOMPDependT();
21445 if (!OMPDependT.isNull())
21446 return true;
21447 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
21448 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
21449 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
21450 if (Diagnose)
21451 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
21452 return false;
21453 }
21454 Stack->setOMPDependT(PT.get());
21455 return true;
21456}
21457
21459 SourceLocation StartLoc,
21460 SourceLocation LParenLoc,
21461 SourceLocation EndLoc) {
21462 if (!Depobj)
21463 return nullptr;
21464
21465 bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack);
21466
21467 // OpenMP 5.0, 2.17.10.1 depobj Construct
21468 // depobj is an lvalue expression of type omp_depend_t.
21469 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
21470 !Depobj->isInstantiationDependent() &&
21472 (OMPDependTFound && !getASTContext().typesAreCompatible(
21473 DSAStack->getOMPDependT(), Depobj->getType(),
21474 /*CompareUnqualified=*/true))) {
21475 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21476 << 0 << Depobj->getType() << Depobj->getSourceRange();
21477 }
21478
21479 if (!Depobj->isLValue()) {
21480 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21481 << 1 << Depobj->getSourceRange();
21482 }
21483
21484 return OMPDepobjClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21485 Depobj);
21486}
21487
21488namespace {
21489// Utility struct that gathers the related info for doacross clause.
21490struct DoacrossDataInfoTy {
21491 // The list of expressions.
21493 // The OperatorOffset for doacross loop.
21494 DSAStackTy::OperatorOffsetTy OpsOffs;
21495 // The depended loop count.
21496 llvm::APSInt TotalDepCount;
21497};
21498} // namespace
21499static DoacrossDataInfoTy
21501 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
21502 SourceLocation EndLoc) {
21503
21505 DSAStackTy::OperatorOffsetTy OpsOffs;
21506 llvm::APSInt DepCounter(/*BitWidth=*/32);
21507 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
21508
21509 if (const Expr *OrderedCountExpr =
21510 Stack->getParentOrderedRegionParam().first) {
21511 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
21512 TotalDepCount.setIsUnsigned(/*Val=*/true);
21513 }
21514
21515 for (Expr *RefExpr : VarList) {
21516 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
21517 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21518 // It will be analyzed later.
21519 Vars.push_back(RefExpr);
21520 continue;
21521 }
21522
21523 SourceLocation ELoc = RefExpr->getExprLoc();
21524 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
21525 if (!IsSource) {
21526 if (Stack->getParentOrderedRegionParam().first &&
21527 DepCounter >= TotalDepCount) {
21528 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
21529 continue;
21530 }
21531 ++DepCounter;
21532 // OpenMP [2.13.9, Summary]
21533 // depend(dependence-type : vec), where dependence-type is:
21534 // 'sink' and where vec is the iteration vector, which has the form:
21535 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
21536 // where n is the value specified by the ordered clause in the loop
21537 // directive, xi denotes the loop iteration variable of the i-th nested
21538 // loop associated with the loop directive, and di is a constant
21539 // non-negative integer.
21540 if (SemaRef.CurContext->isDependentContext()) {
21541 // It will be analyzed later.
21542 Vars.push_back(RefExpr);
21543 continue;
21544 }
21545 SimpleExpr = SimpleExpr->IgnoreImplicit();
21547 SourceLocation OOLoc;
21548 Expr *LHS = SimpleExpr;
21549 Expr *RHS = nullptr;
21550 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
21551 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
21552 OOLoc = BO->getOperatorLoc();
21553 LHS = BO->getLHS()->IgnoreParenImpCasts();
21554 RHS = BO->getRHS()->IgnoreParenImpCasts();
21555 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
21556 OOK = OCE->getOperator();
21557 OOLoc = OCE->getOperatorLoc();
21558 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
21559 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
21560 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
21561 OOK = MCE->getMethodDecl()
21562 ->getNameInfo()
21563 .getName()
21564 .getCXXOverloadedOperator();
21565 OOLoc = MCE->getCallee()->getExprLoc();
21566 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
21567 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
21568 }
21569 SourceLocation ELoc;
21570 SourceRange ERange;
21571 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
21572 if (Res.second) {
21573 // It will be analyzed later.
21574 Vars.push_back(RefExpr);
21575 }
21576 ValueDecl *D = Res.first;
21577 if (!D)
21578 continue;
21579
21580 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
21581 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
21582 continue;
21583 }
21584 if (RHS) {
21585 ExprResult RHSRes =
21587 RHS, OMPC_depend, /*StrictlyPositive=*/false);
21588 if (RHSRes.isInvalid())
21589 continue;
21590 }
21591 if (!SemaRef.CurContext->isDependentContext() &&
21592 Stack->getParentOrderedRegionParam().first &&
21593 DepCounter != Stack->isParentLoopControlVariable(D).first) {
21594 const ValueDecl *VD =
21595 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
21596 if (VD)
21597 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21598 << 1 << VD;
21599 else
21600 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21601 << 0;
21602 continue;
21603 }
21604 OpsOffs.emplace_back(RHS, OOK);
21605 }
21606 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21607 }
21608 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
21609 TotalDepCount > VarList.size() &&
21610 Stack->getParentOrderedRegionParam().first &&
21611 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
21612 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
21613 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
21614 }
21615 return {Vars, OpsOffs, TotalDepCount};
21616}
21617
21619 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
21620 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
21621 SourceLocation EndLoc) {
21622 OpenMPDependClauseKind DepKind = Data.DepKind;
21623 SourceLocation DepLoc = Data.DepLoc;
21624 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
21625 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
21626 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21627 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_depend);
21628 return nullptr;
21629 }
21630 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
21631 DepKind == OMPC_DEPEND_mutexinoutset) {
21632 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
21633 return nullptr;
21634 }
21635 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
21636 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21637 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
21638 DepKind == OMPC_DEPEND_sink ||
21639 ((getLangOpts().OpenMP < 50 ||
21640 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21641 DepKind == OMPC_DEPEND_depobj))) {
21642 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
21643 OMPC_DEPEND_outallmemory,
21644 OMPC_DEPEND_inoutallmemory};
21645 if (getLangOpts().OpenMP < 50 ||
21646 DSAStack->getCurrentDirective() == OMPD_depobj)
21647 Except.push_back(OMPC_DEPEND_depobj);
21648 if (getLangOpts().OpenMP < 51)
21649 Except.push_back(OMPC_DEPEND_inoutset);
21650 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
21651 ? "depend modifier(iterator) or "
21652 : "";
21653 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21654 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
21655 /*Last=*/OMPC_DEPEND_unknown,
21656 Except)
21657 << getOpenMPClauseNameForDiag(OMPC_depend);
21658 return nullptr;
21659 }
21660 if (DepModifier &&
21661 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
21662 Diag(DepModifier->getExprLoc(),
21663 diag::err_omp_depend_sink_source_with_modifier);
21664 return nullptr;
21665 }
21666 if (DepModifier &&
21667 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
21668 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
21669
21671 DSAStackTy::OperatorOffsetTy OpsOffs;
21672 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
21673
21674 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
21675 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
21676 SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
21677 Vars = VarOffset.Vars;
21678 OpsOffs = VarOffset.OpsOffs;
21679 TotalDepCount = VarOffset.TotalDepCount;
21680 } else {
21681 for (Expr *RefExpr : VarList) {
21682 assert(RefExpr && "NULL expr in OpenMP depend clause.");
21683 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21684 // It will be analyzed later.
21685 Vars.push_back(RefExpr);
21686 continue;
21687 }
21688
21689 SourceLocation ELoc = RefExpr->getExprLoc();
21690 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
21691 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
21692 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
21693 if (OMPDependTFound)
21694 OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack,
21695 DepKind == OMPC_DEPEND_depobj);
21696 if (DepKind == OMPC_DEPEND_depobj) {
21697 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21698 // List items used in depend clauses with the depobj dependence type
21699 // must be expressions of the omp_depend_t type.
21700 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21701 !RefExpr->isInstantiationDependent() &&
21702 !RefExpr->containsUnexpandedParameterPack() &&
21703 (OMPDependTFound &&
21704 !getASTContext().hasSameUnqualifiedType(
21705 DSAStack->getOMPDependT(), RefExpr->getType()))) {
21706 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21707 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
21708 continue;
21709 }
21710 if (!RefExpr->isLValue()) {
21711 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21712 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
21713 continue;
21714 }
21715 } else {
21716 // OpenMP 5.0 [2.17.11, Restrictions]
21717 // List items used in depend clauses cannot be zero-length array
21718 // sections.
21719 QualType ExprTy = RefExpr->getType().getNonReferenceType();
21720 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
21721 if (OASE) {
21722 QualType BaseType =
21724 if (BaseType.isNull())
21725 return nullptr;
21726 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21727 ExprTy = ATy->getElementType();
21728 else
21729 ExprTy = BaseType->getPointeeType();
21730 if (BaseType.isNull() || ExprTy.isNull())
21731 return nullptr;
21732 ExprTy = ExprTy.getNonReferenceType();
21733 const Expr *Length = OASE->getLength();
21735 if (Length && !Length->isValueDependent() &&
21736 Length->EvaluateAsInt(Result, getASTContext()) &&
21737 Result.Val.getInt().isZero()) {
21738 Diag(ELoc,
21739 diag::err_omp_depend_zero_length_array_section_not_allowed)
21740 << SimpleExpr->getSourceRange();
21741 continue;
21742 }
21743 }
21744
21745 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21746 // List items used in depend clauses with the in, out, inout,
21747 // inoutset, or mutexinoutset dependence types cannot be
21748 // expressions of the omp_depend_t type.
21749 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21750 !RefExpr->isInstantiationDependent() &&
21751 !RefExpr->containsUnexpandedParameterPack() &&
21752 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
21753 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
21754 ExprTy.getTypePtr()))) {
21755 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21756 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21757 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21758 << RefExpr->getSourceRange();
21759 continue;
21760 }
21761
21762 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
21763 if (ASE && !ASE->getBase()->isTypeDependent() &&
21764 !ASE->getBase()
21765 ->getType()
21766 .getNonReferenceType()
21767 ->isPointerType() &&
21768 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
21769 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21770 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21771 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21772 << RefExpr->getSourceRange();
21773 continue;
21774 }
21775
21776 ExprResult Res;
21777 {
21779 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
21780 RefExpr->IgnoreParenImpCasts());
21781 }
21782 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
21784 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21785 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21786 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21787 << RefExpr->getSourceRange();
21788 continue;
21789 }
21790 }
21791 }
21792 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21793 }
21794 }
21795
21796 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
21797 DepKind != OMPC_DEPEND_outallmemory &&
21798 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
21799 return nullptr;
21800
21801 auto *C = OMPDependClause::Create(
21802 getASTContext(), StartLoc, LParenLoc, EndLoc,
21803 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
21804 TotalDepCount.getZExtValue());
21805 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
21806 DSAStack->isParentOrderedRegion())
21807 DSAStack->addDoacrossDependClause(C, OpsOffs);
21808 return C;
21809}
21810
21813 SourceLocation LParenLoc, SourceLocation ModifierLoc,
21814 SourceLocation EndLoc) {
21815 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
21816 "Unexpected device modifier in OpenMP < 50.");
21817
21818 bool ErrorFound = false;
21819 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
21820 std::string Values =
21821 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
21822 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21823 << Values << getOpenMPClauseNameForDiag(OMPC_device);
21824 ErrorFound = true;
21825 }
21826
21827 Expr *ValExpr = Device;
21828 Stmt *HelperValStmt = nullptr;
21829
21830 // OpenMP [2.9.1, Restrictions]
21831 // The device expression must evaluate to a non-negative integer value.
21832 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device,
21833 /*StrictlyPositive=*/false) ||
21834 ErrorFound;
21835 if (ErrorFound)
21836 return nullptr;
21837
21838 // OpenMP 5.0 [2.12.5, Restrictions]
21839 // In case of ancestor device-modifier, a requires directive with
21840 // the reverse_offload clause must be specified.
21841 if (Modifier == OMPC_DEVICE_ancestor) {
21842 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
21843 SemaRef.targetDiag(
21844 StartLoc,
21845 diag::err_omp_device_ancestor_without_requires_reverse_offload);
21846 ErrorFound = true;
21847 }
21848 }
21849
21850 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
21851 OpenMPDirectiveKind CaptureRegion =
21852 getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP);
21853 if (CaptureRegion != OMPD_unknown &&
21854 !SemaRef.CurContext->isDependentContext()) {
21855 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
21856 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21857 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
21858 HelperValStmt = buildPreInits(getASTContext(), Captures);
21859 }
21860
21861 return new (getASTContext())
21862 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
21863 LParenLoc, ModifierLoc, EndLoc);
21864}
21865
21867 DSAStackTy *Stack, QualType QTy,
21868 bool FullCheck = true) {
21869 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
21870 return false;
21871 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
21872 !QTy.isTriviallyCopyableType(SemaRef.Context))
21873 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
21874 return true;
21875}
21876
21877/// Return true if it can be proven that the provided array expression
21878/// (array section or array subscript) does NOT specify the whole size of the
21879/// array whose base type is \a BaseQTy.
21881 const Expr *E,
21882 QualType BaseQTy) {
21883 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21884
21885 // If this is an array subscript, it refers to the whole size if the size of
21886 // the dimension is constant and equals 1. Also, an array section assumes the
21887 // format of an array subscript if no colon is used.
21888 if (isa<ArraySubscriptExpr>(E) ||
21889 (OASE && OASE->getColonLocFirst().isInvalid())) {
21890 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21891 return ATy->getSExtSize() != 1;
21892 // Size can't be evaluated statically.
21893 return false;
21894 }
21895
21896 assert(OASE && "Expecting array section if not an array subscript.");
21897 const Expr *LowerBound = OASE->getLowerBound();
21898 const Expr *Length = OASE->getLength();
21899
21900 // If there is a lower bound that does not evaluates to zero, we are not
21901 // covering the whole dimension.
21902 if (LowerBound) {
21903 Expr::EvalResult Result;
21904 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
21905 return false; // Can't get the integer value as a constant.
21906
21907 llvm::APSInt ConstLowerBound = Result.Val.getInt();
21908 if (ConstLowerBound.getSExtValue())
21909 return true;
21910 }
21911
21912 // If we don't have a length we covering the whole dimension.
21913 if (!Length)
21914 return false;
21915
21916 // If the base is a pointer, we don't have a way to get the size of the
21917 // pointee.
21918 if (BaseQTy->isPointerType())
21919 return false;
21920
21921 // We can only check if the length is the same as the size of the dimension
21922 // if we have a constant array.
21923 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
21924 if (!CATy)
21925 return false;
21926
21927 Expr::EvalResult Result;
21928 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21929 return false; // Can't get the integer value as a constant.
21930
21931 llvm::APSInt ConstLength = Result.Val.getInt();
21932 return CATy->getSExtSize() != ConstLength.getSExtValue();
21933}
21934
21935// Return true if it can be proven that the provided array expression (array
21936// section or array subscript) does NOT specify a single element of the array
21937// whose base type is \a BaseQTy.
21939 const Expr *E,
21940 QualType BaseQTy) {
21941 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21942
21943 // An array subscript always refer to a single element. Also, an array section
21944 // assumes the format of an array subscript if no colon is used.
21945 if (isa<ArraySubscriptExpr>(E) ||
21946 (OASE && OASE->getColonLocFirst().isInvalid()))
21947 return false;
21948
21949 assert(OASE && "Expecting array section if not an array subscript.");
21950 const Expr *Length = OASE->getLength();
21951
21952 // If we don't have a length we have to check if the array has unitary size
21953 // for this dimension. Also, we should always expect a length if the base type
21954 // is pointer.
21955 if (!Length) {
21956 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21957 return ATy->getSExtSize() != 1;
21958 // We cannot assume anything.
21959 return false;
21960 }
21961
21962 // Check if the length evaluates to 1.
21963 Expr::EvalResult Result;
21964 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21965 return false; // Can't get the integer value as a constant.
21966
21967 llvm::APSInt ConstLength = Result.Val.getInt();
21968 return ConstLength.getSExtValue() != 1;
21969}
21970
21971// The base of elements of list in a map clause have to be either:
21972// - a reference to variable or field.
21973// - a member expression.
21974// - an array expression.
21975//
21976// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
21977// reference to 'r'.
21978//
21979// If we have:
21980//
21981// struct SS {
21982// Bla S;
21983// foo() {
21984// #pragma omp target map (S.Arr[:12]);
21985// }
21986// }
21987//
21988// We want to retrieve the member expression 'this->S';
21989
21990// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
21991// If a list item is an array section, it must specify contiguous storage.
21992//
21993// For this restriction it is sufficient that we make sure only references
21994// to variables or fields and array expressions, and that no array sections
21995// exist except in the rightmost expression (unless they cover the whole
21996// dimension of the array). E.g. these would be invalid:
21997//
21998// r.ArrS[3:5].Arr[6:7]
21999//
22000// r.ArrS[3:5].x
22001//
22002// but these would be valid:
22003// r.ArrS[3].Arr[6:7]
22004//
22005// r.ArrS[3].x
22006namespace {
22007class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
22008 Sema &SemaRef;
22009 OpenMPClauseKind CKind = OMPC_unknown;
22010 OpenMPDirectiveKind DKind = OMPD_unknown;
22012 bool IsNonContiguous = false;
22013 bool NoDiagnose = false;
22014 const Expr *RelevantExpr = nullptr;
22015 bool AllowUnitySizeArraySection = true;
22016 bool AllowWholeSizeArraySection = true;
22017 bool AllowAnotherPtr = true;
22018 SourceLocation ELoc;
22019 SourceRange ERange;
22020
22021 void emitErrorMsg() {
22022 // If nothing else worked, this is not a valid map clause expression.
22023 if (SemaRef.getLangOpts().OpenMP < 50) {
22024 SemaRef.Diag(ELoc,
22025 diag::err_omp_expected_named_var_member_or_array_expression)
22026 << ERange;
22027 } else {
22028 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22029 << getOpenMPClauseNameForDiag(CKind) << ERange;
22030 }
22031 }
22032
22033public:
22034 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
22035 if (!isa<VarDecl>(DRE->getDecl())) {
22036 emitErrorMsg();
22037 return false;
22038 }
22039 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22040 RelevantExpr = DRE;
22041 // Record the component.
22042 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
22043 return true;
22044 }
22045
22046 bool VisitMemberExpr(MemberExpr *ME) {
22047 Expr *E = ME;
22048 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
22049
22050 if (isa<CXXThisExpr>(BaseE)) {
22051 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22052 // We found a base expression: this->Val.
22053 RelevantExpr = ME;
22054 } else {
22055 E = BaseE;
22056 }
22057
22058 if (!isa<FieldDecl>(ME->getMemberDecl())) {
22059 if (!NoDiagnose) {
22060 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
22061 << ME->getSourceRange();
22062 return false;
22063 }
22064 if (RelevantExpr)
22065 return false;
22066 return Visit(E);
22067 }
22068
22069 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
22070
22071 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
22072 // A bit-field cannot appear in a map clause.
22073 //
22074 if (FD->isBitField()) {
22075 if (!NoDiagnose) {
22076 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
22077 << ME->getSourceRange() << getOpenMPClauseNameForDiag(CKind);
22078 return false;
22079 }
22080 if (RelevantExpr)
22081 return false;
22082 return Visit(E);
22083 }
22084
22085 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22086 // If the type of a list item is a reference to a type T then the type
22087 // will be considered to be T for all purposes of this clause.
22088 QualType CurType = BaseE->getType().getNonReferenceType();
22089
22090 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
22091 // A list item cannot be a variable that is a member of a structure with
22092 // a union type.
22093 //
22094 if (CurType->isUnionType()) {
22095 if (!NoDiagnose) {
22096 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
22097 << ME->getSourceRange();
22098 return false;
22099 }
22100 return RelevantExpr || Visit(E);
22101 }
22102
22103 // If we got a member expression, we should not expect any array section
22104 // before that:
22105 //
22106 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
22107 // If a list item is an element of a structure, only the rightmost symbol
22108 // of the variable reference can be an array section.
22109 //
22110 AllowUnitySizeArraySection = false;
22111 AllowWholeSizeArraySection = false;
22112
22113 // Record the component.
22114 Components.emplace_back(ME, FD, IsNonContiguous);
22115 return RelevantExpr || Visit(E);
22116 }
22117
22118 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
22119 Expr *E = AE->getBase()->IgnoreParenImpCasts();
22120
22121 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
22122 if (!NoDiagnose) {
22123 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22124 << 0 << AE->getSourceRange();
22125 return false;
22126 }
22127 return RelevantExpr || Visit(E);
22128 }
22129
22130 // If we got an array subscript that express the whole dimension we
22131 // can have any array expressions before. If it only expressing part of
22132 // the dimension, we can only have unitary-size array expressions.
22134 AllowWholeSizeArraySection = false;
22135
22136 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
22137 Expr::EvalResult Result;
22138 if (!AE->getIdx()->isValueDependent() &&
22139 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
22140 !Result.Val.getInt().isZero()) {
22141 SemaRef.Diag(AE->getIdx()->getExprLoc(),
22142 diag::err_omp_invalid_map_this_expr);
22143 SemaRef.Diag(AE->getIdx()->getExprLoc(),
22144 diag::note_omp_invalid_subscript_on_this_ptr_map);
22145 }
22146 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22147 RelevantExpr = TE;
22148 }
22149
22150 // Record the component - we don't have any declaration associated.
22151 Components.emplace_back(AE, nullptr, IsNonContiguous);
22152
22153 return RelevantExpr || Visit(E);
22154 }
22155
22156 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
22157 // After OMP 5.0 Array section in reduction clause will be implicitly
22158 // mapped
22159 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
22160 "Array sections cannot be implicitly mapped.");
22161 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
22162 QualType CurType =
22164
22165 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22166 // If the type of a list item is a reference to a type T then the type
22167 // will be considered to be T for all purposes of this clause.
22168 if (CurType->isReferenceType())
22169 CurType = CurType->getPointeeType();
22170
22171 bool IsPointer = CurType->isAnyPointerType();
22172
22173 if (!IsPointer && !CurType->isArrayType()) {
22174 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22175 << 0 << OASE->getSourceRange();
22176 return false;
22177 }
22178
22179 bool NotWhole =
22180 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
22181 bool NotUnity =
22182 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
22183
22184 if (AllowWholeSizeArraySection) {
22185 // Any array section is currently allowed. Allowing a whole size array
22186 // section implies allowing a unity array section as well.
22187 //
22188 // If this array section refers to the whole dimension we can still
22189 // accept other array sections before this one, except if the base is a
22190 // pointer. Otherwise, only unitary sections are accepted.
22191 if (NotWhole || IsPointer)
22192 AllowWholeSizeArraySection = false;
22193 } else if (DKind == OMPD_target_update &&
22194 SemaRef.getLangOpts().OpenMP >= 50) {
22195 if (IsPointer && !AllowAnotherPtr)
22196 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
22197 << /*array of unknown bound */ 1;
22198 else
22199 IsNonContiguous = true;
22200 } else if (AllowUnitySizeArraySection && NotUnity) {
22201 // A unity or whole array section is not allowed and that is not
22202 // compatible with the properties of the current array section.
22203 if (NoDiagnose)
22204 return false;
22205 SemaRef.Diag(ELoc,
22206 diag::err_array_section_does_not_specify_contiguous_storage)
22207 << OASE->getSourceRange();
22208 return false;
22209 }
22210
22211 if (IsPointer)
22212 AllowAnotherPtr = false;
22213
22214 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
22215 Expr::EvalResult ResultR;
22216 Expr::EvalResult ResultL;
22217 if (!OASE->getLength()->isValueDependent() &&
22218 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
22219 !ResultR.Val.getInt().isOne()) {
22220 SemaRef.Diag(OASE->getLength()->getExprLoc(),
22221 diag::err_omp_invalid_map_this_expr);
22222 SemaRef.Diag(OASE->getLength()->getExprLoc(),
22223 diag::note_omp_invalid_length_on_this_ptr_mapping);
22224 }
22225 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
22226 OASE->getLowerBound()->EvaluateAsInt(ResultL,
22227 SemaRef.getASTContext()) &&
22228 !ResultL.Val.getInt().isZero()) {
22229 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
22230 diag::err_omp_invalid_map_this_expr);
22231 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
22232 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
22233 }
22234 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22235 RelevantExpr = TE;
22236 }
22237
22238 // Record the component - we don't have any declaration associated.
22239 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
22240 return RelevantExpr || Visit(E);
22241 }
22242 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
22243 Expr *Base = E->getBase();
22244
22245 // Record the component - we don't have any declaration associated.
22246 Components.emplace_back(E, nullptr, IsNonContiguous);
22247
22248 return Visit(Base->IgnoreParenImpCasts());
22249 }
22250
22251 bool VisitUnaryOperator(UnaryOperator *UO) {
22252 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
22253 UO->getOpcode() != UO_Deref) {
22254 emitErrorMsg();
22255 return false;
22256 }
22257 if (!RelevantExpr) {
22258 // Record the component if haven't found base decl.
22259 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
22260 }
22261 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
22262 }
22263 bool VisitBinaryOperator(BinaryOperator *BO) {
22264 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
22265 emitErrorMsg();
22266 return false;
22267 }
22268
22269 // Pointer arithmetic is the only thing we expect to happen here so after we
22270 // make sure the binary operator is a pointer type, the only thing we need
22271 // to do is to visit the subtree that has the same type as root (so that we
22272 // know the other subtree is just an offset)
22273 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
22274 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
22275 Components.emplace_back(BO, nullptr, false);
22276 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
22277 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
22278 "Either LHS or RHS have base decl inside");
22279 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
22280 return RelevantExpr || Visit(LE);
22281 return RelevantExpr || Visit(RE);
22282 }
22283 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
22284 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22285 RelevantExpr = CTE;
22286 Components.emplace_back(CTE, nullptr, IsNonContiguous);
22287 return true;
22288 }
22289 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
22290 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22291 Components.emplace_back(COCE, nullptr, IsNonContiguous);
22292 return true;
22293 }
22294 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
22295 Expr *Source = E->getSourceExpr();
22296 if (!Source) {
22297 emitErrorMsg();
22298 return false;
22299 }
22300 return Visit(Source);
22301 }
22302 bool VisitStmt(Stmt *) {
22303 emitErrorMsg();
22304 return false;
22305 }
22306 const Expr *getFoundBase() const { return RelevantExpr; }
22307 explicit MapBaseChecker(
22308 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
22310 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
22311 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
22312 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
22313};
22314} // namespace
22315
22316/// Return the expression of the base of the mappable expression or null if it
22317/// cannot be determined and do all the necessary checks to see if the
22318/// expression is valid as a standalone mappable expression. In the process,
22319/// record all the components of the expression.
22321 Sema &SemaRef, Expr *E,
22323 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
22324 SourceLocation ELoc = E->getExprLoc();
22325 SourceRange ERange = E->getSourceRange();
22326 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
22327 ERange);
22328 if (Checker.Visit(E->IgnoreParens())) {
22329 // Check if the highest dimension array section has length specified
22330 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
22331 (CKind == OMPC_to || CKind == OMPC_from)) {
22332 auto CI = CurComponents.rbegin();
22333 auto CE = CurComponents.rend();
22334 for (; CI != CE; ++CI) {
22335 const auto *OASE =
22336 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
22337 if (!OASE)
22338 continue;
22339 if (OASE && OASE->getLength())
22340 break;
22341 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
22342 << ERange;
22343 }
22344 }
22345 return Checker.getFoundBase();
22346 }
22347 return nullptr;
22348}
22349
22350// Return true if expression E associated with value VD has conflicts with other
22351// map information.
22353 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
22354 bool CurrentRegionOnly,
22356 OpenMPClauseKind CKind) {
22357 assert(VD && E);
22358 SourceLocation ELoc = E->getExprLoc();
22359 SourceRange ERange = E->getSourceRange();
22360
22361 // In order to easily check the conflicts we need to match each component of
22362 // the expression under test with the components of the expressions that are
22363 // already in the stack.
22364
22365 assert(!CurComponents.empty() && "Map clause expression with no components!");
22366 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
22367 "Map clause expression with unexpected base!");
22368
22369 // Variables to help detecting enclosing problems in data environment nests.
22370 bool IsEnclosedByDataEnvironmentExpr = false;
22371 const Expr *EnclosingExpr = nullptr;
22372
22373 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
22374 VD, CurrentRegionOnly,
22375 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
22376 ERange, CKind, &EnclosingExpr,
22378 StackComponents,
22379 OpenMPClauseKind Kind) {
22380 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
22381 return false;
22382 assert(!StackComponents.empty() &&
22383 "Map clause expression with no components!");
22384 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
22385 "Map clause expression with unexpected base!");
22386 (void)VD;
22387
22388 // The whole expression in the stack.
22389 const Expr *RE = StackComponents.front().getAssociatedExpression();
22390
22391 // Expressions must start from the same base. Here we detect at which
22392 // point both expressions diverge from each other and see if we can
22393 // detect if the memory referred to both expressions is contiguous and
22394 // do not overlap.
22395 auto CI = CurComponents.rbegin();
22396 auto CE = CurComponents.rend();
22397 auto SI = StackComponents.rbegin();
22398 auto SE = StackComponents.rend();
22399 for (; CI != CE && SI != SE; ++CI, ++SI) {
22400
22401 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
22402 // At most one list item can be an array item derived from a given
22403 // variable in map clauses of the same construct.
22404 if (CurrentRegionOnly &&
22405 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
22406 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
22407 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
22408 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
22409 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
22410 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
22411 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
22412 diag::err_omp_multiple_array_items_in_map_clause)
22413 << CI->getAssociatedExpression()->getSourceRange();
22414 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
22415 diag::note_used_here)
22416 << SI->getAssociatedExpression()->getSourceRange();
22417 return true;
22418 }
22419
22420 // Do both expressions have the same kind?
22421 if (CI->getAssociatedExpression()->getStmtClass() !=
22422 SI->getAssociatedExpression()->getStmtClass())
22423 break;
22424
22425 // Are we dealing with different variables/fields?
22426 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
22427 break;
22428 }
22429 // Check if the extra components of the expressions in the enclosing
22430 // data environment are redundant for the current base declaration.
22431 // If they are, the maps completely overlap, which is legal.
22432 for (; SI != SE; ++SI) {
22433 QualType Type;
22434 if (const auto *ASE =
22435 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
22436 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
22437 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
22438 SI->getAssociatedExpression())) {
22439 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
22441 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
22442 SI->getAssociatedExpression())) {
22443 Type = OASE->getBase()->getType()->getPointeeType();
22444 }
22445 if (Type.isNull() || Type->isAnyPointerType() ||
22447 SemaRef, SI->getAssociatedExpression(), Type))
22448 break;
22449 }
22450
22451 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
22452 // List items of map clauses in the same construct must not share
22453 // original storage.
22454 //
22455 // If the expressions are exactly the same or one is a subset of the
22456 // other, it means they are sharing storage.
22457 if (CI == CE && SI == SE) {
22458 if (CurrentRegionOnly) {
22459 if (CKind == OMPC_map) {
22460 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22461 } else {
22462 assert(CKind == OMPC_to || CKind == OMPC_from);
22463 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22464 << ERange;
22465 }
22466 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22467 << RE->getSourceRange();
22468 return true;
22469 }
22470 // If we find the same expression in the enclosing data environment,
22471 // that is legal.
22472 IsEnclosedByDataEnvironmentExpr = true;
22473 return false;
22474 }
22475
22476 QualType DerivedType =
22477 std::prev(CI)->getAssociatedDeclaration()->getType();
22478 SourceLocation DerivedLoc =
22479 std::prev(CI)->getAssociatedExpression()->getExprLoc();
22480
22481 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22482 // If the type of a list item is a reference to a type T then the type
22483 // will be considered to be T for all purposes of this clause.
22484 DerivedType = DerivedType.getNonReferenceType();
22485
22486 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
22487 // A variable for which the type is pointer and an array section
22488 // derived from that variable must not appear as list items of map
22489 // clauses of the same construct.
22490 //
22491 // Also, cover one of the cases in:
22492 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
22493 // If any part of the original storage of a list item has corresponding
22494 // storage in the device data environment, all of the original storage
22495 // must have corresponding storage in the device data environment.
22496 //
22497 if (DerivedType->isAnyPointerType()) {
22498 if (CI == CE || SI == SE) {
22499 SemaRef.Diag(
22500 DerivedLoc,
22501 diag::err_omp_pointer_mapped_along_with_derived_section)
22502 << DerivedLoc;
22503 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22504 << RE->getSourceRange();
22505 return true;
22506 }
22507 if (CI->getAssociatedExpression()->getStmtClass() !=
22508 SI->getAssociatedExpression()->getStmtClass() ||
22509 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
22510 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
22511 assert(CI != CE && SI != SE);
22512 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
22513 << DerivedLoc;
22514 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22515 << RE->getSourceRange();
22516 return true;
22517 }
22518 }
22519
22520 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
22521 // List items of map clauses in the same construct must not share
22522 // original storage.
22523 //
22524 // An expression is a subset of the other.
22525 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
22526 if (CKind == OMPC_map) {
22527 if (CI != CE || SI != SE) {
22528 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
22529 // a pointer.
22530 auto Begin =
22531 CI != CE ? CurComponents.begin() : StackComponents.begin();
22532 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
22533 auto It = Begin;
22534 while (It != End && !It->getAssociatedDeclaration())
22535 std::advance(It, 1);
22536 assert(It != End &&
22537 "Expected at least one component with the declaration.");
22538 if (It != Begin && It->getAssociatedDeclaration()
22539 ->getType()
22540 .getCanonicalType()
22541 ->isAnyPointerType()) {
22542 IsEnclosedByDataEnvironmentExpr = false;
22543 EnclosingExpr = nullptr;
22544 return false;
22545 }
22546 }
22547 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22548 } else {
22549 assert(CKind == OMPC_to || CKind == OMPC_from);
22550 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22551 << ERange;
22552 }
22553 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22554 << RE->getSourceRange();
22555 return true;
22556 }
22557
22558 // The current expression uses the same base as other expression in the
22559 // data environment but does not contain it completely.
22560 if (!CurrentRegionOnly && SI != SE)
22561 EnclosingExpr = RE;
22562
22563 // The current expression is a subset of the expression in the data
22564 // environment.
22565 IsEnclosedByDataEnvironmentExpr |=
22566 (!CurrentRegionOnly && CI != CE && SI == SE);
22567
22568 return false;
22569 });
22570
22571 if (CurrentRegionOnly)
22572 return FoundError;
22573
22574 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
22575 // If any part of the original storage of a list item has corresponding
22576 // storage in the device data environment, all of the original storage must
22577 // have corresponding storage in the device data environment.
22578 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
22579 // If a list item is an element of a structure, and a different element of
22580 // the structure has a corresponding list item in the device data environment
22581 // prior to a task encountering the construct associated with the map clause,
22582 // then the list item must also have a corresponding list item in the device
22583 // data environment prior to the task encountering the construct.
22584 //
22585 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
22586 SemaRef.Diag(ELoc,
22587 diag::err_omp_original_storage_is_shared_and_does_not_contain)
22588 << ERange;
22589 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
22590 << EnclosingExpr->getSourceRange();
22591 return true;
22592 }
22593
22594 return FoundError;
22595}
22596
22597// Look up the user-defined mapper given the mapper name and mapped type, and
22598// build a reference to it.
22600 CXXScopeSpec &MapperIdScopeSpec,
22601 const DeclarationNameInfo &MapperId,
22602 QualType Type,
22603 Expr *UnresolvedMapper) {
22604 if (MapperIdScopeSpec.isInvalid())
22605 return ExprError();
22606 // Get the actual type for the array type.
22607 if (Type->isArrayType()) {
22608 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
22610 }
22611 // Find all user-defined mappers with the given MapperId.
22612 SmallVector<UnresolvedSet<8>, 4> Lookups;
22613 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
22614 Lookup.suppressDiagnostics();
22615 if (S) {
22616 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
22617 /*ObjectType=*/QualType())) {
22618 NamedDecl *D = Lookup.getRepresentativeDecl();
22619 while (S && !S->isDeclScope(D))
22620 S = S->getParent();
22621 if (S)
22622 S = S->getParent();
22623 Lookups.emplace_back();
22624 Lookups.back().append(Lookup.begin(), Lookup.end());
22625 Lookup.clear();
22626 }
22627 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
22628 // Extract the user-defined mappers with the given MapperId.
22629 Lookups.push_back(UnresolvedSet<8>());
22630 for (NamedDecl *D : ULE->decls()) {
22631 auto *DMD = cast<OMPDeclareMapperDecl>(D);
22632 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
22633 Lookups.back().addDecl(DMD);
22634 }
22635 }
22636 // Defer the lookup for dependent types. The results will be passed through
22637 // UnresolvedMapper on instantiation.
22638 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
22642 return !D->isInvalidDecl() &&
22643 (D->getType()->isDependentType() ||
22644 D->getType()->isInstantiationDependentType() ||
22645 D->getType()->containsUnexpandedParameterPack());
22646 })) {
22647 UnresolvedSet<8> URS;
22648 for (const UnresolvedSet<8> &Set : Lookups) {
22649 if (Set.empty())
22650 continue;
22651 URS.append(Set.begin(), Set.end());
22652 }
22654 SemaRef.Context, /*NamingClass=*/nullptr,
22655 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
22656 /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false,
22657 /*KnownInstantiationDependent=*/false);
22658 }
22659 SourceLocation Loc = MapperId.getLoc();
22660 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22661 // The type must be of struct, union or class type in C and C++
22663 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
22664 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
22665 return ExprError();
22666 }
22667 // Perform argument dependent lookup.
22668 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
22669 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
22670 // Return the first user-defined mapper with the desired type.
22672 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
22673 if (!D->isInvalidDecl() &&
22674 SemaRef.Context.hasSameType(D->getType(), Type))
22675 return D;
22676 return nullptr;
22677 }))
22678 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
22679 // Find the first user-defined mapper with a type derived from the desired
22680 // type.
22682 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
22683 if (!D->isInvalidDecl() &&
22684 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
22685 !Type.isMoreQualifiedThan(D->getType(),
22686 SemaRef.getASTContext()))
22687 return D;
22688 return nullptr;
22689 })) {
22690 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
22691 /*DetectVirtual=*/false);
22692 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
22693 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
22694 VD->getType().getUnqualifiedType()))) {
22695 if (SemaRef.CheckBaseClassAccess(
22696 Loc, VD->getType(), Type, Paths.front(),
22697 /*DiagID=*/0) != Sema::AR_inaccessible) {
22698 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
22699 }
22700 }
22701 }
22702 }
22703 // Report error if a mapper is specified, but cannot be found.
22704 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
22705 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
22706 << Type << MapperId.getName();
22707 return ExprError();
22708 }
22709 return ExprEmpty();
22710}
22711
22712namespace {
22713// Utility struct that gathers all the related lists associated with a mappable
22714// expression.
22715struct MappableVarListInfo {
22716 // The list of expressions.
22717 ArrayRef<Expr *> VarList;
22718 // The list of processed expressions.
22719 SmallVector<Expr *, 16> ProcessedVarList;
22720 // The mappble components for each expression.
22722 // The base declaration of the variable.
22723 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
22724 // The reference to the user-defined mapper associated with every expression.
22725 SmallVector<Expr *, 16> UDMapperList;
22726
22727 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
22728 // We have a list of components and base declarations for each entry in the
22729 // variable list.
22730 VarComponents.reserve(VarList.size());
22731 VarBaseDeclarations.reserve(VarList.size());
22732 }
22733};
22734} // namespace
22735
22737 DSAStackTy *Stack,
22739
22740 const RecordDecl *RD = BaseType->getAsRecordDecl();
22741 SourceRange Range = RD->getSourceRange();
22742 DeclarationNameInfo ImplicitName;
22743 // Dummy variable _s for Mapper.
22744 VarDecl *VD = buildVarDecl(S, Range.getEnd(), BaseType, "_s");
22745 DeclRefExpr *MapperVarRef =
22746 buildDeclRefExpr(S, VD, BaseType, SourceLocation());
22747
22748 // Create implicit map clause for mapper.
22750 for (auto *FD : RD->fields()) {
22751 Expr *BE = S.BuildMemberExpr(
22752 MapperVarRef, /*IsArrow=*/false, Range.getBegin(),
22753 NestedNameSpecifierLoc(), Range.getBegin(), FD,
22755 /*HadMultipleCandidates=*/false,
22757 FD->getType(), VK_LValue, OK_Ordinary);
22758 SExprs.push_back(BE);
22759 }
22760 CXXScopeSpec MapperIdScopeSpec;
22761 DeclarationNameInfo MapperId;
22762 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
22763
22764 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
22765 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec,
22766 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
22767 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), SExprs,
22768 OMPVarListLocTy());
22769 Maps.push_back(MapClause);
22770 return MapperVarRef;
22771}
22772
22774 DSAStackTy *Stack) {
22775
22776 // Build impilicit map for mapper
22778 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
22779
22780 const RecordDecl *RD = BaseType->getAsRecordDecl();
22781 // AST context is RD's ParentASTContext().
22782 ASTContext &Ctx = RD->getParentASTContext();
22783 // DeclContext is RD's DeclContext.
22784 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
22785
22786 // Create implicit default mapper for "RD".
22787 DeclarationName MapperId;
22788 auto &DeclNames = Ctx.DeclarationNames;
22789 MapperId = DeclNames.getIdentifier(&Ctx.Idents.get("default"));
22790 auto *DMD = OMPDeclareMapperDecl::Create(Ctx, DCT, SourceLocation(), MapperId,
22791 BaseType, MapperId, Maps, nullptr);
22792 Scope *Scope = S.getScopeForContext(DCT);
22793 if (Scope)
22794 S.PushOnScopeChains(DMD, Scope, /*AddToContext=*/false);
22795 DCT->addDecl(DMD);
22796 DMD->setAccess(clang::AS_none);
22797 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22798 VD->setDeclContext(DMD);
22799 VD->setLexicalDeclContext(DMD);
22800 DMD->addDecl(VD);
22801 DMD->setMapperVarRef(MapperVarRef);
22802 FieldDecl *FD = *RD->field_begin();
22803 // create mapper refence.
22805 DMD, false, SourceLocation(), BaseType, VK_LValue);
22806}
22807
22808// Look up the user-defined mapper given the mapper name and mapper type,
22809// return true if found one.
22810static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
22811 CXXScopeSpec &MapperIdScopeSpec,
22812 const DeclarationNameInfo &MapperId,
22813 QualType Type) {
22814 // Find all user-defined mappers with the given MapperId.
22815 SmallVector<UnresolvedSet<8>, 4> Lookups;
22816 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
22817 Lookup.suppressDiagnostics();
22818 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
22819 /*ObjectType=*/QualType())) {
22820 NamedDecl *D = Lookup.getRepresentativeDecl();
22821 while (S && !S->isDeclScope(D))
22822 S = S->getParent();
22823 if (S)
22824 S = S->getParent();
22825 Lookups.emplace_back();
22826 Lookups.back().append(Lookup.begin(), Lookup.end());
22827 Lookup.clear();
22828 }
22829 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
22833 return !D->isInvalidDecl() &&
22834 (D->getType()->isDependentType() ||
22835 D->getType()->isInstantiationDependentType() ||
22836 D->getType()->containsUnexpandedParameterPack());
22837 }))
22838 return false;
22839 // Perform argument dependent lookup.
22840 SourceLocation Loc = MapperId.getLoc();
22841 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
22842 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
22844 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
22845 if (!D->isInvalidDecl() &&
22846 SemaRef.Context.hasSameType(D->getType(), Type))
22847 return D;
22848 return nullptr;
22849 }))
22850 return true;
22851 // Find the first user-defined mapper with a type derived from the desired
22852 // type.
22854 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
22855 if (!D->isInvalidDecl() &&
22856 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
22857 !Type.isMoreQualifiedThan(D->getType(), SemaRef.getASTContext()))
22858 return D;
22859 return nullptr;
22860 });
22861 if (!VD)
22862 return false;
22863 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
22864 /*DetectVirtual=*/false);
22865 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
22866 bool IsAmbiguous = !Paths.isAmbiguous(
22868 if (IsAmbiguous)
22869 return false;
22870 if (SemaRef.CheckBaseClassAccess(Loc, VD->getType(), Type, Paths.front(),
22871 /*DiagID=*/0) != Sema::AR_inaccessible)
22872 return true;
22873 }
22874 return false;
22875}
22876
22877static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
22878 QualType CanonType, const Expr *E) {
22879
22880 // DFS over data members in structures/classes.
22882 {CanonType, nullptr});
22883 llvm::DenseMap<const Type *, bool> Visited;
22884 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
22885 while (!Types.empty()) {
22886 auto [BaseType, CurFD] = Types.pop_back_val();
22887 while (ParentChain.back().second == 0)
22888 ParentChain.pop_back();
22889 --ParentChain.back().second;
22890 if (BaseType.isNull())
22891 continue;
22892 // Only structs/classes are allowed to have mappers.
22893 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
22894 if (!RD)
22895 continue;
22896 auto It = Visited.find(BaseType.getTypePtr());
22897 if (It == Visited.end()) {
22898 // Try to find the associated user-defined mapper.
22899 CXXScopeSpec MapperIdScopeSpec;
22900 DeclarationNameInfo DefaultMapperId;
22902 &S.Context.Idents.get("default")));
22903 DefaultMapperId.setLoc(E->getExprLoc());
22904 bool HasUDMapper =
22905 hasUserDefinedMapper(S, Stack->getCurScope(), MapperIdScopeSpec,
22906 DefaultMapperId, BaseType);
22907 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
22908 }
22909 // Found default mapper.
22910 if (It->second)
22911 return true;
22912 // Check for the "default" mapper for data members.
22913 bool FirstIter = true;
22914 for (FieldDecl *FD : RD->fields()) {
22915 if (!FD)
22916 continue;
22917 QualType FieldTy = FD->getType();
22918 if (FieldTy.isNull() ||
22919 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
22920 continue;
22921 if (FirstIter) {
22922 FirstIter = false;
22923 ParentChain.emplace_back(CurFD, 1);
22924 } else {
22925 ++ParentChain.back().second;
22926 }
22927 Types.emplace_back(FieldTy, FD);
22928 }
22929 }
22930 return false;
22931}
22932
22933// Check the validity of the provided variable list for the provided clause kind
22934// \a CKind. In the check process the valid expressions, mappable expression
22935// components, variables, and user-defined mappers are extracted and used to
22936// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
22937// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
22938// and \a MapperId are expected to be valid if the clause kind is 'map'.
22940 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
22941 MappableVarListInfo &MVLI, SourceLocation StartLoc,
22942 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
22943 ArrayRef<Expr *> UnresolvedMappers,
22945 ArrayRef<OpenMPMapModifierKind> Modifiers = {},
22946 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
22947 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
22948 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
22949 "Unexpected clause kind with mappable expressions!");
22950 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
22951
22952 // If the identifier of user-defined mapper is not specified, it is "default".
22953 // We do not change the actual name in this clause to distinguish whether a
22954 // mapper is specified explicitly, i.e., it is not explicitly specified when
22955 // MapperId.getName() is empty.
22956 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
22957 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
22958 MapperId.setName(DeclNames.getIdentifier(
22959 &SemaRef.getASTContext().Idents.get("default")));
22960 MapperId.setLoc(StartLoc);
22961 }
22962
22963 // Iterators to find the current unresolved mapper expression.
22964 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
22965 bool UpdateUMIt = false;
22966 Expr *UnresolvedMapper = nullptr;
22967
22968 bool HasHoldModifier =
22969 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
22970
22971 // Keep track of the mappable components and base declarations in this clause.
22972 // Each entry in the list is going to have a list of components associated. We
22973 // record each set of the components so that we can build the clause later on.
22974 // In the end we should have the same amount of declarations and component
22975 // lists.
22976
22977 for (Expr *RE : MVLI.VarList) {
22978 assert(RE && "Null expr in omp to/from/map clause");
22979 SourceLocation ELoc = RE->getExprLoc();
22980
22981 // Find the current unresolved mapper expression.
22982 if (UpdateUMIt && UMIt != UMEnd) {
22983 UMIt++;
22984 assert(
22985 UMIt != UMEnd &&
22986 "Expect the size of UnresolvedMappers to match with that of VarList");
22987 }
22988 UpdateUMIt = true;
22989 if (UMIt != UMEnd)
22990 UnresolvedMapper = *UMIt;
22991
22992 const Expr *VE = RE->IgnoreParenLValueCasts();
22993
22994 if (VE->isValueDependent() || VE->isTypeDependent() ||
22995 VE->isInstantiationDependent() ||
22996 VE->containsUnexpandedParameterPack()) {
22997 // Try to find the associated user-defined mapper.
22999 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23000 VE->getType().getCanonicalType(), UnresolvedMapper);
23001 if (ER.isInvalid())
23002 continue;
23003 MVLI.UDMapperList.push_back(ER.get());
23004 // We can only analyze this information once the missing information is
23005 // resolved.
23006 MVLI.ProcessedVarList.push_back(RE);
23007 continue;
23008 }
23009
23011
23012 if (!RE->isLValue()) {
23013 if (SemaRef.getLangOpts().OpenMP < 50) {
23014 SemaRef.Diag(
23015 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
23016 << RE->getSourceRange();
23017 } else {
23018 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
23019 << getOpenMPClauseNameForDiag(CKind) << RE->getSourceRange();
23020 }
23021 continue;
23022 }
23023
23025 ValueDecl *CurDeclaration = nullptr;
23026
23027 // Obtain the array or member expression bases if required. Also, fill the
23028 // components array with all the components identified in the process.
23029 const Expr *BE =
23030 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
23031 DSAS->getCurrentDirective(), NoDiagnose);
23032 if (!BE)
23033 continue;
23034
23035 assert(!CurComponents.empty() &&
23036 "Invalid mappable expression information.");
23037
23038 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
23039 // Add store "this" pointer to class in DSAStackTy for future checking
23040 DSAS->addMappedClassesQualTypes(TE->getType());
23041 // Try to find the associated user-defined mapper.
23043 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23044 VE->getType().getCanonicalType(), UnresolvedMapper);
23045 if (ER.isInvalid())
23046 continue;
23047 MVLI.UDMapperList.push_back(ER.get());
23048 // Skip restriction checking for variable or field declarations
23049 MVLI.ProcessedVarList.push_back(RE);
23050 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23051 MVLI.VarComponents.back().append(CurComponents.begin(),
23052 CurComponents.end());
23053 MVLI.VarBaseDeclarations.push_back(nullptr);
23054 continue;
23055 }
23056
23057 // For the following checks, we rely on the base declaration which is
23058 // expected to be associated with the last component. The declaration is
23059 // expected to be a variable or a field (if 'this' is being mapped).
23060 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
23061 assert(CurDeclaration && "Null decl on map clause.");
23062 assert(
23063 CurDeclaration->isCanonicalDecl() &&
23064 "Expecting components to have associated only canonical declarations.");
23065
23066 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
23067 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
23068
23069 assert((VD || FD) && "Only variables or fields are expected here!");
23070 (void)FD;
23071
23072 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
23073 // threadprivate variables cannot appear in a map clause.
23074 // OpenMP 4.5 [2.10.5, target update Construct]
23075 // threadprivate variables cannot appear in a from clause.
23076 if (VD && DSAS->isThreadPrivate(VD)) {
23077 if (NoDiagnose)
23078 continue;
23079 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
23080 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
23082 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
23083 continue;
23084 }
23085
23086 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
23087 // A list item cannot appear in both a map clause and a data-sharing
23088 // attribute clause on the same construct.
23089
23090 // Check conflicts with other map clause expressions. We check the conflicts
23091 // with the current construct separately from the enclosing data
23092 // environment, because the restrictions are different. We only have to
23093 // check conflicts across regions for the map clauses.
23094 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
23095 /*CurrentRegionOnly=*/true, CurComponents, CKind))
23096 break;
23097 if (CKind == OMPC_map &&
23098 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
23099 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
23100 /*CurrentRegionOnly=*/false, CurComponents, CKind))
23101 break;
23102
23103 // OpenMP 4.5 [2.10.5, target update Construct]
23104 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
23105 // If the type of a list item is a reference to a type T then the type will
23106 // be considered to be T for all purposes of this clause.
23107 auto I = llvm::find_if(
23108 CurComponents,
23110 return MC.getAssociatedDeclaration();
23111 });
23112 assert(I != CurComponents.end() && "Null decl on map clause.");
23113 (void)I;
23114 QualType Type;
23115 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
23116 auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens());
23117 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
23118 if (ASE) {
23119 Type = ASE->getType().getNonReferenceType();
23120 } else if (OASE) {
23121 QualType BaseType =
23123 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
23124 Type = ATy->getElementType();
23125 else
23126 Type = BaseType->getPointeeType();
23127 Type = Type.getNonReferenceType();
23128 } else if (OAShE) {
23129 Type = OAShE->getBase()->getType()->getPointeeType();
23130 } else {
23131 Type = VE->getType();
23132 }
23133
23134 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
23135 // A list item in a to or from clause must have a mappable type.
23136 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
23137 // A list item must have a mappable type.
23138 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
23139 DSAS, Type, /*FullCheck=*/true))
23140 continue;
23141
23142 if (CKind == OMPC_map) {
23143 // target enter data
23144 // OpenMP [2.10.2, Restrictions, p. 99]
23145 // A map-type must be specified in all map clauses and must be either
23146 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
23147 // no map type is present.
23148 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
23149 if (DKind == OMPD_target_enter_data &&
23150 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
23151 SemaRef.getLangOpts().OpenMP >= 52)) {
23152 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23153 << (IsMapTypeImplicit ? 1 : 0)
23154 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
23155 << getOpenMPDirectiveName(DKind, OMPVersion);
23156 continue;
23157 }
23158
23159 // target exit_data
23160 // OpenMP [2.10.3, Restrictions, p. 102]
23161 // A map-type must be specified in all map clauses and must be either
23162 // from, release, or delete. Starting with OpenMP 5.2 the default map
23163 // type is `from` if no map type is present.
23164 if (DKind == OMPD_target_exit_data &&
23165 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
23166 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
23167 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23168 << (IsMapTypeImplicit ? 1 : 0)
23169 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
23170 << getOpenMPDirectiveName(DKind, OMPVersion);
23171 continue;
23172 }
23173
23174 // The 'ompx_hold' modifier is specifically intended to be used on a
23175 // 'target' or 'target data' directive to prevent data from being unmapped
23176 // during the associated statement. It is not permitted on a 'target
23177 // enter data' or 'target exit data' directive, which have no associated
23178 // statement.
23179 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
23180 HasHoldModifier) {
23181 SemaRef.Diag(StartLoc,
23182 diag::err_omp_invalid_map_type_modifier_for_directive)
23184 OMPC_MAP_MODIFIER_ompx_hold)
23185 << getOpenMPDirectiveName(DKind, OMPVersion);
23186 continue;
23187 }
23188
23189 // target, target data
23190 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
23191 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
23192 // A map-type in a map clause must be to, from, tofrom or alloc
23193 if ((DKind == OMPD_target_data ||
23195 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
23196 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
23197 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23198 << (IsMapTypeImplicit ? 1 : 0)
23199 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
23200 << getOpenMPDirectiveName(DKind, OMPVersion);
23201 continue;
23202 }
23203
23204 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
23205 // A list item cannot appear in both a map clause and a data-sharing
23206 // attribute clause on the same construct
23207 //
23208 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
23209 // A list item cannot appear in both a map clause and a data-sharing
23210 // attribute clause on the same construct unless the construct is a
23211 // combined construct.
23212 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
23214 DKind == OMPD_target)) {
23215 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
23216 if (isOpenMPPrivate(DVar.CKind)) {
23217 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23218 << getOpenMPClauseNameForDiag(DVar.CKind)
23219 << getOpenMPClauseNameForDiag(OMPC_map)
23220 << getOpenMPDirectiveName(DSAS->getCurrentDirective(),
23221 OMPVersion);
23222 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
23223 continue;
23224 }
23225 }
23226 }
23227
23228 // Try to find the associated user-defined mapper.
23230 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23231 Type.getCanonicalType(), UnresolvedMapper);
23232 if (ER.isInvalid())
23233 continue;
23234
23235 // If no user-defined mapper is found, we need to create an implicit one for
23236 // arrays/array-sections on structs that have members that have
23237 // user-defined mappers. This is needed to ensure that the mapper for the
23238 // member is invoked when mapping each element of the array/array-section.
23239 if (!ER.get()) {
23240 QualType BaseType;
23241
23243 BaseType = VE->getType().getCanonicalType();
23244 if (BaseType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
23245 const auto *OASE = cast<ArraySectionExpr>(VE->IgnoreParenImpCasts());
23246 QualType BType =
23248 QualType ElemType;
23249 if (const auto *ATy = BType->getAsArrayTypeUnsafe())
23250 ElemType = ATy->getElementType();
23251 else
23252 ElemType = BType->getPointeeType();
23253 BaseType = ElemType.getCanonicalType();
23254 }
23255 } else if (VE->getType()->isArrayType()) {
23256 const ArrayType *AT = VE->getType()->getAsArrayTypeUnsafe();
23257 const QualType ElemType = AT->getElementType();
23258 BaseType = ElemType.getCanonicalType();
23259 }
23260
23261 if (!BaseType.isNull() && BaseType->getAsRecordDecl() &&
23262 isImplicitMapperNeeded(SemaRef, DSAS, BaseType, VE)) {
23263 ER = buildImplicitMapper(SemaRef, BaseType, DSAS);
23264 }
23265 }
23266 MVLI.UDMapperList.push_back(ER.get());
23267
23268 // Save the current expression.
23269 MVLI.ProcessedVarList.push_back(RE);
23270
23271 // Store the components in the stack so that they can be used to check
23272 // against other clauses later on.
23273 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
23274 /*WhereFoundClauseKind=*/OMPC_map);
23275
23276 // Save the components and declaration to create the clause. For purposes of
23277 // the clause creation, any component list that has base 'this' uses
23278 // null as base declaration.
23279 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23280 MVLI.VarComponents.back().append(CurComponents.begin(),
23281 CurComponents.end());
23282 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
23283 : CurDeclaration);
23284 }
23285}
23286
23288 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
23289 ArrayRef<SourceLocation> MapTypeModifiersLoc,
23290 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23291 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
23292 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23293 const OMPVarListLocTy &Locs, bool NoDiagnose,
23294 ArrayRef<Expr *> UnresolvedMappers) {
23295 OpenMPMapModifierKind Modifiers[] = {
23301
23302 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
23303 BuiltinType::OMPIterator))
23304 Diag(IteratorModifier->getExprLoc(),
23305 diag::err_omp_map_modifier_not_iterator);
23306
23307 // Process map-type-modifiers, flag errors for duplicate modifiers.
23308 unsigned Count = 0;
23309 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
23310 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
23311 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
23312 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
23313 continue;
23314 }
23315 assert(Count < NumberOfOMPMapClauseModifiers &&
23316 "Modifiers exceed the allowed number of map type modifiers");
23317 Modifiers[Count] = MapTypeModifiers[I];
23318 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
23319 ++Count;
23320 }
23321
23322 MappableVarListInfo MVLI(VarList);
23324 MapperIdScopeSpec, MapperId, UnresolvedMappers,
23325 MapType, Modifiers, IsMapTypeImplicit,
23326 NoDiagnose);
23327
23328 // We need to produce a map clause even if we don't have variables so that
23329 // other diagnostics related with non-existing map clauses are accurate.
23330 return OMPMapClause::Create(
23331 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23332 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
23333 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
23334 MapperId, MapType, IsMapTypeImplicit, MapLoc);
23335}
23336
23339 assert(ParsedType.isUsable());
23340
23341 QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get());
23342 if (ReductionType.isNull())
23343 return QualType();
23344
23345 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
23346 // A type name in a declare reduction directive cannot be a function type, an
23347 // array type, a reference type, or a type qualified with const, volatile or
23348 // restrict.
23349 if (ReductionType.hasQualifiers()) {
23350 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
23351 return QualType();
23352 }
23353
23354 if (ReductionType->isFunctionType()) {
23355 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
23356 return QualType();
23357 }
23358 if (ReductionType->isReferenceType()) {
23359 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
23360 return QualType();
23361 }
23362 if (ReductionType->isArrayType()) {
23363 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
23364 return QualType();
23365 }
23366 return ReductionType;
23367}
23368
23371 Scope *S, DeclContext *DC, DeclarationName Name,
23372 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
23373 AccessSpecifier AS, Decl *PrevDeclInScope) {
23375 Decls.reserve(ReductionTypes.size());
23376
23377 LookupResult Lookup(SemaRef, Name, SourceLocation(),
23379 SemaRef.forRedeclarationInCurContext());
23380 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
23381 // A reduction-identifier may not be re-declared in the current scope for the
23382 // same type or for a type that is compatible according to the base language
23383 // rules.
23384 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
23385 OMPDeclareReductionDecl *PrevDRD = nullptr;
23386 bool InCompoundScope = true;
23387 if (S != nullptr) {
23388 // Find previous declaration with the same name not referenced in other
23389 // declarations.
23390 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
23391 InCompoundScope =
23392 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
23393 SemaRef.LookupName(Lookup, S);
23394 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
23395 /*AllowInlineNamespace=*/false);
23396 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
23397 LookupResult::Filter Filter = Lookup.makeFilter();
23398 while (Filter.hasNext()) {
23399 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
23400 if (InCompoundScope) {
23401 UsedAsPrevious.try_emplace(PrevDecl, false);
23402 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
23403 UsedAsPrevious[D] = true;
23404 }
23405 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
23406 PrevDecl->getLocation();
23407 }
23408 Filter.done();
23409 if (InCompoundScope) {
23410 for (const auto &PrevData : UsedAsPrevious) {
23411 if (!PrevData.second) {
23412 PrevDRD = PrevData.first;
23413 break;
23414 }
23415 }
23416 }
23417 } else if (PrevDeclInScope != nullptr) {
23418 auto *PrevDRDInScope = PrevDRD =
23419 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
23420 do {
23421 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
23422 PrevDRDInScope->getLocation();
23423 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
23424 } while (PrevDRDInScope != nullptr);
23425 }
23426 for (const auto &TyData : ReductionTypes) {
23427 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
23428 bool Invalid = false;
23429 if (I != PreviousRedeclTypes.end()) {
23430 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
23431 << TyData.first;
23432 Diag(I->second, diag::note_previous_definition);
23433 Invalid = true;
23434 }
23435 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
23437 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
23438 DC->addDecl(DRD);
23439 DRD->setAccess(AS);
23440 Decls.push_back(DRD);
23441 if (Invalid)
23442 DRD->setInvalidDecl();
23443 else
23444 PrevDRD = DRD;
23445 }
23446
23447 return DeclGroupPtrTy::make(
23448 DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size()));
23449}
23450
23452 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23453
23454 // Enter new function scope.
23455 SemaRef.PushFunctionScope();
23456 SemaRef.setFunctionHasBranchProtectedScope();
23457 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
23458
23459 if (S != nullptr)
23460 SemaRef.PushDeclContext(S, DRD);
23461 else
23462 SemaRef.CurContext = DRD;
23463
23464 SemaRef.PushExpressionEvaluationContext(
23466
23467 QualType ReductionType = DRD->getType();
23468 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
23469 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
23470 // uses semantics of argument handles by value, but it should be passed by
23471 // reference. C lang does not support references, so pass all parameters as
23472 // pointers.
23473 // Create 'T omp_in;' variable.
23474 VarDecl *OmpInParm =
23475 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in");
23476 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
23477 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
23478 // uses semantics of argument handles by value, but it should be passed by
23479 // reference. C lang does not support references, so pass all parameters as
23480 // pointers.
23481 // Create 'T omp_out;' variable.
23482 VarDecl *OmpOutParm =
23483 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out");
23484 if (S != nullptr) {
23485 SemaRef.PushOnScopeChains(OmpInParm, S);
23486 SemaRef.PushOnScopeChains(OmpOutParm, S);
23487 } else {
23488 DRD->addDecl(OmpInParm);
23489 DRD->addDecl(OmpOutParm);
23490 }
23491 Expr *InE =
23492 ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation());
23493 Expr *OutE =
23494 ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation());
23495 DRD->setCombinerData(InE, OutE);
23496}
23497
23499 Expr *Combiner) {
23500 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23501 SemaRef.DiscardCleanupsInEvaluationContext();
23502 SemaRef.PopExpressionEvaluationContext();
23503
23504 SemaRef.PopDeclContext();
23505 SemaRef.PopFunctionScopeInfo();
23506
23507 if (Combiner != nullptr)
23508 DRD->setCombiner(Combiner);
23509 else
23510 DRD->setInvalidDecl();
23511}
23512
23514 Decl *D) {
23515 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23516
23517 // Enter new function scope.
23518 SemaRef.PushFunctionScope();
23519 SemaRef.setFunctionHasBranchProtectedScope();
23520
23521 if (S != nullptr)
23522 SemaRef.PushDeclContext(S, DRD);
23523 else
23524 SemaRef.CurContext = DRD;
23525
23526 SemaRef.PushExpressionEvaluationContext(
23528
23529 QualType ReductionType = DRD->getType();
23530 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
23531 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
23532 // uses semantics of argument handles by value, but it should be passed by
23533 // reference. C lang does not support references, so pass all parameters as
23534 // pointers.
23535 // Create 'T omp_priv;' variable.
23536 VarDecl *OmpPrivParm =
23537 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv");
23538 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
23539 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
23540 // uses semantics of argument handles by value, but it should be passed by
23541 // reference. C lang does not support references, so pass all parameters as
23542 // pointers.
23543 // Create 'T omp_orig;' variable.
23544 VarDecl *OmpOrigParm =
23545 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig");
23546 if (S != nullptr) {
23547 SemaRef.PushOnScopeChains(OmpPrivParm, S);
23548 SemaRef.PushOnScopeChains(OmpOrigParm, S);
23549 } else {
23550 DRD->addDecl(OmpPrivParm);
23551 DRD->addDecl(OmpOrigParm);
23552 }
23553 Expr *OrigE =
23554 ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation());
23555 Expr *PrivE =
23556 ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation());
23557 DRD->setInitializerData(OrigE, PrivE);
23558 return OmpPrivParm;
23559}
23560
23562 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
23563 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23564 SemaRef.DiscardCleanupsInEvaluationContext();
23565 SemaRef.PopExpressionEvaluationContext();
23566
23567 SemaRef.PopDeclContext();
23568 SemaRef.PopFunctionScopeInfo();
23569
23570 if (Initializer != nullptr) {
23571 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
23572 } else if (OmpPrivParm->hasInit()) {
23573 DRD->setInitializer(OmpPrivParm->getInit(),
23574 OmpPrivParm->isDirectInit()
23577 } else {
23578 DRD->setInvalidDecl();
23579 }
23580}
23581
23583 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
23584 for (Decl *D : DeclReductions.get()) {
23585 if (IsValid) {
23586 if (S)
23587 SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
23588 /*AddToContext=*/false);
23589 } else {
23590 D->setInvalidDecl();
23591 }
23592 }
23593 return DeclReductions;
23594}
23595
23597 Declarator &D) {
23598 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
23599 QualType T = TInfo->getType();
23600 if (D.isInvalidType())
23601 return true;
23602
23603 if (getLangOpts().CPlusPlus) {
23604 // Check that there are no default arguments (C++ only).
23605 SemaRef.CheckExtraCXXDefaultArguments(D);
23606 }
23607
23608 return SemaRef.CreateParsedType(T, TInfo);
23609}
23610
23613 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
23614
23615 QualType MapperType = SemaRef.GetTypeFromParser(ParsedType.get());
23616 assert(!MapperType.isNull() && "Expect valid mapper type");
23617
23618 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
23619 // The type must be of struct, union or class type in C and C++
23620 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
23621 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
23622 return QualType();
23623 }
23624 return MapperType;
23625}
23626
23628 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
23630 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
23631 LookupResult Lookup(SemaRef, Name, SourceLocation(),
23633 SemaRef.forRedeclarationInCurContext());
23634 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
23635 // A mapper-identifier may not be redeclared in the current scope for the
23636 // same type or for a type that is compatible according to the base language
23637 // rules.
23638 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
23639 OMPDeclareMapperDecl *PrevDMD = nullptr;
23640 bool InCompoundScope = true;
23641 if (S != nullptr) {
23642 // Find previous declaration with the same name not referenced in other
23643 // declarations.
23644 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
23645 InCompoundScope =
23646 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
23647 SemaRef.LookupName(Lookup, S);
23648 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
23649 /*AllowInlineNamespace=*/false);
23650 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
23651 LookupResult::Filter Filter = Lookup.makeFilter();
23652 while (Filter.hasNext()) {
23653 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
23654 if (InCompoundScope) {
23655 UsedAsPrevious.try_emplace(PrevDecl, false);
23656 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
23657 UsedAsPrevious[D] = true;
23658 }
23659 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
23660 PrevDecl->getLocation();
23661 }
23662 Filter.done();
23663 if (InCompoundScope) {
23664 for (const auto &PrevData : UsedAsPrevious) {
23665 if (!PrevData.second) {
23666 PrevDMD = PrevData.first;
23667 break;
23668 }
23669 }
23670 }
23671 } else if (PrevDeclInScope) {
23672 auto *PrevDMDInScope = PrevDMD =
23673 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
23674 do {
23675 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
23676 PrevDMDInScope->getLocation();
23677 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
23678 } while (PrevDMDInScope != nullptr);
23679 }
23680 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
23681 bool Invalid = false;
23682 if (I != PreviousRedeclTypes.end()) {
23683 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
23684 << MapperType << Name;
23685 Diag(I->second, diag::note_previous_definition);
23686 Invalid = true;
23687 }
23688 // Build expressions for implicit maps of data members with 'default'
23689 // mappers.
23690 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
23691 if (getLangOpts().OpenMP >= 50)
23693 ClausesWithImplicit);
23694 auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name,
23695 MapperType, VN, ClausesWithImplicit,
23696 PrevDMD);
23697 if (S)
23698 SemaRef.PushOnScopeChains(DMD, S);
23699 else
23700 DC->addDecl(DMD);
23701 DMD->setAccess(AS);
23702 if (Invalid)
23703 DMD->setInvalidDecl();
23704
23705 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
23706 VD->setDeclContext(DMD);
23707 VD->setLexicalDeclContext(DMD);
23708 DMD->addDecl(VD);
23709 DMD->setMapperVarRef(MapperVarRef);
23710
23712}
23713
23715 Scope *S, QualType MapperType, SourceLocation StartLoc,
23716 DeclarationName VN) {
23717 TypeSourceInfo *TInfo =
23718 getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc);
23719 auto *VD = VarDecl::Create(
23720 getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc,
23721 StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None);
23722 if (S)
23723 SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false);
23724 Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc);
23725 DSAStack->addDeclareMapperVarRef(E);
23726 return E;
23727}
23728
23730 bool IsGlobalVar =
23732 if (DSAStack->getDeclareMapperVarRef()) {
23733 if (IsGlobalVar)
23734 SemaRef.Consumer.HandleTopLevelDecl(DeclGroupRef(VD));
23735 DSAStack->addIteratorVarDecl(VD);
23736 } else {
23737 // Currently, only declare mapper handles global-scope iterator vars.
23738 assert(!IsGlobalVar && "Only declare mapper handles TU-scope iterators.");
23739 }
23740}
23741
23743 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
23744 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
23745 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
23746 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
23747 return true;
23749 return true;
23750 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
23751 return true;
23752 return false;
23753 }
23754 return true;
23755}
23756
23758 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
23759 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
23760}
23761
23763 SourceLocation StartLoc,
23764 SourceLocation LParenLoc,
23765 SourceLocation EndLoc) {
23766 if (VarList.empty())
23767 return nullptr;
23768
23769 for (Expr *ValExpr : VarList) {
23770 // OpenMP [teams Constrcut, Restrictions]
23771 // The num_teams expression must evaluate to a positive integer value.
23772 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams,
23773 /*StrictlyPositive=*/true))
23774 return nullptr;
23775 }
23776
23777 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23779 DKind, OMPC_num_teams, getLangOpts().OpenMP);
23780 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
23781 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
23782 LParenLoc, EndLoc, VarList,
23783 /*PreInit=*/nullptr);
23784
23785 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23787 for (Expr *ValExpr : VarList) {
23788 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23789 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23790 Vars.push_back(ValExpr);
23791 }
23792
23793 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
23794 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
23795 LParenLoc, EndLoc, Vars, PreInit);
23796}
23797
23799 SourceLocation StartLoc,
23800 SourceLocation LParenLoc,
23801 SourceLocation EndLoc) {
23802 if (VarList.empty())
23803 return nullptr;
23804
23805 for (Expr *ValExpr : VarList) {
23806 // OpenMP [teams Constrcut, Restrictions]
23807 // The thread_limit expression must evaluate to a positive integer value.
23808 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit,
23809 /*StrictlyPositive=*/true))
23810 return nullptr;
23811 }
23812
23813 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23815 DKind, OMPC_thread_limit, getLangOpts().OpenMP);
23816 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
23817 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion,
23818 StartLoc, LParenLoc, EndLoc, VarList,
23819 /*PreInit=*/nullptr);
23820
23821 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23823 for (Expr *ValExpr : VarList) {
23824 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23825 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23826 Vars.push_back(ValExpr);
23827 }
23828
23829 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
23830 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion, StartLoc,
23831 LParenLoc, EndLoc, Vars, PreInit);
23832}
23833
23835 SourceLocation StartLoc,
23836 SourceLocation LParenLoc,
23837 SourceLocation EndLoc) {
23838 Expr *ValExpr = Priority;
23839 Stmt *HelperValStmt = nullptr;
23840 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23841
23842 // OpenMP [2.9.1, task Constrcut]
23843 // The priority-value is a non-negative numerical scalar expression.
23845 ValExpr, SemaRef, OMPC_priority,
23846 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
23847 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23848 return nullptr;
23849
23850 return new (getASTContext()) OMPPriorityClause(
23851 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23852}
23853
23855 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
23856 SourceLocation StartLoc, SourceLocation LParenLoc,
23857 SourceLocation ModifierLoc, SourceLocation EndLoc) {
23858 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
23859 "Unexpected grainsize modifier in OpenMP < 51.");
23860
23861 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
23862 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
23864 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23865 << Values << getOpenMPClauseNameForDiag(OMPC_grainsize);
23866 return nullptr;
23867 }
23868
23869 Expr *ValExpr = Grainsize;
23870 Stmt *HelperValStmt = nullptr;
23871 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23872
23873 // OpenMP [2.9.2, taskloop Constrcut]
23874 // The parameter of the grainsize clause must be a positive integer
23875 // expression.
23876 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize,
23877 /*StrictlyPositive=*/true,
23878 /*BuildCapture=*/true,
23879 DSAStack->getCurrentDirective(),
23880 &CaptureRegion, &HelperValStmt))
23881 return nullptr;
23882
23883 return new (getASTContext())
23884 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
23885 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23886}
23887
23889 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
23890 SourceLocation StartLoc, SourceLocation LParenLoc,
23891 SourceLocation ModifierLoc, SourceLocation EndLoc) {
23892 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
23893 "Unexpected num_tasks modifier in OpenMP < 51.");
23894
23895 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
23896 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
23898 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23899 << Values << getOpenMPClauseNameForDiag(OMPC_num_tasks);
23900 return nullptr;
23901 }
23902
23903 Expr *ValExpr = NumTasks;
23904 Stmt *HelperValStmt = nullptr;
23905 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23906
23907 // OpenMP [2.9.2, taskloop Constrcut]
23908 // The parameter of the num_tasks clause must be a positive integer
23909 // expression.
23911 ValExpr, SemaRef, OMPC_num_tasks,
23912 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
23913 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23914 return nullptr;
23915
23916 return new (getASTContext())
23917 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
23918 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23919}
23920
23922 SourceLocation StartLoc,
23923 SourceLocation LParenLoc,
23924 SourceLocation EndLoc) {
23925 // OpenMP [2.13.2, critical construct, Description]
23926 // ... where hint-expression is an integer constant expression that evaluates
23927 // to a valid lock hint.
23928 ExprResult HintExpr =
23929 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
23930 if (HintExpr.isInvalid())
23931 return nullptr;
23932 return new (getASTContext())
23933 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
23934}
23935
23936/// Tries to find omp_event_handle_t type.
23938 DSAStackTy *Stack) {
23939 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
23940 if (!OMPEventHandleT.isNull())
23941 return true;
23942 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
23943 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
23944 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23945 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
23946 return false;
23947 }
23948 Stack->setOMPEventHandleT(PT.get());
23949 return true;
23950}
23951
23953 SourceLocation StartLoc,
23954 SourceLocation LParenLoc,
23955 SourceLocation EndLoc) {
23956 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
23957 !Evt->isInstantiationDependent() &&
23960 return nullptr;
23961 // OpenMP 5.0, 2.10.1 task Construct.
23962 // event-handle is a variable of the omp_event_handle_t type.
23963 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
23964 if (!Ref) {
23965 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23966 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
23967 return nullptr;
23968 }
23969 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
23970 if (!VD) {
23971 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23972 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
23973 return nullptr;
23974 }
23975 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
23976 VD->getType()) ||
23977 VD->getType().isConstant(getASTContext())) {
23978 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23979 << "omp_event_handle_t" << 1 << VD->getType()
23980 << Evt->getSourceRange();
23981 return nullptr;
23982 }
23983 // OpenMP 5.0, 2.10.1 task Construct
23984 // [detach clause]... The event-handle will be considered as if it was
23985 // specified on a firstprivate clause.
23986 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
23987 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
23988 DVar.RefExpr) {
23989 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
23990 << getOpenMPClauseNameForDiag(DVar.CKind)
23991 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
23993 return nullptr;
23994 }
23995 }
23996
23997 return new (getASTContext())
23998 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
23999}
24000
24002 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
24003 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
24004 SourceLocation EndLoc) {
24005 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
24006 std::string Values;
24007 Values += "'";
24008 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
24009 Values += "'";
24010 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24011 << Values << getOpenMPClauseNameForDiag(OMPC_dist_schedule);
24012 return nullptr;
24013 }
24014 Expr *ValExpr = ChunkSize;
24015 Stmt *HelperValStmt = nullptr;
24016 if (ChunkSize) {
24017 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
24018 !ChunkSize->isInstantiationDependent() &&
24019 !ChunkSize->containsUnexpandedParameterPack()) {
24020 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
24021 ExprResult Val =
24022 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
24023 if (Val.isInvalid())
24024 return nullptr;
24025
24026 ValExpr = Val.get();
24027
24028 // OpenMP [2.7.1, Restrictions]
24029 // chunk_size must be a loop invariant integer expression with a positive
24030 // value.
24031 if (std::optional<llvm::APSInt> Result =
24033 if (Result->isSigned() && !Result->isStrictlyPositive()) {
24034 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
24035 << "dist_schedule" << /*strictly positive*/ 1
24036 << ChunkSize->getSourceRange();
24037 return nullptr;
24038 }
24040 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
24041 getLangOpts().OpenMP) != OMPD_unknown &&
24042 !SemaRef.CurContext->isDependentContext()) {
24043 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
24044 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24045 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
24046 HelperValStmt = buildPreInits(getASTContext(), Captures);
24047 }
24048 }
24049 }
24050
24051 return new (getASTContext())
24052 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
24053 Kind, ValExpr, HelperValStmt);
24054}
24055
24058 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
24059 SourceLocation KindLoc, SourceLocation EndLoc) {
24060 if (getLangOpts().OpenMP < 50) {
24061 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
24062 Kind != OMPC_DEFAULTMAP_scalar) {
24063 std::string Value;
24064 SourceLocation Loc;
24065 Value += "'";
24066 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
24067 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
24068 OMPC_DEFAULTMAP_MODIFIER_tofrom);
24069 Loc = MLoc;
24070 } else {
24071 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
24072 OMPC_DEFAULTMAP_scalar);
24073 Loc = KindLoc;
24074 }
24075 Value += "'";
24076 Diag(Loc, diag::err_omp_unexpected_clause_value)
24077 << Value << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24078 return nullptr;
24079 }
24080 } else {
24081 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
24082 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
24083 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
24084 if (!isDefaultmapKind || !isDefaultmapModifier) {
24085 StringRef KindValue = getLangOpts().OpenMP < 52
24086 ? "'scalar', 'aggregate', 'pointer'"
24087 : "'scalar', 'aggregate', 'pointer', 'all'";
24088 if (getLangOpts().OpenMP == 50) {
24089 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
24090 "'firstprivate', 'none', 'default'";
24091 if (!isDefaultmapKind && isDefaultmapModifier) {
24092 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24093 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24094 } else if (isDefaultmapKind && !isDefaultmapModifier) {
24095 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24096 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24097 } else {
24098 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24099 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24100 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24101 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24102 }
24103 } else {
24104 StringRef ModifierValue =
24105 getLangOpts().OpenMP < 60
24106 ? "'alloc', 'from', 'to', 'tofrom', "
24107 "'firstprivate', 'none', 'default', 'present'"
24108 : "'storage', 'from', 'to', 'tofrom', "
24109 "'firstprivate', 'private', 'none', 'default', 'present'";
24110 if (!isDefaultmapKind && isDefaultmapModifier) {
24111 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24112 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24113 } else if (isDefaultmapKind && !isDefaultmapModifier) {
24114 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24115 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24116 } else {
24117 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24118 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24119 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24120 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24121 }
24122 }
24123 return nullptr;
24124 }
24125
24126 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
24127 // At most one defaultmap clause for each category can appear on the
24128 // directive.
24129 if (DSAStack->checkDefaultmapCategory(Kind)) {
24130 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
24131 return nullptr;
24132 }
24133 }
24134 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
24135 // Variable category is not specified - mark all categories.
24136 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
24137 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
24138 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
24139 } else {
24140 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
24141 }
24142
24143 return new (getASTContext())
24144 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
24145}
24146
24149 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
24150 if (!CurLexicalContext->isFileContext() &&
24151 !CurLexicalContext->isExternCContext() &&
24152 !CurLexicalContext->isExternCXXContext() &&
24153 !isa<CXXRecordDecl>(CurLexicalContext) &&
24154 !isa<ClassTemplateDecl>(CurLexicalContext) &&
24155 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
24156 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
24157 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
24158 return false;
24159 }
24160
24161 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
24162 if (getLangOpts().HIP)
24163 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
24164
24165 DeclareTargetNesting.push_back(DTCI);
24166 return true;
24167}
24168
24171 assert(!DeclareTargetNesting.empty() &&
24172 "check isInOpenMPDeclareTargetContext() first!");
24173 return DeclareTargetNesting.pop_back_val();
24174}
24175
24178 for (auto &It : DTCI.ExplicitlyMapped)
24179 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
24180}
24181
24183 if (DeclareTargetNesting.empty())
24184 return;
24185 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
24186 unsigned OMPVersion = getLangOpts().OpenMP;
24187 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
24188 << getOpenMPDirectiveName(DTCI.Kind, OMPVersion);
24189}
24190
24192 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
24194 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
24195 /*ObjectType=*/QualType(),
24196 /*AllowBuiltinCreation=*/true);
24197
24198 if (Lookup.isAmbiguous())
24199 return nullptr;
24200 Lookup.suppressDiagnostics();
24201
24202 if (!Lookup.isSingleResult()) {
24203 VarOrFuncDeclFilterCCC CCC(SemaRef);
24204 if (TypoCorrection Corrected =
24205 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
24207 SemaRef.diagnoseTypo(Corrected,
24208 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
24209 << Id.getName());
24210 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
24211 return nullptr;
24212 }
24213
24214 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
24215 return nullptr;
24216 }
24217
24218 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
24219 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
24221 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
24222 return nullptr;
24223 }
24224 return ND;
24225}
24226
24228 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
24230 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
24232 "Expected variable, function or function template.");
24233
24234 if (auto *VD = dyn_cast<VarDecl>(ND)) {
24235 // Only global variables can be marked as declare target.
24236 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24237 !VD->isStaticDataMember()) {
24238 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
24239 << VD->getNameAsString();
24240 return;
24241 }
24242 }
24243 // Diagnose marking after use as it may lead to incorrect diagnosis and
24244 // codegen.
24245 if (getLangOpts().OpenMP >= 50 &&
24246 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
24247 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
24248
24249 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
24250 if (getLangOpts().HIP)
24251 Diag(Loc, diag::warn_hip_omp_target_directives);
24252
24253 // Explicit declare target lists have precedence.
24254 const unsigned Level = -1;
24255
24256 auto *VD = cast<ValueDecl>(ND);
24257 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24258 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24259 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
24260 (*ActiveAttr)->getLevel() == Level) {
24261 Diag(Loc, diag::err_omp_device_type_mismatch)
24262 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
24263 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
24264 (*ActiveAttr)->getDevType());
24265 return;
24266 }
24267 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
24268 (*ActiveAttr)->getLevel() == Level) {
24269 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
24270 return;
24271 }
24272
24273 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
24274 return;
24275
24276 Expr *IndirectE = nullptr;
24277 bool IsIndirect = false;
24278 if (DTCI.Indirect) {
24279 IndirectE = *DTCI.Indirect;
24280 if (!IndirectE)
24281 IsIndirect = true;
24282 }
24283 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
24284 getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level,
24285 SourceRange(Loc, Loc));
24286 ND->addAttr(A);
24287 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
24288 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
24289 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
24290 if (auto *VD = dyn_cast<VarDecl>(ND);
24291 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
24292 VD->hasGlobalStorage())
24294}
24295
24297 Sema &SemaRef, Decl *D) {
24298 if (!D || !isa<VarDecl>(D))
24299 return;
24300 auto *VD = cast<VarDecl>(D);
24301 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
24302 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
24303 if (SemaRef.LangOpts.OpenMP >= 50 &&
24304 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
24305 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
24306 VD->hasGlobalStorage()) {
24307 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
24308 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
24309 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
24310 // If a lambda declaration and definition appears between a
24311 // declare target directive and the matching end declare target
24312 // directive, all variables that are captured by the lambda
24313 // expression must also appear in a to clause.
24314 SemaRef.Diag(VD->getLocation(),
24315 diag::err_omp_lambda_capture_in_declare_target_not_to);
24316 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
24317 << VD << 0 << SR;
24318 return;
24319 }
24320 }
24321 if (MapTy)
24322 return;
24323 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
24324 SemaRef.Diag(SL, diag::note_used_here) << SR;
24325}
24326
24328 Sema &SemaRef, DSAStackTy *Stack,
24329 ValueDecl *VD) {
24330 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
24331 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
24332 /*FullCheck=*/false);
24333}
24334
24336 SourceLocation IdLoc) {
24337 if (!D || D->isInvalidDecl())
24338 return;
24339 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
24340 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
24341 if (auto *VD = dyn_cast<VarDecl>(D)) {
24342 // Only global variables can be marked as declare target.
24343 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24344 !VD->isStaticDataMember())
24345 return;
24346 // 2.10.6: threadprivate variable cannot appear in a declare target
24347 // directive.
24348 if (DSAStack->isThreadPrivate(VD)) {
24349 Diag(SL, diag::err_omp_threadprivate_in_target);
24350 reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false));
24351 return;
24352 }
24353 }
24354 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
24355 D = FTD->getTemplatedDecl();
24356 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
24357 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
24358 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
24359 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
24360 Diag(IdLoc, diag::err_omp_function_in_link_clause);
24361 Diag(FD->getLocation(), diag::note_defined_here) << FD;
24362 return;
24363 }
24364 }
24365 if (auto *VD = dyn_cast<ValueDecl>(D)) {
24366 // Problem if any with var declared with incomplete type will be reported
24367 // as normal, so no need to check it here.
24368 if ((E || !VD->getType()->isIncompleteType()) &&
24370 return;
24371 if (!E && isInOpenMPDeclareTargetContext()) {
24372 // Checking declaration inside declare target region.
24373 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
24375 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24376 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24377 unsigned Level = DeclareTargetNesting.size();
24378 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
24379 return;
24380 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
24381 Expr *IndirectE = nullptr;
24382 bool IsIndirect = false;
24383 if (DTCI.Indirect) {
24384 IndirectE = *DTCI.Indirect;
24385 if (!IndirectE)
24386 IsIndirect = true;
24387 }
24388 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
24389 getASTContext(),
24390 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
24391 : OMPDeclareTargetDeclAttr::MT_To,
24392 DTCI.DT, IndirectE, IsIndirect, Level,
24393 SourceRange(DTCI.Loc, DTCI.Loc));
24394 D->addAttr(A);
24395 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
24396 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
24397 }
24398 return;
24399 }
24400 }
24401 if (!E)
24402 return;
24404}
24405
24406/// This class visits every VarDecl that the initializer references and adds
24407/// OMPDeclareTargetDeclAttr to each of them.
24408class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
24409 SmallVector<VarDecl *> DeclVector;
24410 Attr *A;
24411
24412public:
24413 /// A StmtVisitor class function that visits all DeclRefExpr and adds
24414 /// OMPDeclareTargetDeclAttr to them.
24416 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
24417 VD->addAttr(A);
24418 DeclVector.push_back(VD);
24419 }
24420 }
24421 /// A function that iterates across each of the Expr's children.
24422 void VisitExpr(Expr *Ex) {
24423 for (auto *Child : Ex->children()) {
24424 Visit(Child);
24425 }
24426 }
24427 /// A function that keeps a record of all the Decls that are variables, has
24428 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
24429 /// each Decl one at a time and use the inherited 'visit' functions to look
24430 /// for DeclRefExpr.
24432 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
24433 DeclVector.push_back(cast<VarDecl>(TD));
24434 llvm::SmallDenseSet<Decl *> Visited;
24435 while (!DeclVector.empty()) {
24436 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
24437 if (!Visited.insert(TargetVarDecl).second)
24438 continue;
24439
24440 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
24441 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
24442 if (Expr *Ex = TargetVarDecl->getInit())
24443 Visit(Ex);
24444 }
24445 }
24446 }
24447};
24448
24449/// Adding OMPDeclareTargetDeclAttr to variables with static storage
24450/// duration that are referenced in the initializer expression list of
24451/// variables with static storage duration in declare target directive.
24453 GlobalDeclRefChecker Checker;
24454 if (isa<VarDecl>(TargetDecl))
24455 Checker.declareTargetInitializer(TargetDecl);
24456}
24457
24459 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
24460 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
24461 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
24462 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
24463 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
24468
24469 // Process motion-modifiers, flag errors for duplicate modifiers.
24470 unsigned Count = 0;
24471 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
24472 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
24473 llvm::is_contained(Modifiers, MotionModifiers[I])) {
24474 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
24475 continue;
24476 }
24477 assert(Count < NumberOfOMPMotionModifiers &&
24478 "Modifiers exceed the allowed number of motion modifiers");
24479 Modifiers[Count] = MotionModifiers[I];
24480 ModifiersLoc[Count] = MotionModifiersLoc[I];
24481 ++Count;
24482 }
24483
24484 MappableVarListInfo MVLI(VarList);
24486 MapperIdScopeSpec, MapperId, UnresolvedMappers);
24487 if (MVLI.ProcessedVarList.empty())
24488 return nullptr;
24489 if (IteratorExpr)
24490 if (auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
24491 if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
24492 DSAStack->addIteratorVarDecl(VD);
24493 return OMPToClause::Create(
24494 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24495 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
24496 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
24497 MapperId);
24498}
24499
24501 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
24502 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
24503 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
24504 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
24505 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
24510
24511 // Process motion-modifiers, flag errors for duplicate modifiers.
24512 unsigned Count = 0;
24513 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
24514 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
24515 llvm::is_contained(Modifiers, MotionModifiers[I])) {
24516 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
24517 continue;
24518 }
24519 assert(Count < NumberOfOMPMotionModifiers &&
24520 "Modifiers exceed the allowed number of motion modifiers");
24521 Modifiers[Count] = MotionModifiers[I];
24522 ModifiersLoc[Count] = MotionModifiersLoc[I];
24523 ++Count;
24524 }
24525
24526 MappableVarListInfo MVLI(VarList);
24527 checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
24528 MapperIdScopeSpec, MapperId, UnresolvedMappers);
24529 if (MVLI.ProcessedVarList.empty())
24530 return nullptr;
24531 if (IteratorExpr)
24532 if (auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
24533 if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
24534 DSAStack->addIteratorVarDecl(VD);
24535 return OMPFromClause::Create(
24536 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24537 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
24538 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
24539 MapperId);
24540}
24541
24542OMPClause *
24544 const OMPVarListLocTy &Locs) {
24545 MappableVarListInfo MVLI(VarList);
24546 SmallVector<Expr *, 8> PrivateCopies;
24548
24549 for (Expr *RefExpr : VarList) {
24550 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
24551 SourceLocation ELoc;
24552 SourceRange ERange;
24553 Expr *SimpleRefExpr = RefExpr;
24554 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24555 if (Res.second) {
24556 // It will be analyzed later.
24557 MVLI.ProcessedVarList.push_back(RefExpr);
24558 PrivateCopies.push_back(nullptr);
24559 Inits.push_back(nullptr);
24560 }
24561 ValueDecl *D = Res.first;
24562 if (!D)
24563 continue;
24564
24565 QualType Type = D->getType();
24566 Type = Type.getNonReferenceType().getUnqualifiedType();
24567
24568 auto *VD = dyn_cast<VarDecl>(D);
24569
24570 // Item should be a pointer or reference to pointer.
24571 if (!Type->isPointerType()) {
24572 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
24573 << 0 << RefExpr->getSourceRange();
24574 continue;
24575 }
24576
24577 // Build the private variable and the expression that refers to it.
24578 auto VDPrivate =
24579 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
24580 D->hasAttrs() ? &D->getAttrs() : nullptr,
24581 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
24582 if (VDPrivate->isInvalidDecl())
24583 continue;
24584
24585 SemaRef.CurContext->addDecl(VDPrivate);
24586 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
24587 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
24588
24589 // Add temporary variable to initialize the private copy of the pointer.
24590 VarDecl *VDInit =
24591 buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp");
24592 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
24593 SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
24594 SemaRef.AddInitializerToDecl(
24595 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
24596 /*DirectInit=*/false);
24597
24598 // If required, build a capture to implement the privatization initialized
24599 // with the current list item value.
24600 DeclRefExpr *Ref = nullptr;
24601 if (!VD)
24602 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
24603 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
24604 PrivateCopies.push_back(VDPrivateRefExpr);
24605 Inits.push_back(VDInitRefExpr);
24606
24607 // We need to add a data sharing attribute for this variable to make sure it
24608 // is correctly captured. A variable that shows up in a use_device_ptr has
24609 // similar properties of a first private variable.
24610 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24611
24612 // Create a mappable component for the list item. List items in this clause
24613 // only need a component.
24614 MVLI.VarBaseDeclarations.push_back(D);
24615 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24616 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
24617 /*IsNonContiguous=*/false);
24618 }
24619
24620 if (MVLI.ProcessedVarList.empty())
24621 return nullptr;
24622
24624 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
24625 MVLI.VarBaseDeclarations, MVLI.VarComponents);
24626}
24627
24628OMPClause *
24630 const OMPVarListLocTy &Locs) {
24631 MappableVarListInfo MVLI(VarList);
24632
24633 for (Expr *RefExpr : VarList) {
24634 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
24635 SourceLocation ELoc;
24636 SourceRange ERange;
24637 Expr *SimpleRefExpr = RefExpr;
24638 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24639 /*AllowArraySection=*/true,
24640 /*AllowAssumedSizeArray=*/true);
24641 if (Res.second) {
24642 // It will be analyzed later.
24643 MVLI.ProcessedVarList.push_back(RefExpr);
24644 }
24645 ValueDecl *D = Res.first;
24646 if (!D)
24647 continue;
24648 auto *VD = dyn_cast<VarDecl>(D);
24649
24650 // If required, build a capture to implement the privatization initialized
24651 // with the current list item value.
24652 DeclRefExpr *Ref = nullptr;
24653 if (!VD)
24654 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
24655 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
24656
24657 // We need to add a data sharing attribute for this variable to make sure it
24658 // is correctly captured. A variable that shows up in a use_device_addr has
24659 // similar properties of a first private variable.
24660 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24661
24662 // Create a mappable component for the list item. List items in this clause
24663 // only need a component.
24664 MVLI.VarBaseDeclarations.push_back(D);
24665 MVLI.VarComponents.emplace_back();
24666 Expr *Component = SimpleRefExpr;
24667 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
24668 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
24669 Component =
24670 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
24671 MVLI.VarComponents.back().emplace_back(Component, D,
24672 /*IsNonContiguous=*/false);
24673 }
24674
24675 if (MVLI.ProcessedVarList.empty())
24676 return nullptr;
24677
24679 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24680 MVLI.VarComponents);
24681}
24682
24683OMPClause *
24685 const OMPVarListLocTy &Locs) {
24686 MappableVarListInfo MVLI(VarList);
24687 for (Expr *RefExpr : VarList) {
24688 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
24689 SourceLocation ELoc;
24690 SourceRange ERange;
24691 Expr *SimpleRefExpr = RefExpr;
24692 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24693 if (Res.second) {
24694 // It will be analyzed later.
24695 MVLI.ProcessedVarList.push_back(RefExpr);
24696 }
24697 ValueDecl *D = Res.first;
24698 if (!D)
24699 continue;
24700
24701 QualType Type = D->getType();
24702 // item should be a pointer or array or reference to pointer or array
24703 if (!Type.getNonReferenceType()->isPointerType() &&
24704 !Type.getNonReferenceType()->isArrayType()) {
24705 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
24706 << 0 << RefExpr->getSourceRange();
24707 continue;
24708 }
24709
24710 // Check if the declaration in the clause does not show up in any data
24711 // sharing attribute.
24712 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
24713 if (isOpenMPPrivate(DVar.CKind)) {
24714 unsigned OMPVersion = getLangOpts().OpenMP;
24715 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24716 << getOpenMPClauseNameForDiag(DVar.CKind)
24717 << getOpenMPClauseNameForDiag(OMPC_is_device_ptr)
24718 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
24719 OMPVersion);
24721 continue;
24722 }
24723
24724 const Expr *ConflictExpr;
24725 if (DSAStack->checkMappableExprComponentListsForDecl(
24726 D, /*CurrentRegionOnly=*/true,
24727 [&ConflictExpr](
24729 OpenMPClauseKind) -> bool {
24730 ConflictExpr = R.front().getAssociatedExpression();
24731 return true;
24732 })) {
24733 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24734 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
24735 << ConflictExpr->getSourceRange();
24736 continue;
24737 }
24738
24739 // Store the components in the stack so that they can be used to check
24740 // against other clauses later on.
24742 SimpleRefExpr, D, /*IsNonContiguous=*/false);
24743 DSAStack->addMappableExpressionComponents(
24744 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
24745
24746 // Record the expression we've just processed.
24747 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
24748
24749 // Create a mappable component for the list item. List items in this clause
24750 // only need a component. We use a null declaration to signal fields in
24751 // 'this'.
24752 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
24753 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
24754 "Unexpected device pointer expression!");
24755 MVLI.VarBaseDeclarations.push_back(
24756 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
24757 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24758 MVLI.VarComponents.back().push_back(MC);
24759 }
24760
24761 if (MVLI.ProcessedVarList.empty())
24762 return nullptr;
24763
24765 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24766 MVLI.VarComponents);
24767}
24768
24769OMPClause *
24771 const OMPVarListLocTy &Locs) {
24772 MappableVarListInfo MVLI(VarList);
24773 for (Expr *RefExpr : VarList) {
24774 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
24775 SourceLocation ELoc;
24776 SourceRange ERange;
24777 Expr *SimpleRefExpr = RefExpr;
24778 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24779 /*AllowArraySection=*/true);
24780 if (Res.second) {
24781 // It will be analyzed later.
24782 MVLI.ProcessedVarList.push_back(RefExpr);
24783 }
24784 ValueDecl *D = Res.first;
24785 if (!D)
24786 continue;
24787
24788 // Check if the declaration in the clause does not show up in any data
24789 // sharing attribute.
24790 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
24791 if (isOpenMPPrivate(DVar.CKind)) {
24792 unsigned OMPVersion = getLangOpts().OpenMP;
24793 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24794 << getOpenMPClauseNameForDiag(DVar.CKind)
24795 << getOpenMPClauseNameForDiag(OMPC_has_device_addr)
24796 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
24797 OMPVersion);
24799 continue;
24800 }
24801
24802 const Expr *ConflictExpr;
24803 if (DSAStack->checkMappableExprComponentListsForDecl(
24804 D, /*CurrentRegionOnly=*/true,
24805 [&ConflictExpr](
24807 OpenMPClauseKind) -> bool {
24808 ConflictExpr = R.front().getAssociatedExpression();
24809 return true;
24810 })) {
24811 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24812 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
24813 << ConflictExpr->getSourceRange();
24814 continue;
24815 }
24816
24817 // Store the components in the stack so that they can be used to check
24818 // against other clauses later on.
24819 Expr *Component = SimpleRefExpr;
24820 auto *VD = dyn_cast<VarDecl>(D);
24821 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
24822 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
24823 Component =
24824 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
24826 Component, D, /*IsNonContiguous=*/false);
24827 DSAStack->addMappableExpressionComponents(
24828 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
24829
24830 // Record the expression we've just processed.
24831 if (!VD && !SemaRef.CurContext->isDependentContext()) {
24832 DeclRefExpr *Ref =
24833 buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
24834 assert(Ref && "has_device_addr capture failed");
24835 MVLI.ProcessedVarList.push_back(Ref);
24836 } else
24837 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
24838
24839 // Create a mappable component for the list item. List items in this clause
24840 // only need a component. We use a null declaration to signal fields in
24841 // 'this'.
24842 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
24843 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
24844 "Unexpected device pointer expression!");
24845 MVLI.VarBaseDeclarations.push_back(
24846 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
24847 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24848 MVLI.VarComponents.back().push_back(MC);
24849 }
24850
24851 if (MVLI.ProcessedVarList.empty())
24852 return nullptr;
24853
24855 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24856 MVLI.VarComponents);
24857}
24858
24860 Expr *Allocator, Expr *Alignment,
24861 OpenMPAllocateClauseModifier FirstAllocateModifier,
24862 SourceLocation FirstAllocateModifierLoc,
24863 OpenMPAllocateClauseModifier SecondAllocateModifier,
24864 SourceLocation SecondAllocateModifierLoc, ArrayRef<Expr *> VarList,
24865 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
24866 SourceLocation EndLoc) {
24867 if (Allocator) {
24868 // Allocator expression is dependent - skip it for now and build the
24869 // allocator when instantiated.
24870 bool AllocDependent =
24871 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
24872 Allocator->isInstantiationDependent() ||
24873 Allocator->containsUnexpandedParameterPack());
24874 if (!AllocDependent) {
24875 // OpenMP [2.11.4 allocate Clause, Description]
24876 // allocator is an expression of omp_allocator_handle_t type.
24878 return nullptr;
24879
24880 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
24881 if (AllocatorRes.isInvalid())
24882 return nullptr;
24883 AllocatorRes = SemaRef.PerformImplicitConversion(
24884 AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
24886 /*AllowExplicit=*/true);
24887 if (AllocatorRes.isInvalid())
24888 return nullptr;
24889 Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr;
24890 }
24891 } else {
24892 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
24893 // allocate clauses that appear on a target construct or on constructs in a
24894 // target region must specify an allocator expression unless a requires
24895 // directive with the dynamic_allocators clause is present in the same
24896 // compilation unit.
24897 if (getLangOpts().OpenMPIsTargetDevice &&
24898 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
24899 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
24900 }
24901 if (Alignment) {
24902 bool AlignmentDependent = Alignment->isTypeDependent() ||
24903 Alignment->isValueDependent() ||
24904 Alignment->isInstantiationDependent() ||
24906 if (!AlignmentDependent) {
24907 ExprResult AlignResult =
24908 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_allocate);
24909 Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr;
24910 }
24911 }
24912 // Analyze and build list of variables.
24914 for (Expr *RefExpr : VarList) {
24915 assert(RefExpr && "NULL expr in OpenMP allocate clause.");
24916 SourceLocation ELoc;
24917 SourceRange ERange;
24918 Expr *SimpleRefExpr = RefExpr;
24919 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24920 if (Res.second) {
24921 // It will be analyzed later.
24922 Vars.push_back(RefExpr);
24923 }
24924 ValueDecl *D = Res.first;
24925 if (!D)
24926 continue;
24927
24928 auto *VD = dyn_cast<VarDecl>(D);
24929 DeclRefExpr *Ref = nullptr;
24930 if (!VD && !SemaRef.CurContext->isDependentContext())
24931 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
24932 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
24933 ? RefExpr->IgnoreParens()
24934 : Ref);
24935 }
24936
24937 if (Vars.empty())
24938 return nullptr;
24939
24940 if (Allocator)
24941 DSAStack->addInnerAllocatorExpr(Allocator);
24942
24944 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
24945 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
24946 SecondAllocateModifierLoc, EndLoc, Vars);
24947}
24948
24950 SourceLocation StartLoc,
24951 SourceLocation LParenLoc,
24952 SourceLocation EndLoc) {
24954 for (Expr *RefExpr : VarList) {
24955 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
24956 SourceLocation ELoc;
24957 SourceRange ERange;
24958 Expr *SimpleRefExpr = RefExpr;
24959 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24960 if (Res.second)
24961 // It will be analyzed later.
24962 Vars.push_back(RefExpr);
24963 ValueDecl *D = Res.first;
24964 if (!D)
24965 continue;
24966
24967 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
24968 // A list-item cannot appear in more than one nontemporal clause.
24969 if (const Expr *PrevRef =
24970 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
24971 Diag(ELoc, diag::err_omp_used_in_clause_twice)
24972 << 0 << getOpenMPClauseNameForDiag(OMPC_nontemporal) << ERange;
24973 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
24974 << getOpenMPClauseNameForDiag(OMPC_nontemporal);
24975 continue;
24976 }
24977
24978 Vars.push_back(RefExpr);
24979 }
24980
24981 if (Vars.empty())
24982 return nullptr;
24983
24984 return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc,
24985 EndLoc, Vars);
24986}
24987
24989 Stmt *AStmt,
24990 SourceLocation StartLoc,
24991 SourceLocation EndLoc) {
24992 if (!AStmt)
24993 return StmtError();
24994
24995 SemaRef.setFunctionHasBranchProtectedScope();
24996
24997 return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
24998 AStmt);
24999}
25000
25002 SourceLocation StartLoc,
25003 SourceLocation LParenLoc,
25004 SourceLocation EndLoc) {
25006 for (Expr *RefExpr : VarList) {
25007 assert(RefExpr && "NULL expr in OpenMP inclusive clause.");
25008 SourceLocation ELoc;
25009 SourceRange ERange;
25010 Expr *SimpleRefExpr = RefExpr;
25011 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
25012 /*AllowArraySection=*/true);
25013 if (Res.second)
25014 // It will be analyzed later.
25015 Vars.push_back(RefExpr);
25016 ValueDecl *D = Res.first;
25017 if (!D)
25018 continue;
25019
25020 const DSAStackTy::DSAVarData DVar =
25021 DSAStack->getTopDSA(D, /*FromParent=*/true);
25022 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
25023 // A list item that appears in the inclusive or exclusive clause must appear
25024 // in a reduction clause with the inscan modifier on the enclosing
25025 // worksharing-loop, worksharing-loop SIMD, or simd construct.
25026 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
25027 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
25028 << RefExpr->getSourceRange();
25029
25030 if (DSAStack->getParentDirective() != OMPD_unknown)
25031 DSAStack->markDeclAsUsedInScanDirective(D);
25032 Vars.push_back(RefExpr);
25033 }
25034
25035 if (Vars.empty())
25036 return nullptr;
25037
25038 return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
25039 EndLoc, Vars);
25040}
25041
25043 SourceLocation StartLoc,
25044 SourceLocation LParenLoc,
25045 SourceLocation EndLoc) {
25047 for (Expr *RefExpr : VarList) {
25048 assert(RefExpr && "NULL expr in OpenMP exclusive clause.");
25049 SourceLocation ELoc;
25050 SourceRange ERange;
25051 Expr *SimpleRefExpr = RefExpr;
25052 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
25053 /*AllowArraySection=*/true);
25054 if (Res.second)
25055 // It will be analyzed later.
25056 Vars.push_back(RefExpr);
25057 ValueDecl *D = Res.first;
25058 if (!D)
25059 continue;
25060
25061 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
25062 DSAStackTy::DSAVarData DVar;
25063 if (ParentDirective != OMPD_unknown)
25064 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
25065 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
25066 // A list item that appears in the inclusive or exclusive clause must appear
25067 // in a reduction clause with the inscan modifier on the enclosing
25068 // worksharing-loop, worksharing-loop SIMD, or simd construct.
25069 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
25070 DVar.Modifier != OMPC_REDUCTION_inscan) {
25071 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
25072 << RefExpr->getSourceRange();
25073 } else {
25074 DSAStack->markDeclAsUsedInScanDirective(D);
25075 }
25076 Vars.push_back(RefExpr);
25077 }
25078
25079 if (Vars.empty())
25080 return nullptr;
25081
25082 return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
25083 EndLoc, Vars);
25084}
25085
25086/// Tries to find omp_alloctrait_t type.
25087static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
25088 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
25089 if (!OMPAlloctraitT.isNull())
25090 return true;
25091 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
25092 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
25093 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
25094 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
25095 return false;
25096 }
25097 Stack->setOMPAlloctraitT(PT.get());
25098 return true;
25099}
25100
25102 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
25104 ASTContext &Context = getASTContext();
25105 // OpenMP [2.12.5, target Construct]
25106 // allocator is an identifier of omp_allocator_handle_t type.
25107 if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack))
25108 return nullptr;
25109 // OpenMP [2.12.5, target Construct]
25110 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
25111 if (llvm::any_of(
25112 Data,
25113 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
25114 !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack))
25115 return nullptr;
25116 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
25117 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
25118 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
25119 StringRef Allocator =
25120 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
25121 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
25122 PredefinedAllocators.insert(SemaRef.LookupSingleName(
25123 SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
25124 }
25125
25127 for (const UsesAllocatorsData &D : Data) {
25128 Expr *AllocatorExpr = nullptr;
25129 // Check allocator expression.
25130 if (D.Allocator->isTypeDependent()) {
25131 AllocatorExpr = D.Allocator;
25132 } else {
25133 // Traits were specified - need to assign new allocator to the specified
25134 // allocator, so it must be an lvalue.
25135 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
25136 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
25137 bool IsPredefinedAllocator = false;
25138 if (DRE) {
25139 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
25140 getAllocatorKind(SemaRef, DSAStack, AllocatorExpr);
25141 IsPredefinedAllocator =
25142 AllocatorTy !=
25143 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
25144 }
25145 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
25146 QualType AllocatorExprType = AllocatorExpr->getType();
25147 bool IsTypeCompatible = IsPredefinedAllocator;
25148 IsTypeCompatible = IsTypeCompatible ||
25149 Context.hasSameUnqualifiedType(AllocatorExprType,
25150 OMPAllocatorHandleT);
25151 IsTypeCompatible =
25152 IsTypeCompatible ||
25153 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
25154 bool IsNonConstantLValue =
25155 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
25156 if (!DRE || !IsTypeCompatible ||
25157 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
25158 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
25159 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
25160 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
25161 continue;
25162 }
25163 // OpenMP [2.12.5, target Construct]
25164 // Predefined allocators appearing in a uses_allocators clause cannot have
25165 // traits specified.
25166 if (IsPredefinedAllocator && D.AllocatorTraits) {
25168 diag::err_omp_predefined_allocator_with_traits)
25170 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
25171 << cast<NamedDecl>(DRE->getDecl())->getName()
25172 << D.Allocator->getSourceRange();
25173 continue;
25174 }
25175 // OpenMP [2.12.5, target Construct]
25176 // Non-predefined allocators appearing in a uses_allocators clause must
25177 // have traits specified.
25178 if (getLangOpts().OpenMP < 52) {
25179 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
25181 diag::err_omp_nonpredefined_allocator_without_traits);
25182 continue;
25183 }
25184 }
25185 // No allocator traits - just convert it to rvalue.
25186 if (!D.AllocatorTraits)
25187 AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
25188 DSAStack->addUsesAllocatorsDecl(
25189 DRE->getDecl(),
25190 IsPredefinedAllocator
25191 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
25192 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
25193 }
25194 Expr *AllocatorTraitsExpr = nullptr;
25195 if (D.AllocatorTraits) {
25197 AllocatorTraitsExpr = D.AllocatorTraits;
25198 } else {
25199 // OpenMP [2.12.5, target Construct]
25200 // Arrays that contain allocator traits that appear in a uses_allocators
25201 // clause must be constant arrays, have constant values and be defined
25202 // in the same scope as the construct in which the clause appears.
25203 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
25204 // Check that traits expr is a constant array.
25205 QualType TraitTy;
25206 if (const ArrayType *Ty =
25207 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
25208 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
25209 TraitTy = ConstArrayTy->getElementType();
25210 if (TraitTy.isNull() ||
25211 !(Context.hasSameUnqualifiedType(TraitTy,
25212 DSAStack->getOMPAlloctraitT()) ||
25213 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
25214 /*CompareUnqualified=*/true))) {
25216 diag::err_omp_expected_array_alloctraits)
25217 << AllocatorTraitsExpr->getType();
25218 continue;
25219 }
25220 // Do not map by default allocator traits if it is a standalone
25221 // variable.
25222 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
25223 DSAStack->addUsesAllocatorsDecl(
25224 DRE->getDecl(),
25225 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
25226 }
25227 }
25228 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
25229 NewD.Allocator = AllocatorExpr;
25230 NewD.AllocatorTraits = AllocatorTraitsExpr;
25231 NewD.LParenLoc = D.LParenLoc;
25232 NewD.RParenLoc = D.RParenLoc;
25233 }
25234 return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc,
25235 EndLoc, NewData);
25236}
25237
25239 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
25240 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
25242 for (Expr *RefExpr : Locators) {
25243 assert(RefExpr && "NULL expr in OpenMP affinity clause.");
25244 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
25245 // It will be analyzed later.
25246 Vars.push_back(RefExpr);
25247 continue;
25248 }
25249
25250 SourceLocation ELoc = RefExpr->getExprLoc();
25251 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
25252
25253 if (!SimpleExpr->isLValue()) {
25254 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
25255 << 1 << 0 << RefExpr->getSourceRange();
25256 continue;
25257 }
25258
25259 ExprResult Res;
25260 {
25262 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
25263 }
25264 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
25266 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
25267 << 1 << 0 << RefExpr->getSourceRange();
25268 continue;
25269 }
25270 Vars.push_back(SimpleExpr);
25271 }
25272
25273 return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc,
25274 ColonLoc, EndLoc, Modifier, Vars);
25275}
25276
25278 SourceLocation KindLoc,
25279 SourceLocation StartLoc,
25280 SourceLocation LParenLoc,
25281 SourceLocation EndLoc) {
25282 if (Kind == OMPC_BIND_unknown) {
25283 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
25284 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
25285 /*Last=*/unsigned(OMPC_BIND_unknown))
25286 << getOpenMPClauseNameForDiag(OMPC_bind);
25287 return nullptr;
25288 }
25289
25290 return OMPBindClause::Create(getASTContext(), Kind, KindLoc, StartLoc,
25291 LParenLoc, EndLoc);
25292}
25293
25295 SourceLocation StartLoc,
25296 SourceLocation LParenLoc,
25297 SourceLocation EndLoc) {
25298 Expr *ValExpr = Size;
25299 Stmt *HelperValStmt = nullptr;
25300
25301 // OpenMP [2.5, Restrictions]
25302 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
25303 // value.
25304 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem,
25305 /*StrictlyPositive=*/false))
25306 return nullptr;
25307
25308 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
25310 DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP);
25311 if (CaptureRegion != OMPD_unknown &&
25312 !SemaRef.CurContext->isDependentContext()) {
25313 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
25314 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
25315 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
25316 HelperValStmt = buildPreInits(getASTContext(), Captures);
25317 }
25318
25320 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
25321}
25322
25326 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc,
25327 SourceLocation M2Loc, SourceLocation EndLoc) {
25328
25329 if ((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ||
25331 std::string Values = getListOfPossibleValues(
25332 OMPC_dyn_groupprivate, /*First=*/0, OMPC_DYN_GROUPPRIVATE_unknown);
25333 Diag((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ? M1Loc
25334 : M2Loc,
25335 diag::err_omp_unexpected_clause_value)
25336 << Values << getOpenMPClauseName(OMPC_dyn_groupprivate);
25337 return nullptr;
25338 }
25339
25340 Expr *ValExpr = Size;
25341 Stmt *HelperValStmt = nullptr;
25342
25343 // OpenMP [2.5, Restrictions]
25344 // The dyn_groupprivate expression must evaluate to a positive integer
25345 // value.
25346 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_dyn_groupprivate,
25347 /*StrictlyPositive=*/false))
25348 return nullptr;
25349
25350 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
25352 DKind, OMPC_dyn_groupprivate, getLangOpts().OpenMP);
25353 if (CaptureRegion != OMPD_unknown &&
25354 !SemaRef.CurContext->isDependentContext()) {
25355 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
25356 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
25357 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
25358 HelperValStmt = buildPreInits(getASTContext(), Captures);
25359 }
25360
25362 StartLoc, LParenLoc, EndLoc, ValExpr, HelperValStmt, CaptureRegion, M1,
25363 M1Loc, M2, M2Loc);
25364}
25365
25368 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
25369 SourceLocation LParenLoc, SourceLocation EndLoc) {
25370
25371 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
25372 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
25373 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
25374 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
25375 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
25376 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_doacross);
25377 return nullptr;
25378 }
25379
25381 DSAStackTy::OperatorOffsetTy OpsOffs;
25382 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
25383 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
25384 SemaRef,
25385 DepType == OMPC_DOACROSS_source ||
25386 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
25387 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
25388 VarList, DSAStack, EndLoc);
25389 Vars = VarOffset.Vars;
25390 OpsOffs = VarOffset.OpsOffs;
25391 TotalDepCount = VarOffset.TotalDepCount;
25392 auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc,
25393 EndLoc, DepType, DepLoc, ColonLoc, Vars,
25394 TotalDepCount.getZExtValue());
25395 if (DSAStack->isParentOrderedRegion())
25396 DSAStack->addDoacrossDependClause(C, OpsOffs);
25397 return C;
25398}
25399
25401 SourceLocation StartLoc,
25402 SourceLocation LParenLoc,
25403 SourceLocation EndLoc) {
25404 return new (getASTContext())
25405 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
25406}
25407
25409 SourceLocation EndLoc) {
25410 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
25411}
25412
25414 SourceLocation LParenLoc,
25415 SourceLocation EndLoc) {
25416 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
25417}
25418
25422 switch (CK) {
25423 case OMPC_absent:
25424 return OMPAbsentClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
25425 case OMPC_contains:
25426 return OMPContainsClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
25427 default:
25428 llvm_unreachable("Unexpected OpenMP clause");
25429 }
25430}
25431
25433 SourceLocation Loc,
25434 SourceLocation RLoc) {
25435 switch (CK) {
25436 case OMPC_no_openmp:
25437 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
25438 case OMPC_no_openmp_routines:
25439 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
25440 case OMPC_no_parallelism:
25441 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
25442 case OMPC_no_openmp_constructs:
25443 return new (getASTContext()) OMPNoOpenMPConstructsClause(Loc, RLoc);
25444 default:
25445 llvm_unreachable("Unexpected OpenMP clause");
25446 }
25447}
25448
25450 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
25451 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
25452 Expr *Stride, SourceLocation RBLoc) {
25453 ASTContext &Context = getASTContext();
25454 if (Base->hasPlaceholderType() &&
25455 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
25456 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
25457 if (Result.isInvalid())
25458 return ExprError();
25459 Base = Result.get();
25460 }
25461 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
25462 ExprResult Result = SemaRef.CheckPlaceholderExpr(LowerBound);
25463 if (Result.isInvalid())
25464 return ExprError();
25465 Result = SemaRef.DefaultLvalueConversion(Result.get());
25466 if (Result.isInvalid())
25467 return ExprError();
25468 LowerBound = Result.get();
25469 }
25470 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
25471 ExprResult Result = SemaRef.CheckPlaceholderExpr(Length);
25472 if (Result.isInvalid())
25473 return ExprError();
25474 Result = SemaRef.DefaultLvalueConversion(Result.get());
25475 if (Result.isInvalid())
25476 return ExprError();
25477 Length = Result.get();
25478 }
25479 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
25480 ExprResult Result = SemaRef.CheckPlaceholderExpr(Stride);
25481 if (Result.isInvalid())
25482 return ExprError();
25483 Result = SemaRef.DefaultLvalueConversion(Result.get());
25484 if (Result.isInvalid())
25485 return ExprError();
25486 Stride = Result.get();
25487 }
25488
25489 // Build an unanalyzed expression if either operand is type-dependent.
25490 if (Base->isTypeDependent() ||
25491 (LowerBound &&
25492 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
25493 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
25494 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
25495 return new (Context) ArraySectionExpr(
25496 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
25497 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
25498 }
25499
25500 // Perform default conversions.
25502 QualType ResultTy;
25503 if (OriginalTy->isAnyPointerType()) {
25504 ResultTy = OriginalTy->getPointeeType();
25505 } else if (OriginalTy->isArrayType()) {
25506 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
25507 } else {
25508 return ExprError(
25509 Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
25510 << Base->getSourceRange());
25511 }
25512 // C99 6.5.2.1p1
25513 if (LowerBound) {
25514 auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
25515 LowerBound);
25516 if (Res.isInvalid())
25517 return ExprError(Diag(LowerBound->getExprLoc(),
25518 diag::err_omp_typecheck_section_not_integer)
25519 << 0 << LowerBound->getSourceRange());
25520 LowerBound = Res.get();
25521
25522 if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25523 LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25524 Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
25525 << 0 << LowerBound->getSourceRange();
25526 }
25527 if (Length) {
25528 auto Res =
25529 PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
25530 if (Res.isInvalid())
25531 return ExprError(Diag(Length->getExprLoc(),
25532 diag::err_omp_typecheck_section_not_integer)
25533 << 1 << Length->getSourceRange());
25534 Length = Res.get();
25535
25536 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25537 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25538 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
25539 << 1 << Length->getSourceRange();
25540 }
25541 if (Stride) {
25542 ExprResult Res =
25544 if (Res.isInvalid())
25545 return ExprError(Diag(Stride->getExprLoc(),
25546 diag::err_omp_typecheck_section_not_integer)
25547 << 1 << Stride->getSourceRange());
25548 Stride = Res.get();
25549
25550 if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25551 Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25552 Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
25553 << 1 << Stride->getSourceRange();
25554 }
25555
25556 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
25557 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
25558 // type. Note that functions are not objects, and that (in C99 parlance)
25559 // incomplete types are not object types.
25560 if (ResultTy->isFunctionType()) {
25561 Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
25562 << ResultTy << Base->getSourceRange();
25563 return ExprError();
25564 }
25565
25566 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
25567 diag::err_omp_section_incomplete_type, Base))
25568 return ExprError();
25569
25570 if (LowerBound && !OriginalTy->isAnyPointerType()) {
25572 if (LowerBound->EvaluateAsInt(Result, Context)) {
25573 // OpenMP 5.0, [2.1.5 Array Sections]
25574 // The array section must be a subset of the original array.
25575 llvm::APSInt LowerBoundValue = Result.Val.getInt();
25576 if (LowerBoundValue.isNegative()) {
25577 Diag(LowerBound->getExprLoc(),
25578 diag::err_omp_section_not_subset_of_array)
25579 << LowerBound->getSourceRange();
25580 return ExprError();
25581 }
25582 }
25583 }
25584
25585 if (Length) {
25587 if (Length->EvaluateAsInt(Result, Context)) {
25588 // OpenMP 5.0, [2.1.5 Array Sections]
25589 // The length must evaluate to non-negative integers.
25590 llvm::APSInt LengthValue = Result.Val.getInt();
25591 if (LengthValue.isNegative()) {
25592 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
25593 << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
25594 << Length->getSourceRange();
25595 return ExprError();
25596 }
25597 }
25598 } else if (SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.isValid() &&
25599 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
25600 !OriginalTy->isVariableArrayType()))) {
25601 // OpenMP 5.0, [2.1.5 Array Sections]
25602 // When the size of the array dimension is not known, the length must be
25603 // specified explicitly.
25604 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
25605 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
25606 return ExprError();
25607 }
25608
25609 if (Stride) {
25611 if (Stride->EvaluateAsInt(Result, Context)) {
25612 // OpenMP 5.0, [2.1.5 Array Sections]
25613 // The stride must evaluate to a positive integer.
25614 llvm::APSInt StrideValue = Result.Val.getInt();
25615 if (!StrideValue.isStrictlyPositive()) {
25616 Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
25617 << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
25618 << Stride->getSourceRange();
25619 return ExprError();
25620 }
25621 }
25622 }
25623
25624 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
25625 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(Base);
25626 if (Result.isInvalid())
25627 return ExprError();
25628 Base = Result.get();
25629 }
25630 return new (Context) ArraySectionExpr(
25631 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
25632 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
25633}
25634
25636 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
25637 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
25638 ASTContext &Context = getASTContext();
25639 if (Base->hasPlaceholderType()) {
25640 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
25641 if (Result.isInvalid())
25642 return ExprError();
25643 Result = SemaRef.DefaultLvalueConversion(Result.get());
25644 if (Result.isInvalid())
25645 return ExprError();
25646 Base = Result.get();
25647 }
25648 QualType BaseTy = Base->getType();
25649 // Delay analysis of the types/expressions if instantiation/specialization is
25650 // required.
25651 if (!BaseTy->isPointerType() && Base->isTypeDependent())
25652 return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
25653 LParenLoc, RParenLoc, Dims, Brackets);
25654 if (!BaseTy->isPointerType() ||
25655 (!Base->isTypeDependent() &&
25656 BaseTy->getPointeeType()->isIncompleteType()))
25657 return ExprError(Diag(Base->getExprLoc(),
25658 diag::err_omp_non_pointer_type_array_shaping_base)
25659 << Base->getSourceRange());
25660
25661 SmallVector<Expr *, 4> NewDims;
25662 bool ErrorFound = false;
25663 for (Expr *Dim : Dims) {
25664 if (Dim->hasPlaceholderType()) {
25665 ExprResult Result = SemaRef.CheckPlaceholderExpr(Dim);
25666 if (Result.isInvalid()) {
25667 ErrorFound = true;
25668 continue;
25669 }
25670 Result = SemaRef.DefaultLvalueConversion(Result.get());
25671 if (Result.isInvalid()) {
25672 ErrorFound = true;
25673 continue;
25674 }
25675 Dim = Result.get();
25676 }
25677 if (!Dim->isTypeDependent()) {
25680 if (Result.isInvalid()) {
25681 ErrorFound = true;
25682 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
25683 << Dim->getSourceRange();
25684 continue;
25685 }
25686 Dim = Result.get();
25687 Expr::EvalResult EvResult;
25688 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
25689 // OpenMP 5.0, [2.1.4 Array Shaping]
25690 // Each si is an integral type expression that must evaluate to a
25691 // positive integer.
25692 llvm::APSInt Value = EvResult.Val.getInt();
25693 if (!Value.isStrictlyPositive()) {
25694 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
25695 << toString(Value, /*Radix=*/10, /*Signed=*/true)
25696 << Dim->getSourceRange();
25697 ErrorFound = true;
25698 continue;
25699 }
25700 }
25701 }
25702 NewDims.push_back(Dim);
25703 }
25704 if (ErrorFound)
25705 return ExprError();
25706 return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
25707 LParenLoc, RParenLoc, NewDims, Brackets);
25708}
25709
25711 SourceLocation IteratorKwLoc,
25712 SourceLocation LLoc,
25713 SourceLocation RLoc,
25715 ASTContext &Context = getASTContext();
25717 bool IsCorrect = true;
25718 for (const OMPIteratorData &D : Data) {
25719 TypeSourceInfo *TInfo = nullptr;
25720 SourceLocation StartLoc;
25721 QualType DeclTy;
25722 if (!D.Type.getAsOpaquePtr()) {
25723 // OpenMP 5.0, 2.1.6 Iterators
25724 // In an iterator-specifier, if the iterator-type is not specified then
25725 // the type of that iterator is of int type.
25726 DeclTy = Context.IntTy;
25727 StartLoc = D.DeclIdentLoc;
25728 } else {
25729 DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo);
25730 StartLoc = TInfo->getTypeLoc().getBeginLoc();
25731 }
25732
25733 bool IsDeclTyDependent = DeclTy->isDependentType() ||
25734 DeclTy->containsUnexpandedParameterPack() ||
25735 DeclTy->isInstantiationDependentType();
25736 if (!IsDeclTyDependent) {
25737 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
25738 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
25739 // The iterator-type must be an integral or pointer type.
25740 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25741 << DeclTy;
25742 IsCorrect = false;
25743 continue;
25744 }
25745 if (DeclTy.isConstant(Context)) {
25746 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
25747 // The iterator-type must not be const qualified.
25748 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25749 << DeclTy;
25750 IsCorrect = false;
25751 continue;
25752 }
25753 }
25754
25755 // Iterator declaration.
25756 assert(D.DeclIdent && "Identifier expected.");
25757 // Always try to create iterator declarator to avoid extra error messages
25758 // about unknown declarations use.
25759 auto *VD =
25760 VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc,
25761 D.DeclIdent, DeclTy, TInfo, SC_None);
25762 VD->setImplicit();
25763 if (S) {
25764 // Check for conflicting previous declaration.
25765 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
25768 Previous.suppressDiagnostics();
25769 SemaRef.LookupName(Previous, S);
25770
25771 SemaRef.FilterLookupForScope(Previous, SemaRef.CurContext, S,
25772 /*ConsiderLinkage=*/false,
25773 /*AllowInlineNamespace=*/false);
25774 if (!Previous.empty()) {
25775 NamedDecl *Old = Previous.getRepresentativeDecl();
25776 Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
25777 Diag(Old->getLocation(), diag::note_previous_definition);
25778 } else {
25779 SemaRef.PushOnScopeChains(VD, S);
25780 }
25781 } else {
25782 SemaRef.CurContext->addDecl(VD);
25783 }
25784
25785 /// Act on the iterator variable declaration.
25787
25788 Expr *Begin = D.Range.Begin;
25789 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
25790 ExprResult BeginRes = SemaRef.PerformImplicitConversion(
25791 Begin, DeclTy, AssignmentAction::Converting);
25792 Begin = BeginRes.get();
25793 }
25794 Expr *End = D.Range.End;
25795 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
25796 ExprResult EndRes = SemaRef.PerformImplicitConversion(
25797 End, DeclTy, AssignmentAction::Converting);
25798 End = EndRes.get();
25799 }
25800 Expr *Step = D.Range.Step;
25801 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
25802 if (!Step->getType()->isIntegralType(Context)) {
25803 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
25804 << Step << Step->getSourceRange();
25805 IsCorrect = false;
25806 continue;
25807 }
25808 std::optional<llvm::APSInt> Result =
25809 Step->getIntegerConstantExpr(Context);
25810 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
25811 // If the step expression of a range-specification equals zero, the
25812 // behavior is unspecified.
25813 if (Result && Result->isZero()) {
25814 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
25815 << Step << Step->getSourceRange();
25816 IsCorrect = false;
25817 continue;
25818 }
25819 }
25820 if (!Begin || !End || !IsCorrect) {
25821 IsCorrect = false;
25822 continue;
25823 }
25824 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
25825 IDElem.IteratorDecl = VD;
25826 IDElem.AssignmentLoc = D.AssignLoc;
25827 IDElem.Range.Begin = Begin;
25828 IDElem.Range.End = End;
25829 IDElem.Range.Step = Step;
25830 IDElem.ColonLoc = D.ColonLoc;
25831 IDElem.SecondColonLoc = D.SecColonLoc;
25832 }
25833 if (!IsCorrect) {
25834 // Invalidate all created iterator declarations if error is found.
25835 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
25836 if (Decl *ID = D.IteratorDecl)
25837 ID->setInvalidDecl();
25838 }
25839 return ExprError();
25840 }
25842 if (!SemaRef.CurContext->isDependentContext()) {
25843 // Build number of ityeration for each iteration range.
25844 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
25845 // ((Begini-Stepi-1-Endi) / -Stepi);
25847 // (Endi - Begini)
25848 ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub,
25849 D.Range.End, D.Range.Begin);
25850 if (!Res.isUsable()) {
25851 IsCorrect = false;
25852 continue;
25853 }
25854 ExprResult St, St1;
25855 if (D.Range.Step) {
25856 St = D.Range.Step;
25857 // (Endi - Begini) + Stepi
25858 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(),
25859 St.get());
25860 if (!Res.isUsable()) {
25861 IsCorrect = false;
25862 continue;
25863 }
25864 // (Endi - Begini) + Stepi - 1
25865 Res = SemaRef.CreateBuiltinBinOp(
25866 D.AssignmentLoc, BO_Sub, Res.get(),
25867 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
25868 if (!Res.isUsable()) {
25869 IsCorrect = false;
25870 continue;
25871 }
25872 // ((Endi - Begini) + Stepi - 1) / Stepi
25873 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(),
25874 St.get());
25875 if (!Res.isUsable()) {
25876 IsCorrect = false;
25877 continue;
25878 }
25879 St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
25880 D.Range.Step);
25881 // (Begini - Endi)
25882 ExprResult Res1 = SemaRef.CreateBuiltinBinOp(
25883 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
25884 if (!Res1.isUsable()) {
25885 IsCorrect = false;
25886 continue;
25887 }
25888 // (Begini - Endi) - Stepi
25889 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(),
25890 St1.get());
25891 if (!Res1.isUsable()) {
25892 IsCorrect = false;
25893 continue;
25894 }
25895 // (Begini - Endi) - Stepi - 1
25896 Res1 = SemaRef.CreateBuiltinBinOp(
25897 D.AssignmentLoc, BO_Sub, Res1.get(),
25898 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
25899 if (!Res1.isUsable()) {
25900 IsCorrect = false;
25901 continue;
25902 }
25903 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
25904 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(),
25905 St1.get());
25906 if (!Res1.isUsable()) {
25907 IsCorrect = false;
25908 continue;
25909 }
25910 // Stepi > 0.
25911 ExprResult CmpRes = SemaRef.CreateBuiltinBinOp(
25912 D.AssignmentLoc, BO_GT, D.Range.Step,
25913 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
25914 if (!CmpRes.isUsable()) {
25915 IsCorrect = false;
25916 continue;
25917 }
25918 Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
25919 CmpRes.get(), Res.get(), Res1.get());
25920 if (!Res.isUsable()) {
25921 IsCorrect = false;
25922 continue;
25923 }
25924 }
25925 Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false);
25926 if (!Res.isUsable()) {
25927 IsCorrect = false;
25928 continue;
25929 }
25930
25931 // Build counter update.
25932 // Build counter.
25933 auto *CounterVD = VarDecl::Create(Context, SemaRef.CurContext,
25934 D.IteratorDecl->getBeginLoc(),
25935 D.IteratorDecl->getBeginLoc(), nullptr,
25936 Res.get()->getType(), nullptr, SC_None);
25937 CounterVD->setImplicit();
25938 ExprResult RefRes =
25939 SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue,
25940 D.IteratorDecl->getBeginLoc());
25941 // Build counter update.
25942 // I = Begini + counter * Stepi;
25943 ExprResult UpdateRes;
25944 if (D.Range.Step) {
25945 UpdateRes = SemaRef.CreateBuiltinBinOp(
25946 D.AssignmentLoc, BO_Mul,
25947 SemaRef.DefaultLvalueConversion(RefRes.get()).get(), St.get());
25948 } else {
25949 UpdateRes = SemaRef.DefaultLvalueConversion(RefRes.get());
25950 }
25951 if (!UpdateRes.isUsable()) {
25952 IsCorrect = false;
25953 continue;
25954 }
25955 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
25956 D.Range.Begin, UpdateRes.get());
25957 if (!UpdateRes.isUsable()) {
25958 IsCorrect = false;
25959 continue;
25960 }
25961 ExprResult VDRes =
25962 SemaRef.BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl),
25963 cast<VarDecl>(D.IteratorDecl)->getType(),
25964 VK_LValue, D.IteratorDecl->getBeginLoc());
25965 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
25966 VDRes.get(), UpdateRes.get());
25967 if (!UpdateRes.isUsable()) {
25968 IsCorrect = false;
25969 continue;
25970 }
25971 UpdateRes =
25972 SemaRef.ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true);
25973 if (!UpdateRes.isUsable()) {
25974 IsCorrect = false;
25975 continue;
25976 }
25977 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
25978 D.AssignmentLoc, UO_PreInc, RefRes.get());
25979 if (!CounterUpdateRes.isUsable()) {
25980 IsCorrect = false;
25981 continue;
25982 }
25983 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(CounterUpdateRes.get(),
25984 /*DiscardedValue=*/true);
25985 if (!CounterUpdateRes.isUsable()) {
25986 IsCorrect = false;
25987 continue;
25988 }
25989 OMPIteratorHelperData &HD = Helpers.emplace_back();
25990 HD.CounterVD = CounterVD;
25991 HD.Upper = Res.get();
25992 HD.Update = UpdateRes.get();
25993 HD.CounterUpdate = CounterUpdateRes.get();
25994 }
25995 } else {
25996 Helpers.assign(ID.size(), {});
25997 }
25998 if (!IsCorrect) {
25999 // Invalidate all created iterator declarations if error is found.
26000 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
26001 if (Decl *ID = D.IteratorDecl)
26002 ID->setInvalidDecl();
26003 }
26004 return ExprError();
26005 }
26006 return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc,
26007 LLoc, RLoc, ID, Helpers);
26008}
26009
26010/// Check if \p AssumptionStr is a known assumption and warn if not.
26012 StringRef AssumptionStr) {
26013 if (llvm::getKnownAssumptionStrings().count(AssumptionStr))
26014 return;
26015
26016 unsigned BestEditDistance = 3;
26017 StringRef Suggestion;
26018 for (const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) {
26019 unsigned EditDistance =
26020 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
26021 if (EditDistance < BestEditDistance) {
26022 Suggestion = KnownAssumptionIt.getKey();
26023 BestEditDistance = EditDistance;
26024 }
26025 }
26026
26027 if (!Suggestion.empty())
26028 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
26029 << AssumptionStr << Suggestion;
26030 else
26031 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
26032 << AssumptionStr;
26033}
26034
26036 // Handle the case where the attribute has a text message.
26037 StringRef Str;
26038 SourceLocation AttrStrLoc;
26039 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
26040 return;
26041
26042 checkOMPAssumeAttr(SemaRef, AttrStrLoc, Str);
26043
26044 D->addAttr(::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
26045}
26046
26048 : 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 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 OMPAssumeDirective * Create(const ASTContext &Ctx, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AStmt)
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.
static OMPDispatchDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, SourceLocation TargetCallLoc)
Creates directive with a list of Clauses.
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.
static OMPErrorDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
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.
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 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.
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.
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'.
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 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 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'.
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:780
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:856
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:776
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:895
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:7105
Expr * getBase()
Get base of the array section.
Definition Expr.h:7183
Expr * getLength()
Get length of array section.
Definition Expr.h:7193
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition Expr.cpp:5266
Expr * getLowerBound()
Get lower bound of array section.
Definition Expr.h:7187
SourceLocation getColonLocFirst() const
Definition Expr.h:7214
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3722
QualType getElementType() const
Definition TypeBase.h:3734
Attr - This represents one attribute.
Definition Attr.h:45
Represents an attribute applied to a statement.
Definition Stmt.h:2182
static AttributedStmt * Create(const ASTContext &C, SourceLocation Loc, ArrayRef< const Attr * > Attrs, Stmt *SubStmt)
Definition Stmt.cpp:436
SourceLocation getBeginLoc() const
Definition Stmt.h:2221
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:3972
Expr * getLHS() const
Definition Expr.h:4022
static bool isRelationalOp(Opcode Opc)
Definition Expr.h:4066
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition Expr.cpp:2176
static Opcode getOpForCompoundAssignment(Opcode Opc)
Definition Expr.h:4119
SourceLocation getOperatorLoc() const
Definition Expr.h:4014
SourceLocation getExprLoc() const
Definition Expr.h:4013
static Opcode reverseComparisonOp(Opcode Opc)
Definition Expr.h:4091
Expr * getRHS() const
Definition Expr.h:4024
Opcode getOpcode() const
Definition Expr.h:4017
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition Expr.cpp:2138
BinaryOperatorKind Opcode
Definition Expr.h:3977
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:2943
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:2877
SourceLocation getBeginLoc() const
Definition Expr.h:3211
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:1513
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3060
Expr * getCallee()
Definition Expr.h:3024
arg_range arguments()
Definition Expr.h:3129
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:4940
unsigned getNumParams() const
Definition Decl.h:4978
void setNothrow(bool Nothrow=true)
Definition Decl.cpp:5629
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:5625
ImplicitParamDecl * getParam(unsigned i) const
Definition Decl.h:4980
This captures a statement into a function.
Definition Stmt.h:3865
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
Definition Stmt.cpp:1455
SourceRange getSourceRange() const LLVM_READONLY
Definition Stmt.h:4068
Stmt * getCapturedStmt()
Retrieve the statement being captured.
Definition Stmt.h:3969
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
Definition Stmt.cpp:1479
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.h:4060
capture_range captures()
Definition Stmt.h:4003
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3610
Declaration of a class template.
Complex values, per C99 6.2.5p11.
Definition TypeBase.h:3275
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition Stmt.h:1719
SourceLocation getBeginLoc() const
Definition Stmt.h:1833
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
Definition Stmt.cpp:394
ConditionalOperator - The ?
Definition Expr.h:4325
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:484
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:547
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:1610
SourceLocation getEndLoc() const
Definition Stmt.h:1633
const DeclGroupRef getDeclGroup() const
Definition Stmt.h:1628
const Decl * getSingleDecl() const
Definition Stmt.h:1625
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.h:1636
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:3091
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:3103
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:3086
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3074
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:3082
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:3066
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:273
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:4822
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:1072
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition Stmt.h:2867
Stmt * getBody()
Definition Stmt.h:2911
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:3822
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:5254
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:2238
Stmt * getThen()
Definition Stmt.h:2327
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:1006
Expr * getCond()
Definition Stmt.h:2315
Stmt * getElse()
Definition Stmt.h:2336
SourceLocation getBeginLoc() const
Definition Stmt.h:2450
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:2069
ImplicitConversionSequence - Represents an implicit conversion sequence, which may be a standard conv...
Definition Overload.h:618
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:971
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:3381
Expr * getBase() const
Definition Expr.h:3375
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:3359
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:3493
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:1841
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 OMPAbsentClause * Create(const ASTContext &C, ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
This represents 'acq_rel' clause in the 'pragma omp atomic|flush' directives.
This represents 'acquire' clause in the 'pragma omp atomic|flush' directives.
static OMPAffinityClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Creates clause with a modifier a list of locator items.
static OMPAlignClause * Create(const ASTContext &C, Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'align' clause with the given alignment.
static OMPAlignedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Expr *A)
Creates clause with a list of variables VL and alignment A.
static OMPAllocateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, Expr *Allocator, 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:5374
This represents 'at' clause in the 'pragma omp error' directive.
SourceLocation getAtKindKwLoc() const
Returns location of clause kind.
OpenMPAtClauseKind getAtKind() const
Returns kind of the clause.
This represents 'atomic_default_mem_order' clause in the 'pragma omp requires' directive.
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').
This represents 'capture' clause in the 'pragma omp atomic' directive.
Pseudo declaration for capturing expressions.
Definition DeclOpenMP.h:445
static OMPCapturedExprDecl * Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, QualType T, SourceLocation StartLoc)
Class that represents a component of a mappable expression.
ArrayRef< MappableComponent > MappableExprComponentListRef
SmallVector< MappableComponent, 8 > MappableExprComponentList
SmallVector< MappableExprComponentList, 8 > MappableExprComponentLists
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 'compare' clause in the 'pragma omp atomic' directive.
static OMPContainsClause * Create(const ASTContext &C, ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
static OMPCopyinClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
static OMPCopyprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
This represents 'pragma omp 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 '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.
This represents 'dist_schedule' clause in the 'pragma omp ...' directive.
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 ....
This represents 'dynamic_allocators' clause in the 'pragma omp requires' directive.
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 'fail' clause in the 'pragma omp atomic' directive.
This represents 'filter' clause in the 'pragma omp ...' directive.
This represents 'final' clause in the 'pragma omp ...' directive.
static OMPFirstprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PrivateVL, ArrayRef< Expr * > InitVL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents implicit clause 'flush' for the 'pragma omp flush' directive.
static OMPFlushClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static 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.
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 'grainsize' clause in the 'pragma omp ...' directive.
This represents 'pragma omp groupprivate ...' directive.
Definition DeclOpenMP.h:173
static OMPGroupPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
static OMPHasDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
This represents 'hint' clause in the 'pragma omp ...' directive.
This represents the 'holds' clause in the 'pragma omp assume' directive.
This represents 'if' clause in the 'pragma omp ...' directive.
static OMPInReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > TaskgroupDescriptors, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
static OMPInclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPInitClause * Create(const ASTContext &C, Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Creates a fully specified clause.
static OMPIsDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPIteratorExpr * Create(const ASTContext &Context, QualType T, SourceLocation IteratorKwLoc, SourceLocation L, SourceLocation R, ArrayRef< IteratorDefinition > Data, ArrayRef< OMPIteratorHelperData > Helpers)
Definition Expr.cpp:5501
This represents clause 'lastprivate' in the 'pragma omp ...' directives.
static OMPLastprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
This represents clause 'linear' in the 'pragma omp ...' directives.
static OMPLinearClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation StepModifierLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PL, ArrayRef< Expr * > IL, Expr *Step, Expr *CalcStep, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL and a linear step Step.
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.
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.
This represents 'mergeable' clause in the 'pragma omp ...' directive.
This represents the 'message' clause in the 'pragma omp error' and the 'pragma omp parallel' directiv...
Expr * getMessageString() const
Returns message string of the clause.
std::optional< std::string > tryEvaluateString(ASTContext &Ctx) const
Try to evaluate the message string at compile time.
This represents the 'no_openmp' clause in the 'pragma omp assume' directive.
This represents the 'no_openmp_constructs' clause in the.
This represents the 'no_openmp_routines' clause in the 'pragma omp assume' directive.
This represents the 'no_parallelism' clause in the 'pragma omp assume' directive.
This represents 'nocontext' clause in the 'pragma omp ...' directive.
This represents 'nogroup' clause in the 'pragma omp ...' directive.
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 'nowait' clause in the 'pragma omp ...' directive.
This represents 'num_tasks' clause in the 'pragma omp ...' directive.
static OMPNumTeamsClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
This represents 'order' clause in the 'pragma omp ...' directive.
SourceLocation getKindKwLoc() const
Returns location of clause kind.
OpenMPOrderClauseKind getKind() const
Returns kind of the clause.
This represents 'ordered' clause in the 'pragma omp ...' directive.
Expr * getNumForLoops() const
Return the number of associated for-loops.
static OMPOrderedClause * Create(const ASTContext &C, Expr *Num, unsigned NumLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'ordered' clause.
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 'priority' clause in the 'pragma omp ...' directive.
static OMPPrivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PrivateVL)
Creates clause with a list of variables VL.
This represents 'proc_bind' clause in the 'pragma omp ...' directive.
This represents 'read' clause in the 'pragma omp atomic' directive.
static OMPReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, OpenMPReductionClauseModifier Modifier, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > CopyOps, ArrayRef< Expr * > CopyArrayTemps, ArrayRef< Expr * > CopyArrayElems, Stmt *PreInit, Expr *PostUpdate, ArrayRef< bool > IsPrivateVarReduction, OpenMPOriginalSharingModifier OriginalSharingModifier)
Creates clause with a list of variables VL.
This represents 'relaxed' clause in the 'pragma omp atomic' directives.
This represents 'release' clause in the 'pragma omp atomic|flush' directives.
This represents 'pragma omp requires...' directive.
Definition DeclOpenMP.h: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 'reverse_offload' clause in the 'pragma omp requires' directive.
This represents 'simd' clause in the 'pragma omp ...' directive.
This represents 'safelen' clause in the 'pragma omp ...' directive.
Expr * getSafelen() const
Return safe iteration space distance.
This represents 'schedule' clause in the 'pragma omp ...' directive.
SourceLocation getFirstScheduleModifierLoc() const
Get the first modifier location.
OpenMPScheduleClauseModifier getSecondScheduleModifier() const
Get the second modifier of the clause.
OpenMPScheduleClauseModifier getFirstScheduleModifier() const
Get the first modifier of the clause.
SourceLocation getSecondScheduleModifierLoc() const
Get the second modifier location.
This represents 'self_maps' clause in the 'pragma omp requires' directive.
This represents 'seq_cst' clause in the 'pragma omp atomic|flush' directives.
This represents the 'severity' clause in the 'pragma omp error' and the 'pragma omp parallel' directi...
OpenMPSeverityClauseKind getSeverityKind() const
Returns kind of the clause.
SourceLocation getSeverityKindKwLoc() const
Returns location of clause kind.
static OMPSharedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
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.
static OMPTaskReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
static OMPThreadLimitClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents 'pragma omp threadprivate ...' directive.
Definition DeclOpenMP.h:110
static OMPThreadPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
This represents 'threads' clause in the 'pragma omp ...' directive.
This represents 'threadset' clause in the 'pragma omp task ...' directive.
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.
Helper data structure representing the traits in a match clause of an declare variant or metadirectiv...
bool isExtensionActive(llvm::omp::TraitProperty TP)
Check the extension trait TP is active.
bool anyScoreOrCondition(llvm::function_ref< bool(Expr *&, bool)> Cond)
void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const
Create a variant match info object from this trait info object.
This represents 'unified_address' clause in the 'pragma omp requires' directive.
This represents 'unified_shared_memory' clause in the 'pragma omp requires' directive.
This represents 'untied' clause in the 'pragma omp ...' directive.
static OMPUpdateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates clause for 'atomic' directive.
This represents the 'use' clause in 'pragma omp ...' directives.
static OMPUseDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPUseDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< Expr * > PrivateVars, ArrayRef< Expr * > Inits, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
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.
SourceLocation getLParenLoc() const
Returns the location of '('.
This represents 'weak' clause in the 'pragma omp atomic' directives.
This represents 'write' clause in the 'pragma omp atomic' directive.
This represents 'ompx_attribute' clause in a directive that might generate an outlined function.
This represents 'ompx_bare' clause in the 'pragma omp target teams ...' directive.
This represents 'ompx_dyn_cgroup_mem' clause in the 'pragma omp target ...' directive.
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:2953
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:5072
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:2866
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition TypeBase.h:8367
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:3555
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:8278
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:8463
QualType getCanonicalType() const
Definition TypeBase.h:8330
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8372
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:8432
const Type * getTypePtrOrNull() const
Definition TypeBase.h:8282
Represents a struct/union/class.
Definition Decl.h:4321
field_range fields() const
Definition Decl.h:4524
field_iterator field_begin() const
Definition Decl.cpp:5209
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3573
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,...
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...
OMPClause * ActOnOpenMPUseDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_ptr' clause.
StmtResult ActOnOpenMPParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for simd' after parsing of the associated statement.
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
Definition SemaOpenMP.h:55
OMPClause * ActOnOpenMPReleaseClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'release' clause.
OMPClause * ActOnOpenMPAcquireClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acquire' clause.
OMPClause * ActOnOpenMPProcBindClause(llvm::omp::ProcBindKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'proc_bind' clause.
OMPClause * ActOnOpenMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'simd' clause.
OMPClause * ActOnOpenMPXBareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_bare' clause.
StmtResult ActOnOpenMPInformationalDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Process an OpenMP informational directive.
StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt)
Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to an OpenMP loop directive.
OMPClause * ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'hint' clause.
OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK, SourceLocation Loc, SourceLocation RLoc)
StmtResult ActOnOpenMPTargetTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute' after parsing of the associated statement...
StmtResult ActOnOpenMPParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for' after parsing of the associated statement.
OMPClause * ActOnOpenMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'capture' clause.
StmtResult ActOnOpenMPForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for' after parsing of the associated statement.
StmtResult ActOnOpenMPAtomicDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp atomic' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target update'.
StmtResult ActOnOpenMPOrderedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp ordered' after parsing of the associated statement.
StmtResult ActOnOpenMPReverseDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp reverse'.
ExprResult ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > Brackets)
OMPClause * 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:1290
Expr * get() const
Definition Sema.h:7752
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition Sema.h:12467
Abstract base class used for diagnosing integer constant expression violations.
Definition Sema.h:7703
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:854
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition Sema.h:1120
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:9314
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
Definition Sema.h:9355
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
Definition Sema.h:9357
@ LookupAnyName
Look up any declaration with any name.
Definition Sema.h:9359
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:1501
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
Definition Sema.h:4731
@ AR_inaccessible
Definition Sema.h:1655
Scope * getScopeForContext(DeclContext *Ctx)
Determines the active Scope associated with the given declaration context.
Definition Sema.cpp:2312
FPOptionsOverride CurFPFeatureOverrides()
Definition Sema.h:2045
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:1283
void ActOnCapturedRegionError()
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
Definition SemaDecl.cpp:78
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:754
ASTContext & getASTContext() const
Definition Sema.h:925
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:9307
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition Sema.h:1191
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:918
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:1282
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:1281
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
Definition Sema.cpp:2558
llvm::SmallSetVector< DeclContext *, 16 > AssociatedNamespaceSet
Definition Sema.h:9306
DeclContext * getCurLexicalContext() const
Definition Sema.h:1124
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:639
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
Definition Sema.h:15420
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
Definition Sema.cpp:2513
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition Sema.h:1414
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:15375
void setFunctionHasBranchProtectedScope()
Definition Sema.cpp:2498
std::pair< StringRef, QualType > CapturedParamNameType
Definition Sema.h:11199
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:273
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:6728
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
Definition Sema.h:6697
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:1246
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:2104
sema::CapturedRegionScopeInfo * getCurCapturedRegion()
Retrieve the current captured region, if any.
Definition Sema.cpp:2887
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:7766
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition Sema.h:8636
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:85
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:1472
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:4889
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:8249
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:8260
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:9051
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:8618
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:2066
bool isArrayType() const
Definition TypeBase.h:8614
bool isArithmeticType() const
Definition Type.cpp:2337
bool isPointerType() const
Definition TypeBase.h:8515
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:8915
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9158
bool isReferenceType() const
Definition TypeBase.h:8539
bool isEnumeralType() const
Definition TypeBase.h:8646
bool isScalarType() const
Definition TypeBase.h:8973
bool isVariableArrayType() const
Definition TypeBase.h:8626
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
Definition Type.cpp:2103
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:752
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
Definition Type.cpp:2291
bool isAnyCharacterType() const
Determine whether this type is any of the built-in character types.
Definition Type.cpp:2168
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
Definition TypeBase.h:8865
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition TypeBase.h:2790
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition TypeBase.h:8840
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition TypeBase.h:2782
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
Definition Type.cpp:2411
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
bool isAnyComplexType() const
Definition TypeBase.h:8650
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:2243
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:9014
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2800
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition TypeBase.h:9144
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition Type.cpp:2435
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
Definition TypeBase.h:9108
bool isFunctionType() const
Definition TypeBase.h:8511
bool isStructureOrClassType() const
Definition Type.cpp:706
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2320
bool isFloatingType() const
Definition Type.cpp:2304
bool isAnyPointerType() const
Definition TypeBase.h:8523
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9091
bool isRecordType() const
Definition TypeBase.h:8642
bool isUnionType() const
Definition Type.cpp:718
bool isFunctionNoProtoType() const
Definition TypeBase.h:2600
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:3582
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:2158
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:2175
bool hasInit() const
Definition Decl.cpp:2405
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:2267
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2197
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition Decl.cpp:2264
@ 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:2484
@ 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:2535
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:1249
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
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:665
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:5381
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
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:5874
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:438
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
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:5339
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
Data for list of allocators.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Expr * AllocatorTraits
Allocator traits.
This structure contains most locations needed for by an OMPVarListClause.
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.
Clang specific specialization of the OMPContext to lookup target features.