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, x[] | bycopy|
2210 // | ptr | n.a. | - | - | - | x[] | bycopy|
2211 // | ptr | n.a. | - | - | x | | bycopy|
2212 // | ptr | n.a. | - | - | x | x | bycopy|
2213 // | ptr | n.a. | - | - | x | x[] | bycopy|
2214 // =========================================================================
2215 // Legend:
2216 // scl - scalar
2217 // ptr - pointer
2218 // agg - aggregate
2219 // x - applies
2220 // - - invalid in this combination
2221 // [] - mapped with an array section
2222 // byref - should be mapped by reference
2223 // byval - should be mapped by value
2224 // null - initialize a local variable to null on the device
2225 //
2226 // Observations:
2227 // - All scalar declarations that show up in a map clause have to be passed
2228 // by reference, because they may have been mapped in the enclosing data
2229 // environment.
2230 // - If the scalar value does not fit the size of uintptr, it has to be
2231 // passed by reference, regardless the result in the table above.
2232 // - For pointers mapped by value that have either an implicit map or an
2233 // array section, the runtime library may pass the NULL value to the
2234 // device instead of the value passed to it by the compiler.
2235 // - If both a pointer and a dereference of it are mapped, then the pointer
2236 // should be passed by reference.
2237
2238 if (Ty->isReferenceType())
2239 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2240
2241 // Locate map clauses and see if the variable being captured is mapped by
2242 // itself, or referred to, in any of those clauses. Here we only care about
2243 // variables, not fields, because fields are part of aggregates.
2244 bool IsVariableAssociatedWithSection = false;
2245 bool IsVariableItselfMapped = false;
2246
2247 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2248 D, Level,
2249 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2250 &IsVariableItselfMapped,
2252 MapExprComponents,
2253 OpenMPClauseKind WhereFoundClauseKind) {
2254 // Both map and has_device_addr clauses information influences how a
2255 // variable is captured. E.g. is_device_ptr does not require changing
2256 // the default behavior.
2257 if (WhereFoundClauseKind != OMPC_map &&
2258 WhereFoundClauseKind != OMPC_has_device_addr)
2259 return false;
2260
2261 auto EI = MapExprComponents.rbegin();
2262 auto EE = MapExprComponents.rend();
2263
2264 assert(EI != EE && "Invalid map expression!");
2265
2266 if (isa<DeclRefExpr>(EI->getAssociatedExpression()) &&
2267 EI->getAssociatedDeclaration() == D) {
2268 IsVariableUsedInMapClause = true;
2269
2270 // If the component list has only one element, it's for mapping the
2271 // variable itself, like map(p). This takes precedence in
2272 // determining how it's captured, so we don't need to look further
2273 // for any other maps that use the variable (like map(p[0]) etc.)
2274 if (MapExprComponents.size() == 1) {
2275 IsVariableItselfMapped = true;
2276 return true;
2277 }
2278 }
2279
2280 ++EI;
2281 if (EI == EE)
2282 return false;
2283 auto Last = std::prev(EE);
2284 const auto *UO =
2285 dyn_cast<UnaryOperator>(Last->getAssociatedExpression());
2286 if ((UO && UO->getOpcode() == UO_Deref) ||
2287 isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) ||
2288 isa<ArraySectionExpr>(Last->getAssociatedExpression()) ||
2289 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2290 isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) {
2291 IsVariableAssociatedWithSection = true;
2292 // We've found a case like map(p[0]) or map(p->a) or map(*p),
2293 // so we are done with this particular map, but we need to keep
2294 // looking in case we find a map(p).
2295 return false;
2296 }
2297
2298 // Keep looking for more map info.
2299 return false;
2300 });
2301
2302 if (IsVariableUsedInMapClause) {
2303 // If variable is identified in a map clause it is always captured by
2304 // reference except if it is a pointer that is dereferenced somehow, but
2305 // not itself mapped.
2306 //
2307 // OpenMP 6.0, 7.1.1: Data sharing attribute rules, variables referenced
2308 // in a construct::
2309 // If a list item in a has_device_addr clause or in a map clause on the
2310 // target construct has a base pointer, and the base pointer is a scalar
2311 // variable *that is not a list item in a map clause on the construct*,
2312 // the base pointer is firstprivate.
2313 //
2314 // OpenMP 4.5, 2.15.1.1: Data-sharing Attribute Rules for Variables
2315 // Referenced in a Construct:
2316 // If an array section is a list item in a map clause on the target
2317 // construct and the array section is derived from a variable for which
2318 // the type is pointer then that variable is firstprivate.
2319 IsByRef = IsVariableItselfMapped ||
2320 !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2321 } else {
2322 // By default, all the data that has a scalar type is mapped by copy
2323 // (except for reduction variables).
2324 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2325 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2326 !Ty->isAnyPointerType()) ||
2327 !Ty->isScalarType() ||
2328 DSAStack->isDefaultmapCapturedByRef(
2330 DSAStack->hasExplicitDSA(
2331 D,
2332 [](OpenMPClauseKind K, bool AppliedToPointee) {
2333 return K == OMPC_reduction && !AppliedToPointee;
2334 },
2335 Level);
2336 }
2337 }
2338
2339 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2340 IsByRef =
2341 ((IsVariableUsedInMapClause &&
2342 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2343 OMPD_target) ||
2344 !(DSAStack->hasExplicitDSA(
2345 D,
2346 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2347 return K == OMPC_firstprivate ||
2348 (K == OMPC_reduction && AppliedToPointee);
2349 },
2350 Level, /*NotLastprivate=*/true) ||
2351 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2352 // If the variable is artificial and must be captured by value - try to
2353 // capture by value.
2354 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2355 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2356 // If the variable is implicitly firstprivate and scalar - capture by
2357 // copy
2358 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2359 DSAStack->getDefaultDSA() == DSA_private) &&
2360 !DSAStack->hasExplicitDSA(
2361 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2362 Level) &&
2363 !DSAStack->isLoopControlVariable(D, Level).first);
2364 }
2365
2366 // When passing data by copy, we need to make sure it fits the uintptr size
2367 // and alignment, because the runtime library only deals with uintptr types.
2368 // If it does not fit the uintptr size, we need to pass the data by reference
2369 // instead.
2370 if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) >
2372 Ctx.getAlignOfGlobalVarInChars(Ty, dyn_cast<VarDecl>(D)) >
2373 Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2374 IsByRef = true;
2375 }
2376
2377 return IsByRef;
2378}
2379
2380unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2381 assert(getLangOpts().OpenMP);
2382 return DSAStack->getNestingLevel();
2383}
2384
2386 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2387 DSAStack->isUntiedRegion();
2388}
2389
2391 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2392 !DSAStack->isClauseParsingMode()) ||
2393 DSAStack->hasDirective(
2395 SourceLocation) -> bool {
2397 },
2398 false);
2399}
2400
2402 // Only rebuild for Field.
2403 if (!isa<FieldDecl>(D))
2404 return false;
2405 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2406 D,
2407 [](OpenMPClauseKind C, bool AppliedToPointee,
2408 DefaultDataSharingAttributes DefaultAttr) {
2409 return isOpenMPPrivate(C) && !AppliedToPointee &&
2410 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2411 },
2412 [](OpenMPDirectiveKind) { return true; },
2413 DSAStack->isClauseParsingMode());
2414 if (DVarPrivate.CKind != OMPC_unknown)
2415 return true;
2416 return false;
2417}
2418
2420 Expr *CaptureExpr, bool WithInit,
2421 DeclContext *CurContext,
2422 bool AsExpression);
2423
2425 unsigned StopAt) {
2426 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2427 D = getCanonicalDecl(D);
2428
2429 auto *VD = dyn_cast<VarDecl>(D);
2430 // Do not capture constexpr variables.
2431 if (VD && VD->isConstexpr())
2432 return nullptr;
2433
2434 // If we want to determine whether the variable should be captured from the
2435 // perspective of the current capturing scope, and we've already left all the
2436 // capturing scopes of the top directive on the stack, check from the
2437 // perspective of its parent directive (if any) instead.
2438 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2439 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2440
2441 // If we are attempting to capture a global variable in a directive with
2442 // 'target' we return true so that this global is also mapped to the device.
2443 //
2444 if (VD && !VD->hasLocalStorage() &&
2445 (SemaRef.getCurCapturedRegion() || SemaRef.getCurBlock() ||
2446 SemaRef.getCurLambda())) {
2448 DSAStackTy::DSAVarData DVarTop =
2449 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2450 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2451 return VD;
2452 // If the declaration is enclosed in a 'declare target' directive,
2453 // then it should not be captured.
2454 //
2455 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2456 return nullptr;
2457 CapturedRegionScopeInfo *CSI = nullptr;
2458 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2459 llvm::reverse(SemaRef.FunctionScopes),
2460 CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2461 : 0)) {
2462 if (!isa<CapturingScopeInfo>(FSI))
2463 return nullptr;
2464 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2465 if (RSI->CapRegionKind == CR_OpenMP) {
2466 CSI = RSI;
2467 break;
2468 }
2469 }
2470 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2473 DSAStack->getDirective(CSI->OpenMPLevel));
2474 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2475 return VD;
2476 }
2478 // Try to mark variable as declare target if it is used in capturing
2479 // regions.
2480 if (getLangOpts().OpenMP <= 45 &&
2481 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2483 return nullptr;
2484 }
2485 }
2486
2487 if (CheckScopeInfo) {
2488 bool OpenMPFound = false;
2489 for (unsigned I = StopAt + 1; I > 0; --I) {
2490 FunctionScopeInfo *FSI = SemaRef.FunctionScopes[I - 1];
2491 if (!isa<CapturingScopeInfo>(FSI))
2492 return nullptr;
2493 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2494 if (RSI->CapRegionKind == CR_OpenMP) {
2495 OpenMPFound = true;
2496 break;
2497 }
2498 }
2499 if (!OpenMPFound)
2500 return nullptr;
2501 }
2502
2503 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2504 (!DSAStack->isClauseParsingMode() ||
2505 DSAStack->getParentDirective() != OMPD_unknown)) {
2506 auto &&Info = DSAStack->isLoopControlVariable(D);
2507 if (Info.first ||
2508 (VD && VD->hasLocalStorage() &&
2509 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2510 (VD && DSAStack->isForceVarCapturing()))
2511 return VD ? VD : Info.second;
2512 DSAStackTy::DSAVarData DVarTop =
2513 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2514 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2515 (!VD || VD->hasLocalStorage() ||
2516 !(DVarTop.AppliedToPointee && DVarTop.CKind != OMPC_reduction)))
2517 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2518 // Threadprivate variables must not be captured.
2519 if (isOpenMPThreadPrivate(DVarTop.CKind))
2520 return nullptr;
2521 // The variable is not private or it is the variable in the directive with
2522 // default(none) clause and not used in any clause.
2523 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2524 D,
2525 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2526 return isOpenMPPrivate(C) && !AppliedToPointee;
2527 },
2528 [](OpenMPDirectiveKind) { return true; },
2529 DSAStack->isClauseParsingMode());
2530 // Global shared must not be captured.
2531 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2532 ((DSAStack->getDefaultDSA() != DSA_none &&
2533 DSAStack->getDefaultDSA() != DSA_private &&
2534 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2535 DVarTop.CKind == OMPC_shared))
2536 return nullptr;
2537 auto *FD = dyn_cast<FieldDecl>(D);
2538 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2539 !DVarPrivate.PrivateCopy) {
2540 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2541 D,
2542 [](OpenMPClauseKind C, bool AppliedToPointee,
2543 DefaultDataSharingAttributes DefaultAttr) {
2544 return isOpenMPPrivate(C) && !AppliedToPointee &&
2545 (DefaultAttr == DSA_firstprivate ||
2546 DefaultAttr == DSA_private);
2547 },
2548 [](OpenMPDirectiveKind) { return true; },
2549 DSAStack->isClauseParsingMode());
2550 if (DVarPrivate.CKind == OMPC_unknown)
2551 return nullptr;
2552
2553 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2554 if (VD)
2555 return VD;
2556 if (SemaRef.getCurrentThisType().isNull())
2557 return nullptr;
2558 Expr *ThisExpr = SemaRef.BuildCXXThisExpr(SourceLocation(),
2559 SemaRef.getCurrentThisType(),
2560 /*IsImplicit=*/true);
2561 const CXXScopeSpec CS = CXXScopeSpec();
2562 Expr *ME = SemaRef.BuildMemberExpr(
2563 ThisExpr, /*IsArrow=*/true, SourceLocation(),
2566 /*HadMultipleCandidates=*/false, DeclarationNameInfo(), FD->getType(),
2569 SemaRef, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2570 SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2571 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2573 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2574 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2575 return VD;
2576 }
2577 if (DVarPrivate.CKind != OMPC_unknown ||
2578 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2579 DSAStack->getDefaultDSA() == DSA_private ||
2580 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2581 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2582 }
2583 return nullptr;
2584}
2585
2586void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2587 unsigned Level) const {
2588 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2589}
2590
2592 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2593 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2594 DSAStack->loopInit();
2595}
2596
2598 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2599 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2600 DSAStack->resetPossibleLoopCounter();
2601 DSAStack->loopStart();
2602 }
2603}
2604
2606 unsigned CapLevel) const {
2607 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2608 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2609 (!DSAStack->isClauseParsingMode() ||
2610 DSAStack->getParentDirective() != OMPD_unknown)) {
2611 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2612 D,
2613 [](OpenMPClauseKind C, bool AppliedToPointee,
2614 DefaultDataSharingAttributes DefaultAttr) {
2615 return isOpenMPPrivate(C) && !AppliedToPointee &&
2616 DefaultAttr == DSA_private;
2617 },
2618 [](OpenMPDirectiveKind) { return true; },
2619 DSAStack->isClauseParsingMode());
2620 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2621 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2622 !DSAStack->isLoopControlVariable(D).first)
2623 return OMPC_private;
2624 }
2625 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2626 bool IsTriviallyCopyable =
2628 getASTContext()) &&
2629 !D->getType()
2633 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2635 getOpenMPCaptureRegions(CaptureRegions, DKind);
2636 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2637 (IsTriviallyCopyable ||
2638 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2639 if (DSAStack->hasExplicitDSA(
2640 D,
2641 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2642 Level, /*NotLastprivate=*/true))
2643 return OMPC_firstprivate;
2644 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2645 if (DVar.CKind != OMPC_shared &&
2646 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2647 DSAStack->addImplicitTaskFirstprivate(Level, D);
2648 return OMPC_firstprivate;
2649 }
2650 }
2651 }
2652 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2653 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2654 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2655 DSAStack->resetPossibleLoopCounter(D);
2656 DSAStack->loopStart();
2657 return OMPC_private;
2658 }
2659 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2660 DSAStack->isLoopControlVariable(D).first) &&
2661 !DSAStack->hasExplicitDSA(
2662 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2663 Level) &&
2664 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2665 return OMPC_private;
2666 }
2667 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2668 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2669 DSAStack->isForceVarCapturing() &&
2670 !DSAStack->hasExplicitDSA(
2671 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2672 Level))
2673 return OMPC_private;
2674 }
2675 // User-defined allocators are private since they must be defined in the
2676 // context of target region.
2677 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2678 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2679 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2680 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2681 return OMPC_private;
2682 return (DSAStack->hasExplicitDSA(
2683 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2684 Level) ||
2685 (DSAStack->isClauseParsingMode() &&
2686 DSAStack->getClauseParsingMode() == OMPC_private) ||
2687 // Consider taskgroup reduction descriptor variable a private
2688 // to avoid possible capture in the region.
2689 (DSAStack->hasExplicitDirective(
2690 [](OpenMPDirectiveKind K) {
2691 return K == OMPD_taskgroup ||
2692 ((isOpenMPParallelDirective(K) ||
2693 isOpenMPWorksharingDirective(K)) &&
2694 !isOpenMPSimdDirective(K));
2695 },
2696 Level) &&
2697 DSAStack->isTaskgroupReductionRef(D, Level)))
2698 ? OMPC_private
2699 : OMPC_unknown;
2700}
2701
2703 unsigned Level) {
2704 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2705 D = getCanonicalDecl(D);
2706 OpenMPClauseKind OMPC = OMPC_unknown;
2707 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2708 const unsigned NewLevel = I - 1;
2709 if (DSAStack->hasExplicitDSA(
2710 D,
2711 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2712 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2713 OMPC = K;
2714 return true;
2715 }
2716 return false;
2717 },
2718 NewLevel))
2719 break;
2720 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2721 D, NewLevel,
2723 OpenMPClauseKind) { return true; })) {
2724 OMPC = OMPC_map;
2725 break;
2726 }
2727 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2728 NewLevel)) {
2729 OMPC = OMPC_map;
2730 if (DSAStack->mustBeFirstprivateAtLevel(
2732 OMPC = OMPC_firstprivate;
2733 break;
2734 }
2735 }
2736 if (OMPC != OMPC_unknown)
2737 FD->addAttr(
2738 OMPCaptureKindAttr::CreateImplicit(getASTContext(), unsigned(OMPC)));
2739}
2740
2742 unsigned CaptureLevel) const {
2743 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2744 // Return true if the current level is no longer enclosed in a target region.
2745
2747 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2748 const auto *VD = dyn_cast<VarDecl>(D);
2749 return VD && !VD->hasLocalStorage() &&
2750 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2751 Level) &&
2752 Regions[CaptureLevel] != OMPD_task;
2753}
2754
2756 unsigned CaptureLevel) const {
2757 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2758 // Return true if the current level is no longer enclosed in a target region.
2759
2760 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2761 if (!VD->hasLocalStorage()) {
2763 return true;
2764 DSAStackTy::DSAVarData TopDVar =
2765 DSAStack->getTopDSA(D, /*FromParent=*/false);
2766 unsigned NumLevels =
2767 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2768 if (Level == 0)
2769 // non-file scope static variable with default(firstprivate)
2770 // should be global captured.
2771 return (NumLevels == CaptureLevel + 1 &&
2772 (TopDVar.CKind != OMPC_shared ||
2773 DSAStack->getDefaultDSA() == DSA_firstprivate));
2774 do {
2775 --Level;
2776 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2777 if (DVar.CKind != OMPC_shared)
2778 return true;
2779 } while (Level > 0);
2780 }
2781 }
2782 return true;
2783}
2784
2785void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2786
2788 OMPTraitInfo &TI) {
2789 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2790}
2791
2794 "Not in OpenMP declare variant scope!");
2795
2796 OMPDeclareVariantScopes.pop_back();
2797}
2798
2800 const FunctionDecl *Callee,
2801 SourceLocation Loc) {
2802 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2803 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2804 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2805 // Ignore host functions during device analysis.
2806 if (getLangOpts().OpenMPIsTargetDevice &&
2807 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2808 return;
2809 // Ignore nohost functions during host analysis.
2810 if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2811 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2812 return;
2813 const FunctionDecl *FD = Callee->getMostRecentDecl();
2814 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2815 if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2816 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2817 // Diagnose host function called during device codegen.
2818 StringRef HostDevTy =
2819 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2820 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2821 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2822 diag::note_omp_marked_device_type_here)
2823 << HostDevTy;
2824 return;
2825 }
2826 if (!getLangOpts().OpenMPIsTargetDevice &&
2827 !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2828 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2829 // In OpenMP 5.2 or later, if the function has a host variant then allow
2830 // that to be called instead
2831 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2832 for (OMPDeclareVariantAttr *A :
2833 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2834 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2835 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2836 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2837 OMPDeclareTargetDeclAttr::getDeviceType(
2838 VariantFD->getMostRecentDecl());
2839 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2840 return true;
2841 }
2842 return false;
2843 };
2844 if (getLangOpts().OpenMP >= 52 &&
2845 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2846 return;
2847 // Diagnose nohost function called during host codegen.
2848 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2849 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2850 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2851 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2852 diag::note_omp_marked_device_type_here)
2853 << NoHostDevTy;
2854 }
2855}
2856
2858 const DeclarationNameInfo &DirName,
2859 Scope *CurScope, SourceLocation Loc) {
2860 DSAStack->push(DKind, DirName, CurScope, Loc);
2861 SemaRef.PushExpressionEvaluationContext(
2863}
2864
2866 DSAStack->setClauseParsingMode(K);
2867}
2868
2870 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2871 SemaRef.CleanupVarDeclMarking();
2872}
2873
2874static std::pair<ValueDecl *, bool>
2875getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2876 SourceRange &ERange, bool AllowArraySection = false,
2877 bool AllowAssumedSizeArray = false, StringRef DiagType = "");
2878
2879/// Check consistency of the reduction clauses.
2880static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2881 ArrayRef<OMPClause *> Clauses) {
2882 bool InscanFound = false;
2883 SourceLocation InscanLoc;
2884 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2885 // A reduction clause without the inscan reduction-modifier may not appear on
2886 // a construct on which a reduction clause with the inscan reduction-modifier
2887 // appears.
2888 for (OMPClause *C : Clauses) {
2889 if (C->getClauseKind() != OMPC_reduction)
2890 continue;
2891 auto *RC = cast<OMPReductionClause>(C);
2892 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2893 InscanFound = true;
2894 InscanLoc = RC->getModifierLoc();
2895 continue;
2896 }
2897 if (RC->getModifier() == OMPC_REDUCTION_task) {
2898 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2899 // A reduction clause with the task reduction-modifier may only appear on
2900 // a parallel construct, a worksharing construct or a combined or
2901 // composite construct for which any of the aforementioned constructs is a
2902 // constituent construct and simd or loop are not constituent constructs.
2903 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2904 if (!(isOpenMPParallelDirective(CurDir) ||
2906 isOpenMPSimdDirective(CurDir))
2907 S.Diag(RC->getModifierLoc(),
2908 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2909 continue;
2910 }
2911 }
2912 if (InscanFound) {
2913 for (OMPClause *C : Clauses) {
2914 if (C->getClauseKind() != OMPC_reduction)
2915 continue;
2916 auto *RC = cast<OMPReductionClause>(C);
2917 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2918 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2919 ? RC->getBeginLoc()
2920 : RC->getModifierLoc(),
2921 diag::err_omp_inscan_reduction_expected);
2922 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2923 continue;
2924 }
2925 for (Expr *Ref : RC->varlist()) {
2926 assert(Ref && "NULL expr in OpenMP reduction clause.");
2927 SourceLocation ELoc;
2928 SourceRange ERange;
2929 Expr *SimpleRefExpr = Ref;
2930 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2931 /*AllowArraySection=*/true);
2932 ValueDecl *D = Res.first;
2933 if (!D)
2934 continue;
2935 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2936 S.Diag(Ref->getExprLoc(),
2937 diag::err_omp_reduction_not_inclusive_exclusive)
2938 << Ref->getSourceRange();
2939 }
2940 }
2941 }
2942 }
2943}
2944
2945static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2946 ArrayRef<OMPClause *> Clauses);
2947static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2948 bool WithInit);
2949
2950static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2951 const ValueDecl *D,
2952 const DSAStackTy::DSAVarData &DVar,
2953 bool IsLoopIterVar = false);
2954
2956 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2957 // A variable of class type (or array thereof) that appears in a lastprivate
2958 // clause requires an accessible, unambiguous default constructor for the
2959 // class type, unless the list item is also specified in a firstprivate
2960 // clause.
2961
2962 auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) {
2963 SmallVector<Expr *, 8> PrivateCopies;
2964 for (Expr *DE : Clause->varlist()) {
2965 if (DE->isValueDependent() || DE->isTypeDependent()) {
2966 PrivateCopies.push_back(nullptr);
2967 continue;
2968 }
2969 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2970 auto *VD = cast<VarDecl>(DRE->getDecl());
2972 const DSAStackTy::DSAVarData DVar =
2973 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2974 if (DVar.CKind != OMPC_lastprivate) {
2975 // The variable is also a firstprivate, so initialization sequence
2976 // for private copy is generated already.
2977 PrivateCopies.push_back(nullptr);
2978 continue;
2979 }
2980 // Generate helper private variable and initialize it with the
2981 // default value. The address of the original variable is replaced
2982 // by the address of the new private variable in CodeGen. This new
2983 // variable is not added to IdResolver, so the code in the OpenMP
2984 // region uses original variable for proper diagnostics.
2985 VarDecl *VDPrivate = buildVarDecl(
2986 SemaRef, DE->getExprLoc(), Type.getUnqualifiedType(), VD->getName(),
2987 VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2988 SemaRef.ActOnUninitializedDecl(VDPrivate);
2989 if (VDPrivate->isInvalidDecl()) {
2990 PrivateCopies.push_back(nullptr);
2991 continue;
2992 }
2993 PrivateCopies.push_back(buildDeclRefExpr(
2994 SemaRef, VDPrivate, DE->getType(), DE->getExprLoc()));
2995 }
2996 Clause->setPrivateCopies(PrivateCopies);
2997 };
2998
2999 auto FinalizeNontemporal = [&](OMPNontemporalClause *Clause) {
3000 // Finalize nontemporal clause by handling private copies, if any.
3001 SmallVector<Expr *, 8> PrivateRefs;
3002 for (Expr *RefExpr : Clause->varlist()) {
3003 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
3004 SourceLocation ELoc;
3005 SourceRange ERange;
3006 Expr *SimpleRefExpr = RefExpr;
3007 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
3008 if (Res.second)
3009 // It will be analyzed later.
3010 PrivateRefs.push_back(RefExpr);
3011 ValueDecl *D = Res.first;
3012 if (!D)
3013 continue;
3014
3015 const DSAStackTy::DSAVarData DVar =
3016 DSAStack->getTopDSA(D, /*FromParent=*/false);
3017 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
3018 : SimpleRefExpr);
3019 }
3020 Clause->setPrivateRefs(PrivateRefs);
3021 };
3022
3023 auto FinalizeAllocators = [&](OMPUsesAllocatorsClause *Clause) {
3024 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
3025 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
3026 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
3027 if (!DRE)
3028 continue;
3029 ValueDecl *VD = DRE->getDecl();
3030 if (!VD || !isa<VarDecl>(VD))
3031 continue;
3032 DSAStackTy::DSAVarData DVar =
3033 DSAStack->getTopDSA(VD, /*FromParent=*/false);
3034 // OpenMP [2.12.5, target Construct]
3035 // Memory allocators that appear in a uses_allocators clause cannot
3036 // appear in other data-sharing attribute clauses or data-mapping
3037 // attribute clauses in the same construct.
3038 Expr *MapExpr = nullptr;
3039 if (DVar.RefExpr ||
3040 DSAStack->checkMappableExprComponentListsForDecl(
3041 VD, /*CurrentRegionOnly=*/true,
3042 [VD, &MapExpr](
3044 MapExprComponents,
3046 auto MI = MapExprComponents.rbegin();
3047 auto ME = MapExprComponents.rend();
3048 if (MI != ME &&
3049 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
3050 VD->getCanonicalDecl()) {
3051 MapExpr = MI->getAssociatedExpression();
3052 return true;
3053 }
3054 return false;
3055 })) {
3056 Diag(D.Allocator->getExprLoc(), diag::err_omp_allocator_used_in_clauses)
3057 << D.Allocator->getSourceRange();
3058 if (DVar.RefExpr)
3060 else
3061 Diag(MapExpr->getExprLoc(), diag::note_used_here)
3062 << MapExpr->getSourceRange();
3063 }
3064 }
3065 };
3066
3067 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
3068 for (OMPClause *C : D->clauses()) {
3069 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
3070 FinalizeLastprivate(Clause);
3071 } else if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
3072 FinalizeNontemporal(Clause);
3073 } else if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
3074 FinalizeAllocators(Clause);
3075 }
3076 }
3077 // Check allocate clauses.
3078 if (!SemaRef.CurContext->isDependentContext())
3079 checkAllocateClauses(SemaRef, DSAStack, D->clauses());
3080 checkReductionClauses(SemaRef, DSAStack, D->clauses());
3081 }
3082
3083 DSAStack->pop();
3086}
3087
3088static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
3089 Expr *NumIterations, Sema &SemaRef,
3090 Scope *S, DSAStackTy *Stack);
3091
3092static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
3093 OMPLoopBasedDirective::HelperExprs &B,
3094 DSAStackTy *Stack) {
3095 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
3096 "loop exprs were not built");
3097
3098 if (SemaRef.CurContext->isDependentContext())
3099 return false;
3100
3101 // Finalize the clauses that need pre-built expressions for CodeGen.
3102 for (OMPClause *C : Clauses) {
3103 auto *LC = dyn_cast<OMPLinearClause>(C);
3104 if (!LC)
3105 continue;
3106 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
3107 B.NumIterations, SemaRef,
3108 SemaRef.getCurScope(), Stack))
3109 return true;
3110 }
3111
3112 return false;
3113}
3114
3115namespace {
3116
3117class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3118private:
3119 Sema &SemaRef;
3120
3121public:
3122 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3123 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3124 NamedDecl *ND = Candidate.getCorrectionDecl();
3125 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3126 return VD->hasGlobalStorage() &&
3127 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3128 SemaRef.getCurScope());
3129 }
3130 return false;
3131 }
3132
3133 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3134 return std::make_unique<VarDeclFilterCCC>(*this);
3135 }
3136};
3137
3138class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3139private:
3140 Sema &SemaRef;
3141
3142public:
3143 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3144 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3145 NamedDecl *ND = Candidate.getCorrectionDecl();
3146 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3147 isa<FunctionDecl>(ND))) {
3148 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3149 SemaRef.getCurScope());
3150 }
3151 return false;
3152 }
3153
3154 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3155 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3156 }
3157};
3158
3159} // namespace
3160
3162 CXXScopeSpec &ScopeSpec,
3163 const DeclarationNameInfo &Id,
3164 OpenMPDirectiveKind Kind) {
3165 ASTContext &Context = getASTContext();
3166 unsigned OMPVersion = getLangOpts().OpenMP;
3168 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
3169 /*ObjectType=*/QualType(),
3170 /*AllowBuiltinCreation=*/true);
3171
3172 if (Lookup.isAmbiguous())
3173 return ExprError();
3174
3175 VarDecl *VD;
3176 if (!Lookup.isSingleResult()) {
3177 VarDeclFilterCCC CCC(SemaRef);
3178 if (TypoCorrection Corrected =
3179 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
3181 SemaRef.diagnoseTypo(
3182 Corrected,
3183 SemaRef.PDiag(Lookup.empty() ? diag::err_undeclared_var_use_suggest
3184 : diag::err_omp_expected_var_arg_suggest)
3185 << Id.getName());
3186 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3187 } else {
3188 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3189 : diag::err_omp_expected_var_arg)
3190 << Id.getName();
3191 return ExprError();
3192 }
3193 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3194 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3195 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3196 return ExprError();
3197 }
3198 Lookup.suppressDiagnostics();
3199
3200 // OpenMP [2.9.2, Syntax, C/C++]
3201 // Variables must be file-scope, namespace-scope, or static block-scope.
3202 if ((Kind == OMPD_threadprivate || Kind == OMPD_groupprivate) &&
3203 !VD->hasGlobalStorage()) {
3204 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3205 << getOpenMPDirectiveName(Kind, OMPVersion) << !VD->isStaticLocal();
3206 bool IsDecl =
3208 Diag(VD->getLocation(),
3209 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3210 << VD;
3211 return ExprError();
3212 }
3213
3214 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3215 NamedDecl *ND = CanonicalVD;
3216 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3217 // A threadprivate or groupprivate directive for file-scope variables must
3218 // appear outside any definition or declaration.
3219 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3220 !SemaRef.getCurLexicalContext()->isTranslationUnit()) {
3221 Diag(Id.getLoc(), diag::err_omp_var_scope)
3222 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3223 bool IsDecl =
3225 Diag(VD->getLocation(),
3226 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3227 << VD;
3228 return ExprError();
3229 }
3230 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3231 // A threadprivate or groupprivate directive for static class member
3232 // variables must appear in the class definition, in the same scope in which
3233 // the member variables are declared.
3234 if (CanonicalVD->isStaticDataMember() &&
3235 !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) {
3236 Diag(Id.getLoc(), diag::err_omp_var_scope)
3237 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3238 bool IsDecl =
3240 Diag(VD->getLocation(),
3241 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3242 << VD;
3243 return ExprError();
3244 }
3245 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3246 // A threadprivate or groupprivate directive for namespace-scope variables
3247 // must appear outside any definition or declaration other than the
3248 // namespace definition itself.
3249 if (CanonicalVD->getDeclContext()->isNamespace() &&
3250 (!SemaRef.getCurLexicalContext()->isFileContext() ||
3251 !SemaRef.getCurLexicalContext()->Encloses(
3252 CanonicalVD->getDeclContext()))) {
3253 Diag(Id.getLoc(), diag::err_omp_var_scope)
3254 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3255 bool IsDecl =
3257 Diag(VD->getLocation(),
3258 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3259 << VD;
3260 return ExprError();
3261 }
3262 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3263 // A threadprivate or groupprivate directive for static block-scope
3264 // variables must appear in the scope of the variable and not in a nested
3265 // scope.
3266 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3267 !SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(), CurScope)) {
3268 Diag(Id.getLoc(), diag::err_omp_var_scope)
3269 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3270 bool IsDecl =
3272 Diag(VD->getLocation(),
3273 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3274 << VD;
3275 return ExprError();
3276 }
3277
3278 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3279 // A threadprivate or groupprivate directive must lexically precede all
3280 // references to any of the variables in its list.
3281 if ((Kind == OMPD_threadprivate && VD->isUsed() &&
3282 !DSAStack->isThreadPrivate(VD)) ||
3283 (Kind == OMPD_groupprivate && VD->isUsed())) {
3284 Diag(Id.getLoc(), diag::err_omp_var_used)
3285 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3286 return ExprError();
3287 }
3288
3289 QualType ExprType = VD->getType().getNonReferenceType();
3291 SourceLocation(), VD,
3292 /*RefersToEnclosingVariableOrCapture=*/false,
3293 Id.getLoc(), ExprType, VK_LValue);
3294}
3295
3298 ArrayRef<Expr *> VarList) {
3299 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3300 SemaRef.CurContext->addDecl(D);
3302 }
3303 return nullptr;
3304}
3305
3308 ArrayRef<Expr *> VarList) {
3309 if (!getLangOpts().OpenMP || getLangOpts().OpenMP < 60) {
3310 Diag(Loc, diag::err_omp_unexpected_directive)
3311 << getOpenMPDirectiveName(OMPD_groupprivate, getLangOpts().OpenMP);
3312 return nullptr;
3313 }
3314 if (OMPGroupPrivateDecl *D = CheckOMPGroupPrivateDecl(Loc, VarList)) {
3315 SemaRef.CurContext->addDecl(D);
3317 }
3318 return nullptr;
3319}
3320
3321namespace {
3322class LocalVarRefChecker final
3323 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3324 Sema &SemaRef;
3325
3326public:
3327 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3328 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3329 if (VD->hasLocalStorage()) {
3330 SemaRef.Diag(E->getBeginLoc(),
3331 diag::err_omp_local_var_in_threadprivate_init)
3332 << E->getSourceRange();
3333 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3334 << VD << VD->getSourceRange();
3335 return true;
3336 }
3337 }
3338 return false;
3339 }
3340 bool VisitStmt(const Stmt *S) {
3341 for (const Stmt *Child : S->children()) {
3342 if (Child && Visit(Child))
3343 return true;
3344 }
3345 return false;
3346 }
3347 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3348};
3349} // namespace
3350
3351OMPThreadPrivateDecl *
3353 ArrayRef<Expr *> VarList) {
3354 ASTContext &Context = getASTContext();
3356 for (Expr *RefExpr : VarList) {
3357 auto *DE = cast<DeclRefExpr>(RefExpr);
3358 auto *VD = cast<VarDecl>(DE->getDecl());
3359 SourceLocation ILoc = DE->getExprLoc();
3360
3361 // Mark variable as used.
3362 VD->setReferenced();
3363 VD->markUsed(Context);
3364
3365 QualType QType = VD->getType();
3366 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3367 // It will be analyzed later.
3368 Vars.push_back(DE);
3369 continue;
3370 }
3371
3372 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3373 // A threadprivate variable must not have an incomplete type.
3374 if (SemaRef.RequireCompleteType(
3375 ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) {
3376 continue;
3377 }
3378
3379 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3380 // A threadprivate variable must not have a reference type.
3381 if (VD->getType()->isReferenceType()) {
3382 unsigned OMPVersion = getLangOpts().OpenMP;
3383 Diag(ILoc, diag::err_omp_ref_type_arg)
3384 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion)
3385 << VD->getType();
3386 bool IsDecl =
3388 Diag(VD->getLocation(),
3389 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3390 << VD;
3391 continue;
3392 }
3393
3394 // Check if this is a TLS variable. If TLS is not being supported, produce
3395 // the corresponding diagnostic.
3396 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3397 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3398 getLangOpts().OpenMPUseTLS &&
3399 getASTContext().getTargetInfo().isTLSSupported())) ||
3400 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3401 !VD->isLocalVarDecl())) {
3402 Diag(ILoc, diag::err_omp_var_thread_local)
3403 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3404 bool IsDecl =
3406 Diag(VD->getLocation(),
3407 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3408 << VD;
3409 continue;
3410 }
3411
3412 // Check if initial value of threadprivate variable reference variable with
3413 // local storage (it is not supported by runtime).
3414 if (const Expr *Init = VD->getAnyInitializer()) {
3415 LocalVarRefChecker Checker(SemaRef);
3416 if (Checker.Visit(Init))
3417 continue;
3418 }
3419
3420 Vars.push_back(RefExpr);
3421 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3422 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3423 Context, SourceRange(Loc, Loc)));
3424 if (ASTMutationListener *ML = Context.getASTMutationListener())
3425 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3426 }
3427 OMPThreadPrivateDecl *D = nullptr;
3428 if (!Vars.empty()) {
3429 D = OMPThreadPrivateDecl::Create(Context, SemaRef.getCurLexicalContext(),
3430 Loc, Vars);
3431 D->setAccess(AS_public);
3432 }
3433 return D;
3434}
3435
3438 ArrayRef<Expr *> VarList) {
3439 ASTContext &Context = getASTContext();
3441 for (Expr *RefExpr : VarList) {
3442 auto *DE = cast<DeclRefExpr>(RefExpr);
3443 auto *VD = cast<VarDecl>(DE->getDecl());
3444 SourceLocation ILoc = DE->getExprLoc();
3445
3446 // Mark variable as used.
3447 VD->setReferenced();
3448 VD->markUsed(Context);
3449
3450 QualType QType = VD->getType();
3451 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3452 // It will be analyzed later.
3453 Vars.push_back(DE);
3454 continue;
3455 }
3456
3457 // OpenMP groupprivate restrictions:
3458 // A groupprivate variable must not have an incomplete type.
3459 if (SemaRef.RequireCompleteType(
3460 ILoc, VD->getType(), diag::err_omp_groupprivate_incomplete_type)) {
3461 continue;
3462 }
3463
3464 // A groupprivate variable must not have a reference type.
3465 if (VD->getType()->isReferenceType()) {
3466 Diag(ILoc, diag::err_omp_ref_type_arg)
3467 << getOpenMPDirectiveName(OMPD_groupprivate) << VD->getType();
3468 bool IsDecl =
3470 Diag(VD->getLocation(),
3471 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3472 << VD;
3473 continue;
3474 }
3475
3476 // A variable that is declared with an initializer must not appear in a
3477 // groupprivate directive.
3478 if (VD->getAnyInitializer()) {
3479 Diag(ILoc, diag::err_omp_groupprivate_with_initializer)
3480 << VD->getDeclName();
3481 bool IsDecl =
3483 Diag(VD->getLocation(),
3484 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3485 << VD;
3486 continue;
3487 }
3488
3489 Vars.push_back(RefExpr);
3490 DSAStack->addDSA(VD, DE, OMPC_groupprivate);
3491 VD->addAttr(OMPGroupPrivateDeclAttr::CreateImplicit(Context,
3492 SourceRange(Loc, Loc)));
3493 if (ASTMutationListener *ML = Context.getASTMutationListener())
3494 ML->DeclarationMarkedOpenMPGroupPrivate(VD);
3495 }
3496 OMPGroupPrivateDecl *D = nullptr;
3497 if (!Vars.empty()) {
3498 D = OMPGroupPrivateDecl::Create(Context, SemaRef.getCurLexicalContext(),
3499 Loc, Vars);
3500 D->setAccess(AS_public);
3501 }
3502 return D;
3503}
3504
3505static OMPAllocateDeclAttr::AllocatorTypeTy
3506getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3507 if (!Allocator)
3508 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3509 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3510 Allocator->isInstantiationDependent() ||
3512 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3513 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3514 llvm::FoldingSetNodeID AEId;
3515 const Expr *AE = Allocator->IgnoreParenImpCasts();
3516 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3517 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3518 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3519 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3520 llvm::FoldingSetNodeID DAEId;
3521 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3522 /*Canonical=*/true);
3523 if (AEId == DAEId) {
3524 AllocatorKindRes = AllocatorKind;
3525 break;
3526 }
3527 }
3528 return AllocatorKindRes;
3529}
3530
3532 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3533 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3534 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3535 return false;
3536 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3537 Expr *PrevAllocator = A->getAllocator();
3538 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3539 getAllocatorKind(S, Stack, PrevAllocator);
3540 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3541 if (AllocatorsMatch &&
3542 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3543 Allocator && PrevAllocator) {
3544 const Expr *AE = Allocator->IgnoreParenImpCasts();
3545 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3546 llvm::FoldingSetNodeID AEId, PAEId;
3547 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3548 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3549 AllocatorsMatch = AEId == PAEId;
3550 }
3551 if (!AllocatorsMatch) {
3552 SmallString<256> AllocatorBuffer;
3553 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3554 if (Allocator)
3555 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3556 SmallString<256> PrevAllocatorBuffer;
3557 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3558 if (PrevAllocator)
3559 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3560 S.getPrintingPolicy());
3561
3562 SourceLocation AllocatorLoc =
3563 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3564 SourceRange AllocatorRange =
3565 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3566 SourceLocation PrevAllocatorLoc =
3567 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3568 SourceRange PrevAllocatorRange =
3569 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3570 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3571 << (Allocator ? 1 : 0) << AllocatorStream.str()
3572 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3573 << AllocatorRange;
3574 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3575 << PrevAllocatorRange;
3576 return true;
3577 }
3578 return false;
3579}
3580
3581static void
3583 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3584 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3585 if (VD->hasAttr<OMPAllocateDeclAttr>())
3586 return;
3587 if (Alignment &&
3588 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3589 Alignment->isInstantiationDependent() ||
3590 Alignment->containsUnexpandedParameterPack()))
3591 // Apply later when we have a usable value.
3592 return;
3593 if (Allocator &&
3594 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3595 Allocator->isInstantiationDependent() ||
3596 Allocator->containsUnexpandedParameterPack()))
3597 return;
3598 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3599 Allocator, Alignment, SR);
3600 VD->addAttr(A);
3602 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3603}
3604
3607 DeclContext *Owner) {
3608 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3609 Expr *Alignment = nullptr;
3610 Expr *Allocator = nullptr;
3611 if (Clauses.empty()) {
3612 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3613 // allocate directives that appear in a target region must specify an
3614 // allocator clause unless a requires directive with the dynamic_allocators
3615 // clause is present in the same compilation unit.
3616 if (getLangOpts().OpenMPIsTargetDevice &&
3617 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3618 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3619 } else {
3620 for (const OMPClause *C : Clauses)
3621 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3622 Allocator = AC->getAllocator();
3623 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3624 Alignment = AC->getAlignment();
3625 else
3626 llvm_unreachable("Unexpected clause on allocate directive");
3627 }
3628 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3629 getAllocatorKind(SemaRef, DSAStack, Allocator);
3631 for (Expr *RefExpr : VarList) {
3632 auto *DE = cast<DeclRefExpr>(RefExpr);
3633 auto *VD = cast<VarDecl>(DE->getDecl());
3634
3635 // Check if this is a TLS variable or global register.
3636 if (VD->getTLSKind() != VarDecl::TLS_None ||
3637 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3638 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3639 !VD->isLocalVarDecl()))
3640 continue;
3641
3642 // If the used several times in the allocate directive, the same allocator
3643 // must be used.
3645 AllocatorKind, Allocator))
3646 continue;
3647
3648 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3649 // If a list item has a static storage type, the allocator expression in the
3650 // allocator clause must be a constant expression that evaluates to one of
3651 // the predefined memory allocator values.
3652 if (Allocator && VD->hasGlobalStorage()) {
3653 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3654 Diag(Allocator->getExprLoc(),
3655 diag::err_omp_expected_predefined_allocator)
3656 << Allocator->getSourceRange();
3657 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3659 Diag(VD->getLocation(),
3660 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3661 << VD;
3662 continue;
3663 }
3664 }
3665
3666 Vars.push_back(RefExpr);
3667 applyOMPAllocateAttribute(SemaRef, VD, AllocatorKind, Allocator, Alignment,
3668 DE->getSourceRange());
3669 }
3670 if (Vars.empty())
3671 return nullptr;
3672 if (!Owner)
3673 Owner = SemaRef.getCurLexicalContext();
3674 auto *D = OMPAllocateDecl::Create(getASTContext(), Owner, Loc, Vars, Clauses);
3675 D->setAccess(AS_public);
3676 Owner->addDecl(D);
3678}
3679
3682 ArrayRef<OMPClause *> ClauseList) {
3683 OMPRequiresDecl *D = nullptr;
3684 if (!SemaRef.CurContext->isFileContext()) {
3685 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3686 } else {
3687 D = CheckOMPRequiresDecl(Loc, ClauseList);
3688 if (D) {
3689 SemaRef.CurContext->addDecl(D);
3690 DSAStack->addRequiresDecl(D);
3691 }
3692 }
3694}
3695
3697 OpenMPDirectiveKind DKind,
3698 ArrayRef<std::string> Assumptions,
3699 bool SkippedClauses) {
3700 if (!SkippedClauses && Assumptions.empty()) {
3701 unsigned OMPVersion = getLangOpts().OpenMP;
3702 Diag(Loc, diag::err_omp_no_clause_for_directive)
3703 << llvm::omp::getAllAssumeClauseOptions()
3704 << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion);
3705 }
3706
3707 auto *AA =
3708 OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc);
3709 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3710 OMPAssumeScoped.push_back(AA);
3711 return;
3712 }
3713
3714 // Global assumes without assumption clauses are ignored.
3715 if (Assumptions.empty())
3716 return;
3717
3718 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3719 "Unexpected omp assumption directive!");
3720 OMPAssumeGlobal.push_back(AA);
3721
3722 // The OMPAssumeGlobal scope above will take care of new declarations but
3723 // we also want to apply the assumption to existing ones, e.g., to
3724 // declarations in included headers. To this end, we traverse all existing
3725 // declaration contexts and annotate function declarations here.
3726 SmallVector<DeclContext *, 8> DeclContexts;
3727 auto *Ctx = SemaRef.CurContext;
3728 while (Ctx->getLexicalParent())
3729 Ctx = Ctx->getLexicalParent();
3730 DeclContexts.push_back(Ctx);
3731 while (!DeclContexts.empty()) {
3732 DeclContext *DC = DeclContexts.pop_back_val();
3733 for (auto *SubDC : DC->decls()) {
3734 if (SubDC->isInvalidDecl())
3735 continue;
3736 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3737 DeclContexts.push_back(CTD->getTemplatedDecl());
3738 llvm::append_range(DeclContexts, CTD->specializations());
3739 continue;
3740 }
3741 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3742 DeclContexts.push_back(DC);
3743 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3744 F->addAttr(AA);
3745 continue;
3746 }
3747 }
3748 }
3749}
3750
3752 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3753 OMPAssumeScoped.pop_back();
3754}
3755
3757 Stmt *AStmt,
3758 SourceLocation StartLoc,
3759 SourceLocation EndLoc) {
3760 if (!AStmt)
3761 return StmtError();
3762
3763 return OMPAssumeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
3764 AStmt);
3765}
3766
3769 ArrayRef<OMPClause *> ClauseList) {
3770 /// For target specific clauses, the requires directive cannot be
3771 /// specified after the handling of any of the target regions in the
3772 /// current compilation unit.
3773 ArrayRef<SourceLocation> TargetLocations =
3774 DSAStack->getEncounteredTargetLocs();
3775 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3776 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3777 for (const OMPClause *CNew : ClauseList) {
3778 // Check if any of the requires clauses affect target regions.
3783 Diag(Loc, diag::err_omp_directive_before_requires)
3784 << "target" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3785 for (SourceLocation TargetLoc : TargetLocations) {
3786 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3787 << "target";
3788 }
3789 } else if (!AtomicLoc.isInvalid() &&
3791 Diag(Loc, diag::err_omp_directive_before_requires)
3792 << "atomic" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3793 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3794 << "atomic";
3795 }
3796 }
3797 }
3798
3799 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3801 getASTContext(), SemaRef.getCurLexicalContext(), Loc, ClauseList);
3802 return nullptr;
3803}
3804
3805static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3806 const ValueDecl *D,
3807 const DSAStackTy::DSAVarData &DVar,
3808 bool IsLoopIterVar) {
3809 if (DVar.RefExpr) {
3810 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3811 << getOpenMPClauseNameForDiag(DVar.CKind);
3812 return;
3813 }
3814 enum {
3815 PDSA_StaticMemberShared,
3816 PDSA_StaticLocalVarShared,
3817 PDSA_LoopIterVarPrivate,
3818 PDSA_LoopIterVarLinear,
3819 PDSA_LoopIterVarLastprivate,
3820 PDSA_ConstVarShared,
3821 PDSA_GlobalVarShared,
3822 PDSA_TaskVarFirstprivate,
3823 PDSA_LocalVarPrivate,
3824 PDSA_Implicit
3825 } Reason = PDSA_Implicit;
3826 bool ReportHint = false;
3827 auto ReportLoc = D->getLocation();
3828 auto *VD = dyn_cast<VarDecl>(D);
3829 if (IsLoopIterVar) {
3830 if (DVar.CKind == OMPC_private)
3831 Reason = PDSA_LoopIterVarPrivate;
3832 else if (DVar.CKind == OMPC_lastprivate)
3833 Reason = PDSA_LoopIterVarLastprivate;
3834 else
3835 Reason = PDSA_LoopIterVarLinear;
3836 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3837 DVar.CKind == OMPC_firstprivate) {
3838 Reason = PDSA_TaskVarFirstprivate;
3839 ReportLoc = DVar.ImplicitDSALoc;
3840 } else if (VD && VD->isStaticLocal())
3841 Reason = PDSA_StaticLocalVarShared;
3842 else if (VD && VD->isStaticDataMember())
3843 Reason = PDSA_StaticMemberShared;
3844 else if (VD && VD->isFileVarDecl())
3845 Reason = PDSA_GlobalVarShared;
3846 else if (D->getType().isConstant(SemaRef.getASTContext()))
3847 Reason = PDSA_ConstVarShared;
3848 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3849 ReportHint = true;
3850 Reason = PDSA_LocalVarPrivate;
3851 }
3852 if (Reason != PDSA_Implicit) {
3853 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
3854 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3855 << Reason << ReportHint
3856 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
3857 } else if (DVar.ImplicitDSALoc.isValid()) {
3858 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3859 << getOpenMPClauseNameForDiag(DVar.CKind);
3860 }
3861}
3862
3865 bool IsAggregateOrDeclareTarget) {
3867 switch (M) {
3868 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3869 case OMPC_DEFAULTMAP_MODIFIER_storage:
3870 Kind = OMPC_MAP_alloc;
3871 break;
3872 case OMPC_DEFAULTMAP_MODIFIER_to:
3873 Kind = OMPC_MAP_to;
3874 break;
3875 case OMPC_DEFAULTMAP_MODIFIER_from:
3876 Kind = OMPC_MAP_from;
3877 break;
3878 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3879 Kind = OMPC_MAP_tofrom;
3880 break;
3881 case OMPC_DEFAULTMAP_MODIFIER_present:
3882 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3883 // If implicit-behavior is present, each variable referenced in the
3884 // construct in the category specified by variable-category is treated as if
3885 // it had been listed in a map clause with the map-type of alloc and
3886 // map-type-modifier of present.
3887 Kind = OMPC_MAP_alloc;
3888 break;
3889 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3890 case OMPC_DEFAULTMAP_MODIFIER_private:
3892 llvm_unreachable("Unexpected defaultmap implicit behavior");
3893 case OMPC_DEFAULTMAP_MODIFIER_none:
3894 case OMPC_DEFAULTMAP_MODIFIER_default:
3896 // IsAggregateOrDeclareTarget could be true if:
3897 // 1. the implicit behavior for aggregate is tofrom
3898 // 2. it's a declare target link
3899 if (IsAggregateOrDeclareTarget) {
3900 Kind = OMPC_MAP_tofrom;
3901 break;
3902 }
3903 llvm_unreachable("Unexpected defaultmap implicit behavior");
3904 }
3905 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3906 return Kind;
3907}
3908
3909namespace {
3910struct VariableImplicitInfo {
3911 static const unsigned MapKindNum = OMPC_MAP_unknown;
3912 static const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3913
3914 llvm::SetVector<Expr *> Privates;
3915 llvm::SetVector<Expr *> Firstprivates;
3916 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3917 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3918 MapModifiers[DefaultmapKindNum];
3919};
3920
3921class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3922 DSAStackTy *Stack;
3923 Sema &SemaRef;
3924 OpenMPDirectiveKind DKind = OMPD_unknown;
3925 bool ErrorFound = false;
3926 bool TryCaptureCXXThisMembers = false;
3927 CapturedStmt *CS = nullptr;
3928
3929 VariableImplicitInfo ImpInfo;
3930 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3931 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3932
3933 void VisitSubCaptures(OMPExecutableDirective *S) {
3934 // Check implicitly captured variables.
3935 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3936 return;
3937 if (S->getDirectiveKind() == OMPD_atomic ||
3938 S->getDirectiveKind() == OMPD_critical ||
3939 S->getDirectiveKind() == OMPD_section ||
3940 S->getDirectiveKind() == OMPD_master ||
3941 S->getDirectiveKind() == OMPD_masked ||
3942 S->getDirectiveKind() == OMPD_scope ||
3943 S->getDirectiveKind() == OMPD_assume ||
3944 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3945 Visit(S->getAssociatedStmt());
3946 return;
3947 }
3948 visitSubCaptures(S->getInnermostCapturedStmt());
3949 // Try to capture inner this->member references to generate correct mappings
3950 // and diagnostics.
3951 if (TryCaptureCXXThisMembers ||
3953 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3954 [](const CapturedStmt::Capture &C) {
3955 return C.capturesThis();
3956 }))) {
3957 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3958 TryCaptureCXXThisMembers = true;
3959 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3960 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3961 }
3962 // In tasks firstprivates are not captured anymore, need to analyze them
3963 // explicitly.
3964 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3965 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3966 for (OMPClause *C : S->clauses())
3967 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3968 for (Expr *Ref : FC->varlist())
3969 Visit(Ref);
3970 }
3971 }
3972 }
3973
3974public:
3975 void VisitDeclRefExpr(DeclRefExpr *E) {
3976 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3980 return;
3981 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3982 // Check the datasharing rules for the expressions in the clauses.
3983 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3984 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3985 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3986 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3987 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3988 Visit(CED->getInit());
3989 return;
3990 }
3991 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3992 // Do not analyze internal variables and do not enclose them into
3993 // implicit clauses.
3994 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3995 return;
3996 VD = VD->getCanonicalDecl();
3997 // Skip internally declared variables.
3998 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3999 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4000 !Stack->isImplicitTaskFirstprivate(VD))
4001 return;
4002 // Skip allocators in uses_allocators clauses.
4003 if (Stack->isUsesAllocatorsDecl(VD))
4004 return;
4005
4006 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
4007 // Check if the variable has explicit DSA set and stop analysis if it so.
4008 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
4009 return;
4010
4011 // Skip internally declared static variables.
4012 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
4013 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
4014 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
4015 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
4016 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
4017 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4018 !Stack->isImplicitTaskFirstprivate(VD))
4019 return;
4020
4021 SourceLocation ELoc = E->getExprLoc();
4022 // The default(none) clause requires that each variable that is referenced
4023 // in the construct, and does not have a predetermined data-sharing
4024 // attribute, must have its data-sharing attribute explicitly determined
4025 // by being listed in a data-sharing attribute clause.
4026 if (DVar.CKind == OMPC_unknown &&
4027 (Stack->getDefaultDSA() == DSA_none ||
4028 Stack->getDefaultDSA() == DSA_private ||
4029 Stack->getDefaultDSA() == DSA_firstprivate) &&
4030 isImplicitOrExplicitTaskingRegion(DKind) &&
4031 VarsWithInheritedDSA.count(VD) == 0) {
4032 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
4033 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
4034 Stack->getDefaultDSA() == DSA_private)) {
4035 DSAStackTy::DSAVarData DVar =
4036 Stack->getImplicitDSA(VD, /*FromParent=*/false);
4037 InheritedDSA = DVar.CKind == OMPC_unknown;
4038 }
4039 if (InheritedDSA)
4040 VarsWithInheritedDSA[VD] = E;
4041 if (Stack->getDefaultDSA() == DSA_none)
4042 return;
4043 }
4044
4045 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
4046 // If implicit-behavior is none, each variable referenced in the
4047 // construct that does not have a predetermined data-sharing attribute
4048 // and does not appear in a to or link clause on a declare target
4049 // directive must be listed in a data-mapping attribute clause, a
4050 // data-sharing attribute clause (including a data-sharing attribute
4051 // clause on a combined construct where target. is one of the
4052 // constituent constructs), or an is_device_ptr clause.
4053 OpenMPDefaultmapClauseKind ClauseKind =
4055 if (SemaRef.getLangOpts().OpenMP >= 50) {
4056 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
4057 OMPC_DEFAULTMAP_MODIFIER_none;
4058 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
4059 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
4060 // Only check for data-mapping attribute and is_device_ptr here
4061 // since we have already make sure that the declaration does not
4062 // have a data-sharing attribute above
4063 if (!Stack->checkMappableExprComponentListsForDecl(
4064 VD, /*CurrentRegionOnly=*/true,
4066 MapExprComponents,
4068 auto MI = MapExprComponents.rbegin();
4069 auto ME = MapExprComponents.rend();
4070 return MI != ME && MI->getAssociatedDeclaration() == VD;
4071 })) {
4072 VarsWithInheritedDSA[VD] = E;
4073 return;
4074 }
4075 }
4076 }
4077 if (SemaRef.getLangOpts().OpenMP > 50) {
4078 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
4079 OMPC_DEFAULTMAP_MODIFIER_present;
4080 if (IsModifierPresent) {
4081 if (!llvm::is_contained(ImpInfo.MapModifiers[ClauseKind],
4082 OMPC_MAP_MODIFIER_present)) {
4083 ImpInfo.MapModifiers[ClauseKind].push_back(
4084 OMPC_MAP_MODIFIER_present);
4085 }
4086 }
4087 }
4088
4090 !Stack->isLoopControlVariable(VD).first) {
4091 if (!Stack->checkMappableExprComponentListsForDecl(
4092 VD, /*CurrentRegionOnly=*/true,
4094 StackComponents,
4096 if (SemaRef.LangOpts.OpenMP >= 50)
4097 return !StackComponents.empty();
4098 // Variable is used if it has been marked as an array, array
4099 // section, array shaping or the variable itself.
4100 return StackComponents.size() == 1 ||
4101 llvm::all_of(
4102 llvm::drop_begin(llvm::reverse(StackComponents)),
4103 [](const OMPClauseMappableExprCommon::
4104 MappableComponent &MC) {
4105 return MC.getAssociatedDeclaration() ==
4106 nullptr &&
4107 (isa<ArraySectionExpr>(
4108 MC.getAssociatedExpression()) ||
4109 isa<OMPArrayShapingExpr>(
4110 MC.getAssociatedExpression()) ||
4111 isa<ArraySubscriptExpr>(
4112 MC.getAssociatedExpression()));
4113 });
4114 })) {
4115 bool IsFirstprivate = false;
4116 // By default lambdas are captured as firstprivates.
4117 if (const auto *RD =
4119 IsFirstprivate = RD->isLambda();
4120 IsFirstprivate =
4121 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
4122 if (IsFirstprivate) {
4123 ImpInfo.Firstprivates.insert(E);
4124 } else {
4126 Stack->getDefaultmapModifier(ClauseKind);
4127 if (M == OMPC_DEFAULTMAP_MODIFIER_private) {
4128 ImpInfo.Privates.insert(E);
4129 } else {
4131 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
4132 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
4133 }
4134 }
4135 return;
4136 }
4137 }
4138
4139 // OpenMP [2.9.3.6, Restrictions, p.2]
4140 // A list item that appears in a reduction clause of the innermost
4141 // enclosing worksharing or parallel construct may not be accessed in an
4142 // explicit task.
4143 DVar = Stack->hasInnermostDSA(
4144 VD,
4145 [](OpenMPClauseKind C, bool AppliedToPointee) {
4146 return C == OMPC_reduction && !AppliedToPointee;
4147 },
4148 [](OpenMPDirectiveKind K) {
4149 return isOpenMPParallelDirective(K) ||
4151 },
4152 /*FromParent=*/true);
4153 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4154 ErrorFound = true;
4155 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4156 reportOriginalDsa(SemaRef, Stack, VD, DVar);
4157 return;
4158 }
4159
4160 // Define implicit data-sharing attributes for task.
4161 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
4162 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
4163 (((Stack->getDefaultDSA() == DSA_firstprivate &&
4164 DVar.CKind == OMPC_firstprivate) ||
4165 (Stack->getDefaultDSA() == DSA_private &&
4166 DVar.CKind == OMPC_private)) &&
4167 !DVar.RefExpr)) &&
4168 !Stack->isLoopControlVariable(VD).first) {
4169 if (Stack->getDefaultDSA() == DSA_private)
4170 ImpInfo.Privates.insert(E);
4171 else
4172 ImpInfo.Firstprivates.insert(E);
4173 return;
4174 }
4175
4176 // Store implicitly used globals with declare target link for parent
4177 // target.
4178 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
4179 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
4180 Stack->addToParentTargetRegionLinkGlobals(E);
4181 return;
4182 }
4183 }
4184 }
4185 void VisitMemberExpr(MemberExpr *E) {
4186 if (E->isTypeDependent() || E->isValueDependent() ||
4188 return;
4189 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
4190 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
4191 if (!FD)
4192 return;
4193 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
4194 // Check if the variable has explicit DSA set and stop analysis if it
4195 // so.
4196 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
4197 return;
4198
4200 !Stack->isLoopControlVariable(FD).first &&
4201 !Stack->checkMappableExprComponentListsForDecl(
4202 FD, /*CurrentRegionOnly=*/true,
4204 StackComponents,
4206 return isa<CXXThisExpr>(
4207 cast<MemberExpr>(
4208 StackComponents.back().getAssociatedExpression())
4209 ->getBase()
4210 ->IgnoreParens());
4211 })) {
4212 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
4213 // A bit-field cannot appear in a map clause.
4214 //
4215 if (FD->isBitField())
4216 return;
4217
4218 // Check to see if the member expression is referencing a class that
4219 // has already been explicitly mapped
4220 if (Stack->isClassPreviouslyMapped(TE->getType()))
4221 return;
4222
4224 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4225 OpenMPDefaultmapClauseKind ClauseKind =
4228 Modifier, /*IsAggregateOrDeclareTarget=*/true);
4229 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
4230 return;
4231 }
4232
4233 SourceLocation ELoc = E->getExprLoc();
4234 // OpenMP [2.9.3.6, Restrictions, p.2]
4235 // A list item that appears in a reduction clause of the innermost
4236 // enclosing worksharing or parallel construct may not be accessed in
4237 // an explicit task.
4238 DVar = Stack->hasInnermostDSA(
4239 FD,
4240 [](OpenMPClauseKind C, bool AppliedToPointee) {
4241 return C == OMPC_reduction && !AppliedToPointee;
4242 },
4243 [](OpenMPDirectiveKind K) {
4244 return isOpenMPParallelDirective(K) ||
4246 },
4247 /*FromParent=*/true);
4248 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4249 ErrorFound = true;
4250 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4251 reportOriginalDsa(SemaRef, Stack, FD, DVar);
4252 return;
4253 }
4254
4255 // Define implicit data-sharing attributes for task.
4256 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4257 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4258 !Stack->isLoopControlVariable(FD).first) {
4259 // Check if there is a captured expression for the current field in the
4260 // region. Do not mark it as firstprivate unless there is no captured
4261 // expression.
4262 // TODO: try to make it firstprivate.
4263 if (DVar.CKind != OMPC_unknown)
4264 ImpInfo.Firstprivates.insert(E);
4265 }
4266 return;
4267 }
4270 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4271 DKind, /*NoDiagnose=*/true))
4272 return;
4273 const auto *VD = cast<ValueDecl>(
4274 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4275 if (!Stack->checkMappableExprComponentListsForDecl(
4276 VD, /*CurrentRegionOnly=*/true,
4277 [&CurComponents](
4279 StackComponents,
4281 auto CCI = CurComponents.rbegin();
4282 auto CCE = CurComponents.rend();
4283 for (const auto &SC : llvm::reverse(StackComponents)) {
4284 // Do both expressions have the same kind?
4285 if (CCI->getAssociatedExpression()->getStmtClass() !=
4286 SC.getAssociatedExpression()->getStmtClass())
4287 if (!((isa<ArraySectionExpr>(
4288 SC.getAssociatedExpression()) ||
4289 isa<OMPArrayShapingExpr>(
4290 SC.getAssociatedExpression())) &&
4291 isa<ArraySubscriptExpr>(
4292 CCI->getAssociatedExpression())))
4293 return false;
4294
4295 const Decl *CCD = CCI->getAssociatedDeclaration();
4296 const Decl *SCD = SC.getAssociatedDeclaration();
4297 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4298 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4299 if (SCD != CCD)
4300 return false;
4301 std::advance(CCI, 1);
4302 if (CCI == CCE)
4303 break;
4304 }
4305 return true;
4306 })) {
4307 Visit(E->getBase());
4308 }
4309 } else if (!TryCaptureCXXThisMembers) {
4310 Visit(E->getBase());
4311 }
4312 }
4313 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4314 for (OMPClause *C : S->clauses()) {
4315 // Skip analysis of arguments of private clauses for task|target
4316 // directives.
4317 if (isa_and_nonnull<OMPPrivateClause>(C))
4318 continue;
4319 // Skip analysis of arguments of implicitly defined firstprivate clause
4320 // for task|target directives.
4321 // Skip analysis of arguments of implicitly defined map clause for target
4322 // directives.
4324 C->isImplicit() && !isOpenMPTaskingDirective(DKind))) {
4325 for (Stmt *CC : C->children()) {
4326 if (CC)
4327 Visit(CC);
4328 }
4329 }
4330 }
4331 // Check implicitly captured variables.
4332 VisitSubCaptures(S);
4333 }
4334
4335 void VisitOMPCanonicalLoopNestTransformationDirective(
4336 OMPCanonicalLoopNestTransformationDirective *S) {
4337 // Loop transformation directives do not introduce data sharing
4338 VisitStmt(S);
4339 }
4340
4341 void VisitCallExpr(CallExpr *S) {
4342 for (Stmt *C : S->arguments()) {
4343 if (C) {
4344 // Check implicitly captured variables in the task-based directives to
4345 // check if they must be firstprivatized.
4346 Visit(C);
4347 }
4348 }
4349 if (Expr *Callee = S->getCallee()) {
4350 auto *CI = Callee->IgnoreParenImpCasts();
4351 if (auto *CE = dyn_cast<MemberExpr>(CI))
4352 Visit(CE->getBase());
4353 else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4354 Visit(CE);
4355 }
4356 }
4357 void VisitStmt(Stmt *S) {
4358 for (Stmt *C : S->children()) {
4359 if (C) {
4360 // Check implicitly captured variables in the task-based directives to
4361 // check if they must be firstprivatized.
4362 Visit(C);
4363 }
4364 }
4365 }
4366
4367 void visitSubCaptures(CapturedStmt *S) {
4368 for (const CapturedStmt::Capture &Cap : S->captures()) {
4369 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4370 continue;
4371 VarDecl *VD = Cap.getCapturedVar();
4372 // Do not try to map the variable if it or its sub-component was mapped
4373 // already.
4375 Stack->checkMappableExprComponentListsForDecl(
4376 VD, /*CurrentRegionOnly=*/true,
4378 OpenMPClauseKind) { return true; }))
4379 continue;
4380 DeclRefExpr *DRE = buildDeclRefExpr(
4381 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4382 Cap.getLocation(), /*RefersToCapture=*/true);
4383 Visit(DRE);
4384 }
4385 }
4386 bool isErrorFound() const { return ErrorFound; }
4387 const VariableImplicitInfo &getImplicitInfo() const { return ImpInfo; }
4388 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4389 return VarsWithInheritedDSA;
4390 }
4391
4392 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4393 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4394 DKind = S->getCurrentDirective();
4395 // Process declare target link variables for the target directives.
4397 for (DeclRefExpr *E : Stack->getLinkGlobals())
4398 Visit(E);
4399 }
4400 }
4401};
4402} // namespace
4403
4404static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4405 OpenMPDirectiveKind DKind,
4406 bool ScopeEntry) {
4409 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4410 if (isOpenMPTeamsDirective(DKind))
4411 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4412 if (isOpenMPParallelDirective(DKind))
4413 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4415 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4416 if (isOpenMPSimdDirective(DKind))
4417 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4418 Stack->handleConstructTrait(Traits, ScopeEntry);
4419}
4420
4421static SmallVector<SemaOpenMP::CapturedParamNameType>
4422getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4423 ASTContext &Context = SemaRef.getASTContext();
4424 QualType KmpInt32Ty =
4425 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4426 QualType KmpInt32PtrTy =
4427 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4429 std::make_pair(".global_tid.", KmpInt32PtrTy),
4430 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4431 };
4432 if (LoopBoundSharing) {
4433 QualType KmpSizeTy = Context.getSizeType().withConst();
4434 Params.push_back(std::make_pair(".previous.lb.", KmpSizeTy));
4435 Params.push_back(std::make_pair(".previous.ub.", KmpSizeTy));
4436 }
4437
4438 // __context with shared vars
4439 Params.push_back(std::make_pair(StringRef(), QualType()));
4440 return Params;
4441}
4442
4443static SmallVector<SemaOpenMP::CapturedParamNameType>
4445 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4446}
4447
4448static SmallVector<SemaOpenMP::CapturedParamNameType>
4450 ASTContext &Context = SemaRef.getASTContext();
4451 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4452 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4453 QualType KmpInt32PtrTy =
4454 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4455 QualType Args[] = {VoidPtrTy};
4457 EPI.Variadic = true;
4458 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4460 std::make_pair(".global_tid.", KmpInt32Ty),
4461 std::make_pair(".part_id.", KmpInt32PtrTy),
4462 std::make_pair(".privates.", VoidPtrTy),
4463 std::make_pair(
4464 ".copy_fn.",
4465 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4466 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4467 std::make_pair(StringRef(), QualType()) // __context with shared vars
4468 };
4469 return Params;
4470}
4471
4472static SmallVector<SemaOpenMP::CapturedParamNameType>
4474 ASTContext &Context = SemaRef.getASTContext();
4476 if (SemaRef.getLangOpts().OpenMPIsTargetDevice) {
4477 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4478 Params.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4479 }
4480 // __context with shared vars
4481 Params.push_back(std::make_pair(StringRef(), QualType()));
4482 return Params;
4483}
4484
4485static SmallVector<SemaOpenMP::CapturedParamNameType>
4488 std::make_pair(StringRef(), QualType()) // __context with shared vars
4489 };
4490 return Params;
4491}
4492
4493static SmallVector<SemaOpenMP::CapturedParamNameType>
4495 ASTContext &Context = SemaRef.getASTContext();
4496 QualType KmpInt32Ty =
4497 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4498 QualType KmpUInt64Ty =
4499 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4500 QualType KmpInt64Ty =
4501 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4502 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4503 QualType KmpInt32PtrTy =
4504 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4505 QualType Args[] = {VoidPtrTy};
4507 EPI.Variadic = true;
4508 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4510 std::make_pair(".global_tid.", KmpInt32Ty),
4511 std::make_pair(".part_id.", KmpInt32PtrTy),
4512 std::make_pair(".privates.", VoidPtrTy),
4513 std::make_pair(
4514 ".copy_fn.",
4515 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4516 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4517 std::make_pair(".lb.", KmpUInt64Ty),
4518 std::make_pair(".ub.", KmpUInt64Ty),
4519 std::make_pair(".st.", KmpInt64Ty),
4520 std::make_pair(".liter.", KmpInt32Ty),
4521 std::make_pair(".reductions.", VoidPtrTy),
4522 std::make_pair(StringRef(), QualType()) // __context with shared vars
4523 };
4524 return Params;
4525}
4526
4528 Scope *CurScope, SourceLocation Loc) {
4530 getOpenMPCaptureRegions(Regions, DKind);
4531
4532 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(DKind);
4533
4534 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4535 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4536 SemaRef.getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4537 };
4538
4539 for (auto [Level, RKind] : llvm::enumerate(Regions)) {
4540 switch (RKind) {
4541 // All region kinds that can be returned from `getOpenMPCaptureRegions`
4542 // are listed here.
4543 case OMPD_parallel:
4545 Loc, CurScope, CR_OpenMP,
4546 getParallelRegionParams(SemaRef, LoopBoundSharing), Level);
4547 break;
4548 case OMPD_teams:
4549 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4550 getTeamsRegionParams(SemaRef), Level);
4551 break;
4552 case OMPD_task:
4553 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4554 getTaskRegionParams(SemaRef), Level);
4555 // Mark this captured region as inlined, because we don't use outlined
4556 // function directly.
4557 MarkAsInlined(SemaRef.getCurCapturedRegion());
4558 break;
4559 case OMPD_taskloop:
4560 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4561 getTaskloopRegionParams(SemaRef), Level);
4562 // Mark this captured region as inlined, because we don't use outlined
4563 // function directly.
4564 MarkAsInlined(SemaRef.getCurCapturedRegion());
4565 break;
4566 case OMPD_target:
4567 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4568 getTargetRegionParams(SemaRef), Level);
4569 break;
4570 case OMPD_unknown:
4571 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4572 getUnknownRegionParams(SemaRef));
4573 break;
4574 case OMPD_metadirective:
4575 case OMPD_nothing:
4576 default:
4577 llvm_unreachable("Unexpected capture region");
4578 }
4579 }
4580}
4581
4583 Scope *CurScope) {
4584 switch (DKind) {
4585 case OMPD_atomic:
4586 case OMPD_critical:
4587 case OMPD_masked:
4588 case OMPD_master:
4589 case OMPD_section:
4590 case OMPD_tile:
4591 case OMPD_stripe:
4592 case OMPD_unroll:
4593 case OMPD_reverse:
4594 case OMPD_interchange:
4595 case OMPD_fuse:
4596 case OMPD_assume:
4597 break;
4598 default:
4599 processCapturedRegions(SemaRef, DKind, CurScope,
4600 DSAStack->getConstructLoc());
4601 break;
4602 }
4603
4604 DSAStack->setContext(SemaRef.CurContext);
4605 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
4606}
4607
4608int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4609 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4610}
4611
4614 getOpenMPCaptureRegions(CaptureRegions, DKind);
4615 return CaptureRegions.size();
4616}
4617
4619 Expr *CaptureExpr, bool WithInit,
4620 DeclContext *CurContext,
4621 bool AsExpression) {
4622 assert(CaptureExpr);
4623 ASTContext &C = S.getASTContext();
4624 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4625 QualType Ty = Init->getType();
4626 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4627 if (S.getLangOpts().CPlusPlus) {
4628 Ty = C.getLValueReferenceType(Ty);
4629 } else {
4630 Ty = C.getPointerType(Ty);
4631 ExprResult Res =
4632 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4633 if (!Res.isUsable())
4634 return nullptr;
4635 Init = Res.get();
4636 }
4637 WithInit = true;
4638 }
4639 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4640 CaptureExpr->getBeginLoc());
4641 if (!WithInit)
4642 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4643 CurContext->addHiddenDecl(CED);
4645 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4646 return CED;
4647}
4648
4649static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4650 bool WithInit) {
4652 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4654 else
4655 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4656 S.CurContext,
4657 /*AsExpression=*/false);
4658 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4659 CaptureExpr->getExprLoc());
4660}
4661
4662static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4663 StringRef Name) {
4664 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4665 if (!Ref) {
4667 S, &S.getASTContext().Idents.get(Name), CaptureExpr,
4668 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4669 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4670 CaptureExpr->getExprLoc());
4671 }
4672 ExprResult Res = Ref;
4673 if (!S.getLangOpts().CPlusPlus &&
4674 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4675 Ref->getType()->isPointerType()) {
4676 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4677 if (!Res.isUsable())
4678 return ExprError();
4679 }
4680 return S.DefaultLvalueConversion(Res.get());
4681}
4682
4683namespace {
4684// OpenMP directives parsed in this section are represented as a
4685// CapturedStatement with an associated statement. If a syntax error
4686// is detected during the parsing of the associated statement, the
4687// compiler must abort processing and close the CapturedStatement.
4688//
4689// Combined directives such as 'target parallel' have more than one
4690// nested CapturedStatements. This RAII ensures that we unwind out
4691// of all the nested CapturedStatements when an error is found.
4692class CaptureRegionUnwinderRAII {
4693private:
4694 Sema &S;
4695 bool &ErrorFound;
4696 OpenMPDirectiveKind DKind = OMPD_unknown;
4697
4698public:
4699 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4700 OpenMPDirectiveKind DKind)
4701 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4702 ~CaptureRegionUnwinderRAII() {
4703 if (ErrorFound) {
4704 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4705 while (--ThisCaptureLevel >= 0)
4707 }
4708 }
4709};
4710} // namespace
4711
4713 // Capture variables captured by reference in lambdas for target-based
4714 // directives.
4715 if (!SemaRef.CurContext->isDependentContext() &&
4716 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4718 DSAStack->getCurrentDirective()))) {
4719 QualType Type = V->getType();
4720 if (const auto *RD = Type.getCanonicalType()
4721 .getNonReferenceType()
4722 ->getAsCXXRecordDecl()) {
4723 bool SavedForceCaptureByReferenceInTargetExecutable =
4724 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4725 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4726 /*V=*/true);
4727 if (RD->isLambda()) {
4728 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4729 FieldDecl *ThisCapture;
4730 RD->getCaptureFields(Captures, ThisCapture);
4731 for (const LambdaCapture &LC : RD->captures()) {
4732 if (LC.getCaptureKind() == LCK_ByRef) {
4733 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4734 DeclContext *VDC = VD->getDeclContext();
4735 if (!VDC->Encloses(SemaRef.CurContext))
4736 continue;
4737 SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
4738 } else if (LC.getCaptureKind() == LCK_This) {
4739 QualType ThisTy = SemaRef.getCurrentThisType();
4740 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4741 ThisTy, ThisCapture->getType()))
4742 SemaRef.CheckCXXThisCapture(LC.getLocation());
4743 }
4744 }
4745 }
4746 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4747 SavedForceCaptureByReferenceInTargetExecutable);
4748 }
4749 }
4750}
4751
4753 const ArrayRef<OMPClause *> Clauses) {
4754 const OMPOrderedClause *Ordered = nullptr;
4755 const OMPOrderClause *Order = nullptr;
4756
4757 for (const OMPClause *Clause : Clauses) {
4758 if (Clause->getClauseKind() == OMPC_ordered)
4759 Ordered = cast<OMPOrderedClause>(Clause);
4760 else if (Clause->getClauseKind() == OMPC_order) {
4761 Order = cast<OMPOrderClause>(Clause);
4762 if (Order->getKind() != OMPC_ORDER_concurrent)
4763 Order = nullptr;
4764 }
4765 if (Ordered && Order)
4766 break;
4767 }
4768
4769 if (Ordered && Order) {
4770 S.Diag(Order->getKindKwLoc(),
4771 diag::err_omp_simple_clause_incompatible_with_ordered)
4772 << getOpenMPClauseNameForDiag(OMPC_order)
4773 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4774 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4775 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4776 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4777 return true;
4778 }
4779 return false;
4780}
4781
4783 ArrayRef<OMPClause *> Clauses) {
4785 /*ScopeEntry=*/false);
4786 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
4787 return S;
4788
4789 bool ErrorFound = false;
4790 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4791 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4792 if (!S.isUsable()) {
4793 ErrorFound = true;
4794 return StmtError();
4795 }
4796
4798 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4799 OMPOrderedClause *OC = nullptr;
4800 OMPScheduleClause *SC = nullptr;
4803 // This is required for proper codegen.
4804 for (OMPClause *Clause : Clauses) {
4805 if (!getLangOpts().OpenMPSimd &&
4806 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4807 DSAStack->getCurrentDirective() == OMPD_target) &&
4808 Clause->getClauseKind() == OMPC_in_reduction) {
4809 // Capture taskgroup task_reduction descriptors inside the tasking regions
4810 // with the corresponding in_reduction items.
4811 auto *IRC = cast<OMPInReductionClause>(Clause);
4812 for (Expr *E : IRC->taskgroup_descriptors())
4813 if (E)
4814 SemaRef.MarkDeclarationsReferencedInExpr(E);
4815 }
4816 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4817 Clause->getClauseKind() == OMPC_copyprivate ||
4818 (getLangOpts().OpenMPUseTLS &&
4819 getASTContext().getTargetInfo().isTLSSupported() &&
4820 Clause->getClauseKind() == OMPC_copyin)) {
4821 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4822 // Mark all variables in private list clauses as used in inner region.
4823 for (Stmt *VarRef : Clause->children()) {
4824 if (auto *E = cast_or_null<Expr>(VarRef)) {
4825 SemaRef.MarkDeclarationsReferencedInExpr(E);
4826 }
4827 }
4828 DSAStack->setForceVarCapturing(/*V=*/false);
4829 } else if (CaptureRegions.size() > 1 ||
4830 CaptureRegions.back() != OMPD_unknown) {
4831 if (auto *C = OMPClauseWithPreInit::get(Clause))
4832 PICs.push_back(C);
4833 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4834 if (Expr *E = C->getPostUpdateExpr())
4835 SemaRef.MarkDeclarationsReferencedInExpr(E);
4836 }
4837 }
4838 if (Clause->getClauseKind() == OMPC_schedule)
4839 SC = cast<OMPScheduleClause>(Clause);
4840 else if (Clause->getClauseKind() == OMPC_ordered)
4841 OC = cast<OMPOrderedClause>(Clause);
4842 else if (Clause->getClauseKind() == OMPC_linear)
4843 LCs.push_back(cast<OMPLinearClause>(Clause));
4844 }
4845 // Capture allocator expressions if used.
4846 for (Expr *E : DSAStack->getInnerAllocators())
4847 SemaRef.MarkDeclarationsReferencedInExpr(E);
4848 // OpenMP, 2.7.1 Loop Construct, Restrictions
4849 // The nonmonotonic modifier cannot be specified if an ordered clause is
4850 // specified.
4851 if (SC &&
4852 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4854 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4855 OC) {
4856 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4859 diag::err_omp_simple_clause_incompatible_with_ordered)
4860 << getOpenMPClauseNameForDiag(OMPC_schedule)
4861 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4862 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4863 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4864 ErrorFound = true;
4865 }
4866 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4867 // If an order(concurrent) clause is present, an ordered clause may not appear
4868 // on the same directive.
4869 if (checkOrderedOrderSpecified(SemaRef, Clauses))
4870 ErrorFound = true;
4871 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4872 for (const OMPLinearClause *C : LCs) {
4873 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4874 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4875 }
4876 ErrorFound = true;
4877 }
4878 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4879 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4880 OC->getNumForLoops()) {
4881 unsigned OMPVersion = getLangOpts().OpenMP;
4882 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4883 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(), OMPVersion);
4884 ErrorFound = true;
4885 }
4886 if (ErrorFound) {
4887 return StmtError();
4888 }
4889 StmtResult SR = S;
4890 unsigned CompletedRegions = 0;
4891 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4892 // Mark all variables in private list clauses as used in inner region.
4893 // Required for proper codegen of combined directives.
4894 // TODO: add processing for other clauses.
4895 if (ThisCaptureRegion != OMPD_unknown) {
4896 for (const clang::OMPClauseWithPreInit *C : PICs) {
4897 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4898 // Find the particular capture region for the clause if the
4899 // directive is a combined one with multiple capture regions.
4900 // If the directive is not a combined one, the capture region
4901 // associated with the clause is OMPD_unknown and is generated
4902 // only once.
4903 if (CaptureRegion == ThisCaptureRegion ||
4904 CaptureRegion == OMPD_unknown) {
4905 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4906 for (Decl *D : DS->decls())
4907 SemaRef.MarkVariableReferenced(D->getLocation(),
4908 cast<VarDecl>(D));
4909 }
4910 }
4911 }
4912 }
4913 if (ThisCaptureRegion == OMPD_target) {
4914 // Capture allocator traits in the target region. They are used implicitly
4915 // and, thus, are not captured by default.
4916 for (OMPClause *C : Clauses) {
4917 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4918 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4919 ++I) {
4920 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4921 if (Expr *E = D.AllocatorTraits)
4922 SemaRef.MarkDeclarationsReferencedInExpr(E);
4923 }
4924 continue;
4925 }
4926 }
4927 }
4928 if (ThisCaptureRegion == OMPD_parallel) {
4929 // Capture temp arrays for inscan reductions and locals in aligned
4930 // clauses.
4931 for (OMPClause *C : Clauses) {
4932 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4933 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4934 continue;
4935 for (Expr *E : RC->copy_array_temps())
4936 if (E)
4937 SemaRef.MarkDeclarationsReferencedInExpr(E);
4938 }
4939 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4940 for (Expr *E : AC->varlist())
4941 SemaRef.MarkDeclarationsReferencedInExpr(E);
4942 }
4943 }
4944 }
4945 if (++CompletedRegions == CaptureRegions.size())
4946 DSAStack->setBodyComplete();
4947 SR = SemaRef.ActOnCapturedRegionEnd(SR.get());
4948 }
4949 return SR;
4950}
4951
4952static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4953 OpenMPDirectiveKind CancelRegion,
4954 SourceLocation StartLoc) {
4955 // CancelRegion is only needed for cancel and cancellation_point.
4956 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4957 return false;
4958
4959 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4960 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4961 return false;
4962
4963 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
4964 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4965 << getOpenMPDirectiveName(CancelRegion, OMPVersion);
4966 return true;
4967}
4968
4969static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4970 OpenMPDirectiveKind CurrentRegion,
4971 const DeclarationNameInfo &CurrentName,
4972 OpenMPDirectiveKind CancelRegion,
4973 OpenMPBindClauseKind BindKind,
4974 SourceLocation StartLoc) {
4975 if (!Stack->getCurScope())
4976 return false;
4977
4978 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4979 OpenMPDirectiveKind OffendingRegion = ParentRegion;
4980 bool NestingProhibited = false;
4981 bool CloseNesting = true;
4982 bool OrphanSeen = false;
4983 enum {
4984 NoRecommend,
4985 ShouldBeInParallelRegion,
4986 ShouldBeInOrderedRegion,
4987 ShouldBeInTargetRegion,
4988 ShouldBeInTeamsRegion,
4989 ShouldBeInLoopSimdRegion,
4990 } Recommend = NoRecommend;
4991
4994 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4995 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
4996 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
4997
4998 if (OMPVersion >= 50 && Stack->isParentOrderConcurrent() &&
5000 SemaRef.LangOpts)) {
5001 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
5002 << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5003 return true;
5004 }
5005 if (isOpenMPSimdDirective(ParentRegion) &&
5006 ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered) ||
5007 (OMPVersion >= 50 && CurrentRegion != OMPD_ordered &&
5008 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
5009 CurrentRegion != OMPD_scan))) {
5010 // OpenMP [2.16, Nesting of Regions]
5011 // OpenMP constructs may not be nested inside a simd region.
5012 // OpenMP [2.8.1,simd Construct, Restrictions]
5013 // An ordered construct with the simd clause is the only OpenMP
5014 // construct that can appear in the simd region.
5015 // Allowing a SIMD construct nested in another SIMD construct is an
5016 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
5017 // message.
5018 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
5019 // The only OpenMP constructs that can be encountered during execution of
5020 // a simd region are the atomic construct, the loop construct, the simd
5021 // construct and the ordered construct with the simd clause.
5022 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
5023 ? diag::err_omp_prohibited_region_simd
5024 : diag::warn_omp_nesting_simd)
5025 << (OMPVersion >= 50 ? 1 : 0);
5026 return CurrentRegion != OMPD_simd;
5027 }
5028 if (EnclosingConstruct == OMPD_atomic) {
5029 // OpenMP [2.16, Nesting of Regions]
5030 // OpenMP constructs may not be nested inside an atomic region.
5031 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
5032 return true;
5033 }
5034 if (CurrentRegion == OMPD_section) {
5035 // OpenMP [2.7.2, sections Construct, Restrictions]
5036 // Orphaned section directives are prohibited. That is, the section
5037 // directives must appear within the sections construct and must not be
5038 // encountered elsewhere in the sections region.
5039 if (EnclosingConstruct != OMPD_sections) {
5040 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
5041 << (ParentRegion != OMPD_unknown)
5042 << getOpenMPDirectiveName(ParentRegion, OMPVersion);
5043 return true;
5044 }
5045 return false;
5046 }
5047 // Allow some constructs (except teams and cancellation constructs) to be
5048 // orphaned (they could be used in functions, called from OpenMP regions
5049 // with the required preconditions).
5050 if (ParentRegion == OMPD_unknown &&
5051 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
5052 CurrentRegion != OMPD_cancellation_point &&
5053 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5054 return false;
5055 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
5056 // for a detailed explanation
5057 if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
5058 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
5059 (isOpenMPWorksharingDirective(ParentRegion) ||
5060 EnclosingConstruct == OMPD_loop)) {
5061 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
5062 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5063 << true << getOpenMPDirectiveName(ParentRegion, OMPVersion)
5064 << ErrorMsgNumber << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5065 return true;
5066 }
5067 if (CurrentRegion == OMPD_cancellation_point ||
5068 CurrentRegion == OMPD_cancel) {
5069 // OpenMP [2.16, Nesting of Regions]
5070 // A cancellation point construct for which construct-type-clause is
5071 // taskgroup must be nested inside a task construct. A cancellation
5072 // point construct for which construct-type-clause is not taskgroup must
5073 // be closely nested inside an OpenMP construct that matches the type
5074 // specified in construct-type-clause.
5075 // A cancel construct for which construct-type-clause is taskgroup must be
5076 // nested inside a task construct. A cancel construct for which
5077 // construct-type-clause is not taskgroup must be closely nested inside an
5078 // OpenMP construct that matches the type specified in
5079 // construct-type-clause.
5080 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(ParentRegion);
5081 if (CancelRegion == OMPD_taskgroup) {
5082 NestingProhibited =
5083 EnclosingConstruct != OMPD_task &&
5084 (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
5085 } else if (CancelRegion == OMPD_sections) {
5086 NestingProhibited = EnclosingConstruct != OMPD_section &&
5087 EnclosingConstruct != OMPD_sections;
5088 } else {
5089 NestingProhibited = CancelRegion != Leafs.back();
5090 }
5091 OrphanSeen = ParentRegion == OMPD_unknown;
5092 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5093 // OpenMP 5.1 [2.22, Nesting of Regions]
5094 // A masked region may not be closely nested inside a worksharing, loop,
5095 // atomic, task, or taskloop region.
5096 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5097 isOpenMPGenericLoopDirective(ParentRegion) ||
5098 isOpenMPTaskingDirective(ParentRegion);
5099 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5100 // OpenMP [2.16, Nesting of Regions]
5101 // A critical region may not be nested (closely or otherwise) inside a
5102 // critical region with the same name. Note that this restriction is not
5103 // sufficient to prevent deadlock.
5104 SourceLocation PreviousCriticalLoc;
5105 bool DeadLock = Stack->hasDirective(
5106 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5107 const DeclarationNameInfo &DNI,
5108 SourceLocation Loc) {
5109 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5110 PreviousCriticalLoc = Loc;
5111 return true;
5112 }
5113 return false;
5114 },
5115 false /* skip top directive */);
5116 if (DeadLock) {
5117 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
5118 << CurrentName.getName();
5119 if (PreviousCriticalLoc.isValid())
5120 SemaRef.Diag(PreviousCriticalLoc,
5121 diag::note_omp_previous_critical_region);
5122 return true;
5123 }
5124 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5125 // OpenMP 5.1 [2.22, Nesting of Regions]
5126 // A scope region may not be closely nested inside a worksharing, loop,
5127 // task, taskloop, critical, ordered, atomic, or masked region.
5128 // OpenMP 5.1 [2.22, Nesting of Regions]
5129 // A barrier region may not be closely nested inside a worksharing, loop,
5130 // task, taskloop, critical, ordered, atomic, or masked region.
5131 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5132 isOpenMPGenericLoopDirective(ParentRegion) ||
5133 isOpenMPTaskingDirective(ParentRegion) ||
5134 llvm::is_contained({OMPD_masked, OMPD_master,
5135 OMPD_critical, OMPD_ordered},
5136 EnclosingConstruct);
5137 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
5138 !isOpenMPParallelDirective(CurrentRegion) &&
5139 !isOpenMPTeamsDirective(CurrentRegion)) {
5140 // OpenMP 5.1 [2.22, Nesting of Regions]
5141 // A loop region that binds to a parallel region or a worksharing region
5142 // may not be closely nested inside a worksharing, loop, task, taskloop,
5143 // critical, ordered, atomic, or masked region.
5144 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5145 isOpenMPGenericLoopDirective(ParentRegion) ||
5146 isOpenMPTaskingDirective(ParentRegion) ||
5147 llvm::is_contained({OMPD_masked, OMPD_master,
5148 OMPD_critical, OMPD_ordered},
5149 EnclosingConstruct);
5150 Recommend = ShouldBeInParallelRegion;
5151 } else if (CurrentRegion == OMPD_ordered) {
5152 // OpenMP [2.16, Nesting of Regions]
5153 // An ordered region may not be closely nested inside a critical,
5154 // atomic, or explicit task region.
5155 // An ordered region must be closely nested inside a loop region (or
5156 // parallel loop region) with an ordered clause.
5157 // OpenMP [2.8.1,simd Construct, Restrictions]
5158 // An ordered construct with the simd clause is the only OpenMP construct
5159 // that can appear in the simd region.
5160 NestingProhibited = EnclosingConstruct == OMPD_critical ||
5161 isOpenMPTaskingDirective(ParentRegion) ||
5162 !(isOpenMPSimdDirective(ParentRegion) ||
5163 Stack->isParentOrderedRegion());
5164 Recommend = ShouldBeInOrderedRegion;
5165 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
5166 // OpenMP [2.16, Nesting of Regions]
5167 // If specified, a teams construct must be contained within a target
5168 // construct.
5169 NestingProhibited =
5170 (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
5171 (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
5172 EnclosingConstruct != OMPD_target);
5173 OrphanSeen = ParentRegion == OMPD_unknown;
5174 Recommend = ShouldBeInTargetRegion;
5175 } else if (CurrentRegion == OMPD_scan) {
5176 if (OMPVersion >= 50) {
5177 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
5178 // simd, or for simd. This has to take into account combined directives.
5179 // In 5.2 this seems to be implied by the fact that the specified
5180 // separated constructs are do, for, and simd.
5181 NestingProhibited = !llvm::is_contained(
5182 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
5183 } else {
5184 NestingProhibited = true;
5185 }
5186 OrphanSeen = ParentRegion == OMPD_unknown;
5187 Recommend = ShouldBeInLoopSimdRegion;
5188 }
5189 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5190 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5191 EnclosingConstruct == OMPD_teams) {
5192 // OpenMP [5.1, 2.22, Nesting of Regions]
5193 // distribute, distribute simd, distribute parallel worksharing-loop,
5194 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5195 // including any parallel regions arising from combined constructs,
5196 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5197 // only OpenMP regions that may be strictly nested inside the teams
5198 // region.
5199 //
5200 // As an extension, we permit atomic within teams as well.
5201 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5202 !isOpenMPDistributeDirective(CurrentRegion) &&
5203 CurrentRegion != OMPD_loop &&
5204 !(SemaRef.getLangOpts().OpenMPExtensions &&
5205 CurrentRegion == OMPD_atomic);
5206 Recommend = ShouldBeInParallelRegion;
5207 }
5208 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5209 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5210 // If the bind clause is present on the loop construct and binding is
5211 // teams then the corresponding loop region must be strictly nested inside
5212 // a teams region.
5213 NestingProhibited =
5214 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5215 Recommend = ShouldBeInTeamsRegion;
5216 }
5217 if (!NestingProhibited && isOpenMPNestingDistributeDirective(CurrentRegion)) {
5218 // OpenMP 4.5 [2.17 Nesting of Regions]
5219 // The region associated with the distribute construct must be strictly
5220 // nested inside a teams region
5221 NestingProhibited = EnclosingConstruct != OMPD_teams;
5222 Recommend = ShouldBeInTeamsRegion;
5223 }
5224 if (!NestingProhibited &&
5225 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5226 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5227 // OpenMP 4.5 [2.17 Nesting of Regions]
5228 // If a target, target update, target data, target enter data, or
5229 // target exit data construct is encountered during execution of a
5230 // target region, the behavior is unspecified.
5231 NestingProhibited = Stack->hasDirective(
5232 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5235 OffendingRegion = K;
5236 return true;
5237 }
5238 return false;
5239 },
5240 false /* don't skip top directive */);
5241 CloseNesting = false;
5242 }
5243 if (NestingProhibited) {
5244 if (OrphanSeen) {
5245 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5246 << getOpenMPDirectiveName(CurrentRegion, OMPVersion) << Recommend;
5247 } else {
5248 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5249 << CloseNesting << getOpenMPDirectiveName(OffendingRegion, OMPVersion)
5250 << Recommend << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5251 }
5252 return true;
5253 }
5254 return false;
5255}
5256
5262 ArrayRef<OMPClause *> Clauses,
5263 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5264 bool ErrorFound = false;
5265 unsigned NamedModifiersNumber = 0;
5266 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5267 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5268 SmallVector<SourceLocation, 4> NameModifierLoc;
5269 unsigned OMPVersion = S.getLangOpts().OpenMP;
5270 for (const OMPClause *C : Clauses) {
5271 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5272 // At most one if clause without a directive-name-modifier can appear on
5273 // the directive.
5274 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5275 auto &FNM = FoundNameModifiers[CurNM];
5276 if (FNM) {
5277 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5278 << getOpenMPDirectiveName(Kind, OMPVersion)
5279 << getOpenMPClauseNameForDiag(OMPC_if) << (CurNM != OMPD_unknown)
5280 << getOpenMPDirectiveName(CurNM, OMPVersion);
5281 ErrorFound = true;
5282 } else if (CurNM != OMPD_unknown) {
5283 NameModifierLoc.push_back(IC->getNameModifierLoc());
5284 ++NamedModifiersNumber;
5285 }
5286 FNM = IC;
5287 if (CurNM == OMPD_unknown)
5288 continue;
5289 // Check if the specified name modifier is allowed for the current
5290 // directive.
5291 // At most one if clause with the particular directive-name-modifier can
5292 // appear on the directive.
5293 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5294 S.Diag(IC->getNameModifierLoc(),
5295 diag::err_omp_wrong_if_directive_name_modifier)
5296 << getOpenMPDirectiveName(CurNM, OMPVersion)
5297 << getOpenMPDirectiveName(Kind, OMPVersion);
5298 ErrorFound = true;
5299 }
5300 }
5301 }
5302 // If any if clause on the directive includes a directive-name-modifier then
5303 // all if clauses on the directive must include a directive-name-modifier.
5304 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5305 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5306 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5307 diag::err_omp_no_more_if_clause);
5308 } else {
5309 std::string Values;
5310 std::string Sep(", ");
5311 unsigned AllowedCnt = 0;
5312 unsigned TotalAllowedNum =
5313 AllowedNameModifiers.size() - NamedModifiersNumber;
5314 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5315 ++Cnt) {
5316 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5317 if (!FoundNameModifiers[NM]) {
5318 Values += "'";
5319 Values += getOpenMPDirectiveName(NM, OMPVersion);
5320 Values += "'";
5321 if (AllowedCnt + 2 == TotalAllowedNum)
5322 Values += " or ";
5323 else if (AllowedCnt + 1 != TotalAllowedNum)
5324 Values += Sep;
5325 ++AllowedCnt;
5326 }
5327 }
5328 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5329 diag::err_omp_unnamed_if_clause)
5330 << (TotalAllowedNum > 1) << Values;
5331 }
5332 for (SourceLocation Loc : NameModifierLoc) {
5333 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5334 }
5335 ErrorFound = true;
5336 }
5337 return ErrorFound;
5338}
5339
5340static std::pair<ValueDecl *, bool>
5342 SourceRange &ERange, bool AllowArraySection,
5343 bool AllowAssumedSizeArray, StringRef DiagType) {
5344 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5346 return std::make_pair(nullptr, true);
5347
5348 // OpenMP [3.1, C/C++]
5349 // A list item is a variable name.
5350 // OpenMP [2.9.3.3, Restrictions, p.1]
5351 // A variable that is part of another variable (as an array or
5352 // structure element) cannot appear in a private clause.
5353 //
5354 // OpenMP [6.0]
5355 // 5.2.5 Array Sections, p. 166, L28-29
5356 // When the length is absent and the size of the dimension is not known,
5357 // the array section is an assumed-size array.
5358 // 2 Glossary, p. 23, L4-6
5359 // assumed-size array
5360 // For C/C++, an array section for which the length is absent and the
5361 // size of the dimensions is not known.
5362 // 5.2.5 Array Sections, p. 168, L11
5363 // An assumed-size array can appear only in clauses for which it is
5364 // explicitly allowed.
5365 // 7.4 List Item Privatization, Restrictions, p. 222, L15
5366 // Assumed-size arrays must not be privatized.
5367 RefExpr = RefExpr->IgnoreParens();
5368 enum {
5369 NoArrayExpr = -1,
5370 ArraySubscript = 0,
5371 OMPArraySection = 1
5372 } IsArrayExpr = NoArrayExpr;
5373 if (AllowArraySection) {
5374 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5375 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5376 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5377 Base = TempASE->getBase()->IgnoreParenImpCasts();
5378 RefExpr = Base;
5379 IsArrayExpr = ArraySubscript;
5380 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5381 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5382 if (S.getLangOpts().OpenMP >= 60 && !AllowAssumedSizeArray &&
5383 OASE->getColonLocFirst().isValid() && !OASE->getLength()) {
5385 if (BaseType.isNull() || (!BaseType->isConstantArrayType() &&
5386 !BaseType->isVariableArrayType())) {
5387 S.Diag(OASE->getColonLocFirst(),
5388 diag::err_omp_section_length_undefined)
5389 << (!BaseType.isNull() && BaseType->isArrayType());
5390 return std::make_pair(nullptr, false);
5391 }
5392 }
5393 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Base))
5394 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5395 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5396 Base = TempASE->getBase()->IgnoreParenImpCasts();
5397 RefExpr = Base;
5398 IsArrayExpr = OMPArraySection;
5399 }
5400 }
5401 ELoc = RefExpr->getExprLoc();
5402 ERange = RefExpr->getSourceRange();
5403 RefExpr = RefExpr->IgnoreParenImpCasts();
5404 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5405 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5406 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5407 (S.getCurrentThisType().isNull() || !ME ||
5408 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5409 !isa<FieldDecl>(ME->getMemberDecl()))) {
5410 if (IsArrayExpr != NoArrayExpr) {
5411 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5412 << IsArrayExpr << ERange;
5413 } else if (!DiagType.empty()) {
5414 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5415 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5416 : 0;
5417 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5418 << DiagSelect << DiagType << ERange;
5419 } else {
5420 S.Diag(ELoc,
5421 AllowArraySection
5422 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5423 : diag::err_omp_expected_var_name_member_expr)
5424 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5425 }
5426 return std::make_pair(nullptr, false);
5427 }
5428 return std::make_pair(
5429 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5430}
5431
5432namespace {
5433/// Checks if the allocator is used in uses_allocators clause to be allowed in
5434/// target regions.
5435class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5436 DSAStackTy *S = nullptr;
5437
5438public:
5439 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5440 return S->isUsesAllocatorsDecl(E->getDecl())
5441 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5442 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5443 }
5444 bool VisitStmt(const Stmt *S) {
5445 for (const Stmt *Child : S->children()) {
5446 if (Child && Visit(Child))
5447 return true;
5448 }
5449 return false;
5450 }
5451 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5452};
5453} // namespace
5454
5455static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5456 ArrayRef<OMPClause *> Clauses) {
5457 assert(!S.CurContext->isDependentContext() &&
5458 "Expected non-dependent context.");
5459 auto AllocateRange =
5460 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5461 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5462 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5463 return isOpenMPPrivate(C->getClauseKind());
5464 });
5465 for (OMPClause *Cl : PrivateRange) {
5467 if (Cl->getClauseKind() == OMPC_private) {
5468 auto *PC = cast<OMPPrivateClause>(Cl);
5469 I = PC->private_copies().begin();
5470 It = PC->varlist_begin();
5471 Et = PC->varlist_end();
5472 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5473 auto *PC = cast<OMPFirstprivateClause>(Cl);
5474 I = PC->private_copies().begin();
5475 It = PC->varlist_begin();
5476 Et = PC->varlist_end();
5477 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5478 auto *PC = cast<OMPLastprivateClause>(Cl);
5479 I = PC->private_copies().begin();
5480 It = PC->varlist_begin();
5481 Et = PC->varlist_end();
5482 } else if (Cl->getClauseKind() == OMPC_linear) {
5483 auto *PC = cast<OMPLinearClause>(Cl);
5484 I = PC->privates().begin();
5485 It = PC->varlist_begin();
5486 Et = PC->varlist_end();
5487 } else if (Cl->getClauseKind() == OMPC_reduction) {
5488 auto *PC = cast<OMPReductionClause>(Cl);
5489 I = PC->privates().begin();
5490 It = PC->varlist_begin();
5491 Et = PC->varlist_end();
5492 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5493 auto *PC = cast<OMPTaskReductionClause>(Cl);
5494 I = PC->privates().begin();
5495 It = PC->varlist_begin();
5496 Et = PC->varlist_end();
5497 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5498 auto *PC = cast<OMPInReductionClause>(Cl);
5499 I = PC->privates().begin();
5500 It = PC->varlist_begin();
5501 Et = PC->varlist_end();
5502 } else {
5503 llvm_unreachable("Expected private clause.");
5504 }
5505 for (Expr *E : llvm::make_range(It, Et)) {
5506 if (!*I) {
5507 ++I;
5508 continue;
5509 }
5510 SourceLocation ELoc;
5511 SourceRange ERange;
5512 Expr *SimpleRefExpr = E;
5513 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5514 /*AllowArraySection=*/true);
5515 DeclToCopy.try_emplace(Res.first,
5516 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5517 ++I;
5518 }
5519 }
5520 for (OMPClause *C : AllocateRange) {
5521 auto *AC = cast<OMPAllocateClause>(C);
5522 if (S.getLangOpts().OpenMP >= 50 &&
5523 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5524 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5525 AC->getAllocator()) {
5526 Expr *Allocator = AC->getAllocator();
5527 // OpenMP, 2.12.5 target Construct
5528 // Memory allocators that do not appear in a uses_allocators clause cannot
5529 // appear as an allocator in an allocate clause or be used in the target
5530 // region unless a requires directive with the dynamic_allocators clause
5531 // is present in the same compilation unit.
5532 AllocatorChecker Checker(Stack);
5533 if (Checker.Visit(Allocator))
5534 S.Diag(Allocator->getExprLoc(),
5535 diag::err_omp_allocator_not_in_uses_allocators)
5536 << Allocator->getSourceRange();
5537 }
5538 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5539 getAllocatorKind(S, Stack, AC->getAllocator());
5540 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5541 // For task, taskloop or target directives, allocation requests to memory
5542 // allocators with the trait access set to thread result in unspecified
5543 // behavior.
5544 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5545 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5546 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5547 unsigned OMPVersion = S.getLangOpts().OpenMP;
5548 S.Diag(AC->getAllocator()->getExprLoc(),
5549 diag::warn_omp_allocate_thread_on_task_target_directive)
5550 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
5551 }
5552 for (Expr *E : AC->varlist()) {
5553 SourceLocation ELoc;
5554 SourceRange ERange;
5555 Expr *SimpleRefExpr = E;
5556 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5557 ValueDecl *VD = Res.first;
5558 if (!VD)
5559 continue;
5560 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5561 if (!isOpenMPPrivate(Data.CKind)) {
5562 S.Diag(E->getExprLoc(),
5563 diag::err_omp_expected_private_copy_for_allocate);
5564 continue;
5565 }
5566 VarDecl *PrivateVD = DeclToCopy[VD];
5567 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5568 AllocatorKind, AC->getAllocator()))
5569 continue;
5570 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5571 AC->getAlignment(), E->getSourceRange());
5572 }
5573 }
5574}
5575
5576namespace {
5577/// Rewrite statements and expressions for Sema \p Actions CurContext.
5578///
5579/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5580/// context. DeclRefExpr used inside the new context are changed to refer to the
5581/// captured variable instead.
5582class CaptureVars : public TreeTransform<CaptureVars> {
5583 using BaseTransform = TreeTransform<CaptureVars>;
5584
5585public:
5586 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5587
5588 bool AlwaysRebuild() { return true; }
5589};
5590} // namespace
5591
5592static VarDecl *precomputeExpr(Sema &Actions,
5593 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5594 StringRef Name) {
5595 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5596 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5597 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5598 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5599 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5600 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5601 BodyStmts.push_back(NewDeclStmt);
5602 return NewVar;
5603}
5604
5605/// Create a closure that computes the number of iterations of a loop.
5606///
5607/// \param Actions The Sema object.
5608/// \param LogicalTy Type for the logical iteration number.
5609/// \param Rel Comparison operator of the loop condition.
5610/// \param StartExpr Value of the loop counter at the first iteration.
5611/// \param StopExpr Expression the loop counter is compared against in the loop
5612/// condition. \param StepExpr Amount of increment after each iteration.
5613///
5614/// \return Closure (CapturedStmt) of the distance calculation.
5615static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5617 Expr *StartExpr, Expr *StopExpr,
5618 Expr *StepExpr) {
5619 ASTContext &Ctx = Actions.getASTContext();
5620 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5621
5622 // Captured regions currently don't support return values, we use an
5623 // out-parameter instead. All inputs are implicit captures.
5624 // TODO: Instead of capturing each DeclRefExpr occurring in
5625 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5626 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5627 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5628 {StringRef(), QualType()}};
5629 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5630
5631 Stmt *Body;
5632 {
5633 Sema::CompoundScopeRAII CompoundScope(Actions);
5635
5636 // Get the LValue expression for the result.
5637 ImplicitParamDecl *DistParam = CS->getParam(0);
5638 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5639 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5640
5641 SmallVector<Stmt *, 4> BodyStmts;
5642
5643 // Capture all referenced variable references.
5644 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5645 // CapturedStmt, we could compute them before and capture the result, to be
5646 // used jointly with the LoopVar function.
5647 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5648 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5649 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5650 auto BuildVarRef = [&](VarDecl *VD) {
5651 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5652 };
5653
5655 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5657 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5658 Expr *Dist;
5659 if (Rel == BO_NE) {
5660 // When using a != comparison, the increment can be +1 or -1. This can be
5661 // dynamic at runtime, so we need to check for the direction.
5662 Expr *IsNegStep = AssertSuccess(
5663 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5664
5665 // Positive increment.
5666 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5667 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5668 ForwardRange = AssertSuccess(
5669 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5670 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5671 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5672
5673 // Negative increment.
5674 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5675 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5676 BackwardRange = AssertSuccess(
5677 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5678 Expr *NegIncAmount = AssertSuccess(
5679 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5680 Expr *BackwardDist = AssertSuccess(
5681 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5682
5683 // Use the appropriate case.
5684 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5685 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5686 } else {
5687 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5688 "Expected one of these relational operators");
5689
5690 // We can derive the direction from any other comparison operator. It is
5691 // non well-formed OpenMP if Step increments/decrements in the other
5692 // directions. Whether at least the first iteration passes the loop
5693 // condition.
5694 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5695 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5696
5697 // Compute the range between first and last counter value.
5698 Expr *Range;
5699 if (Rel == BO_GE || Rel == BO_GT)
5700 Range = AssertSuccess(Actions.BuildBinOp(
5701 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5702 else
5703 Range = AssertSuccess(Actions.BuildBinOp(
5704 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5705
5706 // Ensure unsigned range space.
5707 Range =
5708 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5709
5710 if (Rel == BO_LE || Rel == BO_GE) {
5711 // Add one to the range if the relational operator is inclusive.
5712 Range =
5713 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5714 }
5715
5716 // Divide by the absolute step amount. If the range is not a multiple of
5717 // the step size, rounding-up the effective upper bound ensures that the
5718 // last iteration is included.
5719 // Note that the rounding-up may cause an overflow in a temporary that
5720 // could be avoided, but would have occurred in a C-style for-loop as
5721 // well.
5722 Expr *Divisor = BuildVarRef(NewStep);
5723 if (Rel == BO_GE || Rel == BO_GT)
5724 Divisor =
5725 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5726 Expr *DivisorMinusOne =
5727 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5728 Expr *RangeRoundUp = AssertSuccess(
5729 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5730 Dist = AssertSuccess(
5731 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5732
5733 // If there is not at least one iteration, the range contains garbage. Fix
5734 // to zero in this case.
5735 Dist = AssertSuccess(
5736 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5737 }
5738
5739 // Assign the result to the out-parameter.
5740 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5741 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5742 BodyStmts.push_back(ResultAssign);
5743
5744 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5745 }
5746
5747 return cast<CapturedStmt>(
5748 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5749}
5750
5751/// Create a closure that computes the loop variable from the logical iteration
5752/// number.
5753///
5754/// \param Actions The Sema object.
5755/// \param LoopVarTy Type for the loop variable used for result value.
5756/// \param LogicalTy Type for the logical iteration number.
5757/// \param StartExpr Value of the loop counter at the first iteration.
5758/// \param Step Amount of increment after each iteration.
5759/// \param Deref Whether the loop variable is a dereference of the loop
5760/// counter variable.
5761///
5762/// \return Closure (CapturedStmt) of the loop value calculation.
5763static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5764 QualType LogicalTy,
5765 DeclRefExpr *StartExpr, Expr *Step,
5766 bool Deref) {
5767 ASTContext &Ctx = Actions.getASTContext();
5768
5769 // Pass the result as an out-parameter. Passing as return value would require
5770 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5771 // invoke a copy constructor.
5772 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5773 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5774 {"Logical", LogicalTy},
5775 {StringRef(), QualType()}};
5776 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5777
5778 // Capture the initial iterator which represents the LoopVar value at the
5779 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5780 // it in every iteration, capture it by value before it is modified.
5781 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5782 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5784 (void)Invalid;
5785 assert(!Invalid && "Expecting capture-by-value to work.");
5786
5787 Expr *Body;
5788 {
5789 Sema::CompoundScopeRAII CompoundScope(Actions);
5790 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5791
5792 ImplicitParamDecl *TargetParam = CS->getParam(0);
5793 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5794 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5795 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5796 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5797 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5798
5799 // Capture the Start expression.
5800 CaptureVars Recap(Actions);
5801 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5802 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5803
5805 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5806 // TODO: Explicitly cast to the iterator's difference_type instead of
5807 // relying on implicit conversion.
5808 Expr *Advanced =
5809 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5810
5811 if (Deref) {
5812 // For range-based for-loops convert the loop counter value to a concrete
5813 // loop variable value by dereferencing the iterator.
5814 Advanced =
5815 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5816 }
5817
5818 // Assign the result to the output parameter.
5819 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5820 BO_Assign, TargetRef, Advanced));
5821 }
5822 return cast<CapturedStmt>(
5823 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5824}
5825
5827 ASTContext &Ctx = getASTContext();
5828
5829 // Extract the common elements of ForStmt and CXXForRangeStmt:
5830 // Loop variable, repeat condition, increment
5831 Expr *Cond, *Inc;
5832 VarDecl *LIVDecl, *LUVDecl;
5833 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5834 Stmt *Init = For->getInit();
5835 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5836 // For statement declares loop variable.
5837 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5838 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5839 // For statement reuses variable.
5840 assert(LCAssign->getOpcode() == BO_Assign &&
5841 "init part must be a loop variable assignment");
5842 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5843 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5844 } else
5845 llvm_unreachable("Cannot determine loop variable");
5846 LUVDecl = LIVDecl;
5847
5848 Cond = For->getCond();
5849 Inc = For->getInc();
5850 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5851 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5852 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5853 LUVDecl = RangeFor->getLoopVariable();
5854
5855 Cond = RangeFor->getCond();
5856 Inc = RangeFor->getInc();
5857 } else
5858 llvm_unreachable("unhandled kind of loop");
5859
5860 QualType CounterTy = LIVDecl->getType();
5861 QualType LVTy = LUVDecl->getType();
5862
5863 // Analyze the loop condition.
5864 Expr *LHS, *RHS;
5865 BinaryOperator::Opcode CondRel;
5866 Cond = Cond->IgnoreImplicit();
5867 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5868 LHS = CondBinExpr->getLHS();
5869 RHS = CondBinExpr->getRHS();
5870 CondRel = CondBinExpr->getOpcode();
5871 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5872 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5873 LHS = CondCXXOp->getArg(0);
5874 RHS = CondCXXOp->getArg(1);
5875 switch (CondCXXOp->getOperator()) {
5876 case OO_ExclaimEqual:
5877 CondRel = BO_NE;
5878 break;
5879 case OO_Less:
5880 CondRel = BO_LT;
5881 break;
5882 case OO_LessEqual:
5883 CondRel = BO_LE;
5884 break;
5885 case OO_Greater:
5886 CondRel = BO_GT;
5887 break;
5888 case OO_GreaterEqual:
5889 CondRel = BO_GE;
5890 break;
5891 default:
5892 llvm_unreachable("unexpected iterator operator");
5893 }
5894 } else
5895 llvm_unreachable("unexpected loop condition");
5896
5897 // Normalize such that the loop counter is on the LHS.
5898 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5899 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5900 std::swap(LHS, RHS);
5901 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5902 }
5903 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5904
5905 // Decide the bit width for the logical iteration counter. By default use the
5906 // unsigned ptrdiff_t integer size (for iterators and pointers).
5907 // TODO: For iterators, use iterator::difference_type,
5908 // std::iterator_traits<>::difference_type or decltype(it - end).
5909 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5910 if (CounterTy->isIntegerType()) {
5911 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5912 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5913 }
5914
5915 // Analyze the loop increment.
5916 Expr *Step;
5917 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5918 int Direction;
5919 switch (IncUn->getOpcode()) {
5920 case UO_PreInc:
5921 case UO_PostInc:
5922 Direction = 1;
5923 break;
5924 case UO_PreDec:
5925 case UO_PostDec:
5926 Direction = -1;
5927 break;
5928 default:
5929 llvm_unreachable("unhandled unary increment operator");
5930 }
5932 Ctx,
5933 llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction, /*isSigned=*/true),
5934 LogicalTy, {});
5935 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5936 if (IncBin->getOpcode() == BO_AddAssign) {
5937 Step = IncBin->getRHS();
5938 } else if (IncBin->getOpcode() == BO_SubAssign) {
5939 Step = AssertSuccess(
5940 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5941 } else
5942 llvm_unreachable("unhandled binary increment operator");
5943 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5944 switch (CondCXXOp->getOperator()) {
5945 case OO_PlusPlus:
5947 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5948 break;
5949 case OO_MinusMinus:
5951 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5952 break;
5953 case OO_PlusEqual:
5954 Step = CondCXXOp->getArg(1);
5955 break;
5956 case OO_MinusEqual:
5957 Step = AssertSuccess(
5958 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5959 break;
5960 default:
5961 llvm_unreachable("unhandled overloaded increment operator");
5962 }
5963 } else
5964 llvm_unreachable("unknown increment expression");
5965
5966 CapturedStmt *DistanceFunc =
5967 buildDistanceFunc(SemaRef, LogicalTy, CondRel, LHS, RHS, Step);
5968 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5969 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5970 DeclRefExpr *LVRef =
5971 SemaRef.BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue, {},
5972 nullptr, nullptr, {}, nullptr);
5973 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
5974 LoopVarFunc, LVRef);
5975}
5976
5978 // Handle a literal loop.
5979 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5980 return ActOnOpenMPCanonicalLoop(AStmt);
5981
5982 // If not a literal loop, it must be the result of a loop transformation.
5984 assert(
5985 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
5986 "Loop transformation directive expected");
5987 return LoopTransform;
5988}
5989
5991 CXXScopeSpec &MapperIdScopeSpec,
5992 const DeclarationNameInfo &MapperId,
5993 QualType Type,
5994 Expr *UnresolvedMapper);
5995
5996/// Perform DFS through the structure/class data members trying to find
5997/// member(s) with user-defined 'default' mapper and generate implicit map
5998/// clauses for such members with the found 'default' mapper.
5999static void
6002 // Check for the default mapper for data members.
6003 if (S.getLangOpts().OpenMP < 50)
6004 return;
6005 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
6006 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
6007 if (!C)
6008 continue;
6009 SmallVector<Expr *, 4> SubExprs;
6010 auto *MI = C->mapperlist_begin();
6011 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
6012 ++I, ++MI) {
6013 // Expression is mapped using mapper - skip it.
6014 if (*MI)
6015 continue;
6016 Expr *E = *I;
6017 // Expression is dependent - skip it, build the mapper when it gets
6018 // instantiated.
6019 if (E->isTypeDependent() || E->isValueDependent() ||
6021 continue;
6022 // Array section - need to check for the mapping of the array section
6023 // element.
6024 QualType CanonType = E->getType().getCanonicalType();
6025 if (CanonType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
6026 const auto *OASE = cast<ArraySectionExpr>(E->IgnoreParenImpCasts());
6027 QualType BaseType =
6029 QualType ElemType;
6030 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6031 ElemType = ATy->getElementType();
6032 else
6033 ElemType = BaseType->getPointeeType();
6034 CanonType = ElemType;
6035 }
6036
6037 // DFS over data members in structures/classes.
6039 1, {CanonType, nullptr});
6040 llvm::DenseMap<const Type *, Expr *> Visited;
6042 1, {nullptr, 1});
6043 while (!Types.empty()) {
6044 QualType BaseType;
6045 FieldDecl *CurFD;
6046 std::tie(BaseType, CurFD) = Types.pop_back_val();
6047 while (ParentChain.back().second == 0)
6048 ParentChain.pop_back();
6049 --ParentChain.back().second;
6050 if (BaseType.isNull())
6051 continue;
6052 // Only structs/classes are allowed to have mappers.
6053 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6054 if (!RD)
6055 continue;
6056 auto It = Visited.find(BaseType.getTypePtr());
6057 if (It == Visited.end()) {
6058 // Try to find the associated user-defined mapper.
6059 CXXScopeSpec MapperIdScopeSpec;
6060 DeclarationNameInfo DefaultMapperId;
6062 &S.Context.Idents.get("default")));
6063 DefaultMapperId.setLoc(E->getExprLoc());
6065 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
6066 BaseType, /*UnresolvedMapper=*/nullptr);
6067 if (ER.isInvalid())
6068 continue;
6069 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
6070 }
6071 // Found default mapper.
6072 if (It->second) {
6073 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
6075 OE->setIsUnique(/*V=*/true);
6076 Expr *BaseExpr = OE;
6077 for (const auto &P : ParentChain) {
6078 if (P.first) {
6079 BaseExpr = S.BuildMemberExpr(
6080 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6082 DeclAccessPair::make(P.first, P.first->getAccess()),
6083 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6084 P.first->getType(), VK_LValue, OK_Ordinary);
6085 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
6086 }
6087 }
6088 if (CurFD)
6089 BaseExpr = S.BuildMemberExpr(
6090 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6092 DeclAccessPair::make(CurFD, CurFD->getAccess()),
6093 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6094 CurFD->getType(), VK_LValue, OK_Ordinary);
6095 SubExprs.push_back(BaseExpr);
6096 continue;
6097 }
6098 // Check for the "default" mapper for data members.
6099 bool FirstIter = true;
6100 for (FieldDecl *FD : RD->fields()) {
6101 if (!FD)
6102 continue;
6103 QualType FieldTy = FD->getType();
6104 if (FieldTy.isNull() ||
6105 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6106 continue;
6107 if (FirstIter) {
6108 FirstIter = false;
6109 ParentChain.emplace_back(CurFD, 1);
6110 } else {
6111 ++ParentChain.back().second;
6112 }
6113 Types.emplace_back(FieldTy, FD);
6114 }
6115 }
6116 }
6117 if (SubExprs.empty())
6118 continue;
6119 CXXScopeSpec MapperIdScopeSpec;
6120 DeclarationNameInfo MapperId;
6121 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
6122 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
6123 MapperIdScopeSpec, MapperId, C->getMapType(),
6124 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6125 SubExprs, OMPVarListLocTy()))
6126 Clauses.push_back(NewClause);
6127 }
6128}
6129
6130namespace {
6131/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
6132/// call in the associated loop-nest cannot be a 'parallel for'.
6133class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
6134 Sema &SemaRef;
6135
6136public:
6137 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
6138
6139 // Is there a nested OpenMP loop bind(parallel)
6140 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
6141 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
6142 if (const auto *C = D->getSingleClause<OMPBindClause>())
6143 if (C->getBindKind() == OMPC_BIND_parallel) {
6144 TeamsLoopCanBeParallelFor = false;
6145 // No need to continue visiting any more
6146 return;
6147 }
6148 }
6149 for (const Stmt *Child : D->children())
6150 if (Child)
6151 Visit(Child);
6152 }
6153
6154 void VisitCallExpr(const CallExpr *C) {
6155 // Function calls inhibit parallel loop translation of 'target teams loop'
6156 // unless the assume-no-nested-parallelism flag has been specified.
6157 // OpenMP API runtime library calls do not inhibit parallel loop
6158 // translation, regardless of the assume-no-nested-parallelism.
6159 bool IsOpenMPAPI = false;
6160 auto *FD = dyn_cast_or_null<FunctionDecl>(C->getCalleeDecl());
6161 if (FD) {
6162 std::string Name = FD->getNameInfo().getAsString();
6163 IsOpenMPAPI = Name.find("omp_") == 0;
6164 }
6165 TeamsLoopCanBeParallelFor =
6166 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
6167 if (!TeamsLoopCanBeParallelFor)
6168 return;
6169
6170 for (const Stmt *Child : C->children())
6171 if (Child)
6172 Visit(Child);
6173 }
6174
6175 void VisitCapturedStmt(const CapturedStmt *S) {
6176 if (!S)
6177 return;
6178 Visit(S->getCapturedDecl()->getBody());
6179 }
6180
6181 void VisitStmt(const Stmt *S) {
6182 if (!S)
6183 return;
6184 for (const Stmt *Child : S->children())
6185 if (Child)
6186 Visit(Child);
6187 }
6188 explicit TeamsLoopChecker(Sema &SemaRef)
6189 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
6190
6191private:
6192 bool TeamsLoopCanBeParallelFor;
6193};
6194} // namespace
6195
6196static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
6197 TeamsLoopChecker Checker(SemaRef);
6198 Checker.Visit(AStmt);
6199 return Checker.teamsLoopCanBeParallelFor();
6200}
6201
6203 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6204 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6205 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
6206 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
6207
6208 StmtResult Res = StmtError();
6210 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6211
6212 if (const OMPBindClause *BC =
6213 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6214 BindKind = BC->getBindKind();
6215
6216 if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
6217 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
6218
6219 // Setting the enclosing teams or parallel construct for the loop
6220 // directive without bind clause.
6221 // [5.0:129:25-28] If the bind clause is not present on the construct and
6222 // the loop construct is closely nested inside a teams or parallel
6223 // construct, the binding region is the corresponding teams or parallel
6224 // region. If none of those conditions hold, the binding region is not
6225 // defined.
6226 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6227 ArrayRef<OpenMPDirectiveKind> ParentLeafs =
6228 getLeafConstructsOrSelf(ParentDirective);
6229
6230 if (ParentDirective == OMPD_unknown) {
6231 Diag(DSAStack->getDefaultDSALocation(),
6232 diag::err_omp_bind_required_on_loop);
6233 } else if (ParentLeafs.back() == OMPD_parallel) {
6234 BindKind = OMPC_BIND_parallel;
6235 } else if (ParentLeafs.back() == OMPD_teams) {
6236 BindKind = OMPC_BIND_teams;
6237 }
6238
6239 assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind");
6240
6241 OMPClause *C =
6244 ClausesWithImplicit.push_back(C);
6245 }
6246
6247 // Diagnose "loop bind(teams)" with "reduction".
6248 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6249 for (OMPClause *C : Clauses) {
6250 if (C->getClauseKind() == OMPC_reduction)
6251 Diag(DSAStack->getDefaultDSALocation(),
6252 diag::err_omp_loop_reduction_clause);
6253 }
6254 }
6255
6256 // First check CancelRegion which is then used in checkNestingOfRegions.
6257 if (checkCancelRegion(SemaRef, Kind, CancelRegion, StartLoc) ||
6258 checkNestingOfRegions(SemaRef, DSAStack, Kind, DirName, CancelRegion,
6259 BindKind, StartLoc)) {
6260 return StmtError();
6261 }
6262
6263 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6266 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6267
6268 VarsWithInheritedDSAType VarsWithInheritedDSA;
6269 bool ErrorFound = false;
6270 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6271
6272 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6274 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6275
6276 // Check default data sharing attributes for referenced variables.
6277 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(AStmt));
6278 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6279 Stmt *S = AStmt;
6280 while (--ThisCaptureLevel >= 0)
6281 S = cast<CapturedStmt>(S)->getCapturedStmt();
6282 DSAChecker.Visit(S);
6284 !isOpenMPTaskingDirective(Kind)) {
6285 // Visit subcaptures to generate implicit clauses for captured vars.
6286 auto *CS = cast<CapturedStmt>(AStmt);
6288 getOpenMPCaptureRegions(CaptureRegions, Kind);
6289 // Ignore outer tasking regions for target directives.
6290 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6292 DSAChecker.visitSubCaptures(CS);
6293 }
6294 if (DSAChecker.isErrorFound())
6295 return StmtError();
6296 // Generate list of implicitly defined firstprivate variables.
6297 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6298 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6299
6301 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6302 // Get the original location of present modifier from Defaultmap clause.
6303 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6304 for (OMPClause *C : Clauses) {
6305 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6306 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6307 PresentModifierLocs[DMC->getDefaultmapKind()] =
6308 DMC->getDefaultmapModifierLoc();
6309 }
6310
6312 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6314 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[K]),
6315 ImpInfo.MapModifiers[K].size(), PresentModifierLocs[K]);
6316 }
6317 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6318 for (OMPClause *C : Clauses) {
6319 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6320 for (Expr *E : IRC->taskgroup_descriptors())
6321 if (E)
6322 ImpInfo.Firstprivates.insert(E);
6323 }
6324 // OpenMP 5.0, 2.10.1 task Construct
6325 // [detach clause]... The event-handle will be considered as if it was
6326 // specified on a firstprivate clause.
6327 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6328 ImpInfo.Firstprivates.insert(DC->getEventHandler());
6329 }
6330 if (!ImpInfo.Firstprivates.empty()) {
6332 ImpInfo.Firstprivates.getArrayRef(), SourceLocation(),
6334 ClausesWithImplicit.push_back(Implicit);
6335 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6336 ImpInfo.Firstprivates.size();
6337 } else {
6338 ErrorFound = true;
6339 }
6340 }
6341 if (!ImpInfo.Privates.empty()) {
6343 ImpInfo.Privates.getArrayRef(), SourceLocation(),
6345 ClausesWithImplicit.push_back(Implicit);
6346 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6347 ImpInfo.Privates.size();
6348 } else {
6349 ErrorFound = true;
6350 }
6351 }
6352 // OpenMP 5.0 [2.19.7]
6353 // If a list item appears in a reduction, lastprivate or linear
6354 // clause on a combined target construct then it is treated as
6355 // if it also appears in a map clause with a map-type of tofrom
6356 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6358 SmallVector<Expr *, 4> ImplicitExprs;
6359 for (OMPClause *C : Clauses) {
6360 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6361 for (Expr *E : RC->varlist())
6363 ImplicitExprs.emplace_back(E);
6364 }
6365 if (!ImplicitExprs.empty()) {
6366 ArrayRef<Expr *> Exprs = ImplicitExprs;
6367 CXXScopeSpec MapperIdScopeSpec;
6368 DeclarationNameInfo MapperId;
6371 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6372 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6373 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6374 ClausesWithImplicit.emplace_back(Implicit);
6375 }
6376 }
6377 for (unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6378 int ClauseKindCnt = -1;
6379 for (unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6380 ArrayRef<Expr *> ImplicitMap = ImpInfo.Mappings[I][J].getArrayRef();
6381 ++ClauseKindCnt;
6382 if (ImplicitMap.empty())
6383 continue;
6384 CXXScopeSpec MapperIdScopeSpec;
6385 DeclarationNameInfo MapperId;
6386 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6388 nullptr, ImpInfo.MapModifiers[I], ImplicitMapModifiersLoc[I],
6389 MapperIdScopeSpec, MapperId, K, /*IsMapTypeImplicit=*/true,
6390 SourceLocation(), SourceLocation(), ImplicitMap,
6391 OMPVarListLocTy())) {
6392 ClausesWithImplicit.emplace_back(Implicit);
6393 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6394 ImplicitMap.size();
6395 } else {
6396 ErrorFound = true;
6397 }
6398 }
6399 }
6400 // Build expressions for implicit maps of data members with 'default'
6401 // mappers.
6402 if (getLangOpts().OpenMP >= 50)
6404 ClausesWithImplicit);
6405 }
6406
6407 switch (Kind) {
6408 case OMPD_parallel:
6409 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6410 EndLoc);
6411 break;
6412 case OMPD_simd:
6413 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6414 VarsWithInheritedDSA);
6415 break;
6416 case OMPD_tile:
6417 Res =
6418 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6419 break;
6420 case OMPD_stripe:
6421 Res = ActOnOpenMPStripeDirective(ClausesWithImplicit, AStmt, StartLoc,
6422 EndLoc);
6423 break;
6424 case OMPD_unroll:
6425 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6426 EndLoc);
6427 break;
6428 case OMPD_reverse:
6429 assert(ClausesWithImplicit.empty() &&
6430 "reverse directive does not support any clauses");
6431 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6432 break;
6433 case OMPD_interchange:
6434 Res = ActOnOpenMPInterchangeDirective(ClausesWithImplicit, AStmt, StartLoc,
6435 EndLoc);
6436 break;
6437 case OMPD_fuse:
6438 Res =
6439 ActOnOpenMPFuseDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6440 break;
6441 case OMPD_for:
6442 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6443 VarsWithInheritedDSA);
6444 break;
6445 case OMPD_for_simd:
6446 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6447 EndLoc, VarsWithInheritedDSA);
6448 break;
6449 case OMPD_sections:
6450 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6451 EndLoc);
6452 break;
6453 case OMPD_section:
6454 assert(ClausesWithImplicit.empty() &&
6455 "No clauses are allowed for 'omp section' directive");
6456 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6457 break;
6458 case OMPD_single:
6459 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6460 EndLoc);
6461 break;
6462 case OMPD_master:
6463 assert(ClausesWithImplicit.empty() &&
6464 "No clauses are allowed for 'omp master' directive");
6465 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6466 break;
6467 case OMPD_masked:
6468 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6469 EndLoc);
6470 break;
6471 case OMPD_critical:
6472 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6473 StartLoc, EndLoc);
6474 break;
6475 case OMPD_parallel_for:
6476 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6477 EndLoc, VarsWithInheritedDSA);
6478 break;
6479 case OMPD_parallel_for_simd:
6481 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6482 break;
6483 case OMPD_scope:
6484 Res =
6485 ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6486 break;
6487 case OMPD_parallel_master:
6488 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6489 StartLoc, EndLoc);
6490 break;
6491 case OMPD_parallel_masked:
6492 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6493 StartLoc, EndLoc);
6494 break;
6495 case OMPD_parallel_sections:
6496 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6497 StartLoc, EndLoc);
6498 break;
6499 case OMPD_task:
6500 Res =
6501 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6502 break;
6503 case OMPD_taskyield:
6504 assert(ClausesWithImplicit.empty() &&
6505 "No clauses are allowed for 'omp taskyield' directive");
6506 assert(AStmt == nullptr &&
6507 "No associated statement allowed for 'omp taskyield' directive");
6508 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6509 break;
6510 case OMPD_error:
6511 assert(AStmt == nullptr &&
6512 "No associated statement allowed for 'omp error' directive");
6513 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6514 break;
6515 case OMPD_barrier:
6516 assert(ClausesWithImplicit.empty() &&
6517 "No clauses are allowed for 'omp barrier' directive");
6518 assert(AStmt == nullptr &&
6519 "No associated statement allowed for 'omp barrier' directive");
6520 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6521 break;
6522 case OMPD_taskwait:
6523 assert(AStmt == nullptr &&
6524 "No associated statement allowed for 'omp taskwait' directive");
6525 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6526 break;
6527 case OMPD_taskgroup:
6528 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6529 EndLoc);
6530 break;
6531 case OMPD_flush:
6532 assert(AStmt == nullptr &&
6533 "No associated statement allowed for 'omp flush' directive");
6534 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6535 break;
6536 case OMPD_depobj:
6537 assert(AStmt == nullptr &&
6538 "No associated statement allowed for 'omp depobj' directive");
6539 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6540 break;
6541 case OMPD_scan:
6542 assert(AStmt == nullptr &&
6543 "No associated statement allowed for 'omp scan' directive");
6544 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6545 break;
6546 case OMPD_ordered:
6547 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6548 EndLoc);
6549 break;
6550 case OMPD_atomic:
6551 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6552 EndLoc);
6553 break;
6554 case OMPD_teams:
6555 Res =
6556 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6557 break;
6558 case OMPD_target:
6559 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6560 EndLoc);
6561 break;
6562 case OMPD_target_parallel:
6563 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6564 StartLoc, EndLoc);
6565 break;
6566 case OMPD_target_parallel_for:
6568 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6569 break;
6570 case OMPD_cancellation_point:
6571 assert(ClausesWithImplicit.empty() &&
6572 "No clauses are allowed for 'omp cancellation point' directive");
6573 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6574 "cancellation point' directive");
6575 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6576 break;
6577 case OMPD_cancel:
6578 assert(AStmt == nullptr &&
6579 "No associated statement allowed for 'omp cancel' directive");
6580 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6581 CancelRegion);
6582 break;
6583 case OMPD_target_data:
6584 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6585 EndLoc);
6586 break;
6587 case OMPD_target_enter_data:
6588 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6589 EndLoc, AStmt);
6590 break;
6591 case OMPD_target_exit_data:
6592 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6593 EndLoc, AStmt);
6594 break;
6595 case OMPD_taskloop:
6596 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6597 EndLoc, VarsWithInheritedDSA);
6598 break;
6599 case OMPD_taskloop_simd:
6600 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6601 EndLoc, VarsWithInheritedDSA);
6602 break;
6603 case OMPD_master_taskloop:
6605 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6606 break;
6607 case OMPD_masked_taskloop:
6609 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6610 break;
6611 case OMPD_master_taskloop_simd:
6613 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6614 break;
6615 case OMPD_masked_taskloop_simd:
6617 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6618 break;
6619 case OMPD_parallel_master_taskloop:
6621 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6622 break;
6623 case OMPD_parallel_masked_taskloop:
6625 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6626 break;
6627 case OMPD_parallel_master_taskloop_simd:
6629 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6630 break;
6631 case OMPD_parallel_masked_taskloop_simd:
6633 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6634 break;
6635 case OMPD_distribute:
6636 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6637 EndLoc, VarsWithInheritedDSA);
6638 break;
6639 case OMPD_target_update:
6640 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6641 EndLoc, AStmt);
6642 break;
6643 case OMPD_distribute_parallel_for:
6645 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6646 break;
6647 case OMPD_distribute_parallel_for_simd:
6649 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6650 break;
6651 case OMPD_distribute_simd:
6653 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6654 break;
6655 case OMPD_target_parallel_for_simd:
6657 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6658 break;
6659 case OMPD_target_simd:
6660 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6661 EndLoc, VarsWithInheritedDSA);
6662 break;
6663 case OMPD_teams_distribute:
6665 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6666 break;
6667 case OMPD_teams_distribute_simd:
6669 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6670 break;
6671 case OMPD_teams_distribute_parallel_for_simd:
6673 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6674 break;
6675 case OMPD_teams_distribute_parallel_for:
6677 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6678 break;
6679 case OMPD_target_teams:
6680 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6681 EndLoc);
6682 break;
6683 case OMPD_target_teams_distribute:
6685 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6686 break;
6687 case OMPD_target_teams_distribute_parallel_for:
6689 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6690 break;
6691 case OMPD_target_teams_distribute_parallel_for_simd:
6693 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6694 break;
6695 case OMPD_target_teams_distribute_simd:
6697 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6698 break;
6699 case OMPD_interop:
6700 assert(AStmt == nullptr &&
6701 "No associated statement allowed for 'omp interop' directive");
6702 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6703 break;
6704 case OMPD_dispatch:
6705 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6706 EndLoc);
6707 break;
6708 case OMPD_loop:
6709 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6710 EndLoc, VarsWithInheritedDSA);
6711 break;
6712 case OMPD_teams_loop:
6714 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6715 break;
6716 case OMPD_target_teams_loop:
6718 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6719 break;
6720 case OMPD_parallel_loop:
6722 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6723 break;
6724 case OMPD_target_parallel_loop:
6726 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6727 break;
6728 case OMPD_declare_target:
6729 case OMPD_end_declare_target:
6730 case OMPD_threadprivate:
6731 case OMPD_allocate:
6732 case OMPD_declare_reduction:
6733 case OMPD_declare_mapper:
6734 case OMPD_declare_simd:
6735 case OMPD_requires:
6736 case OMPD_declare_variant:
6737 case OMPD_begin_declare_variant:
6738 case OMPD_end_declare_variant:
6739 llvm_unreachable("OpenMP Directive is not allowed");
6740 case OMPD_unknown:
6741 default:
6742 llvm_unreachable("Unknown OpenMP directive");
6743 }
6744
6745 ErrorFound = Res.isInvalid() || ErrorFound;
6746
6747 // Check variables in the clauses if default(none) or
6748 // default(firstprivate) was specified.
6749 if (DSAStack->getDefaultDSA() == DSA_none ||
6750 DSAStack->getDefaultDSA() == DSA_private ||
6751 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6752 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6753 for (OMPClause *C : Clauses) {
6754 switch (C->getClauseKind()) {
6755 case OMPC_num_threads:
6756 case OMPC_dist_schedule:
6757 // Do not analyze if no parent teams directive.
6758 if (isOpenMPTeamsDirective(Kind))
6759 break;
6760 continue;
6761 case OMPC_if:
6762 if (isOpenMPTeamsDirective(Kind) &&
6763 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6764 break;
6765 if (isOpenMPParallelDirective(Kind) &&
6767 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6768 break;
6769 continue;
6770 case OMPC_schedule:
6771 case OMPC_detach:
6772 break;
6773 case OMPC_grainsize:
6774 case OMPC_num_tasks:
6775 case OMPC_final:
6776 case OMPC_priority:
6777 case OMPC_novariants:
6778 case OMPC_nocontext:
6779 // Do not analyze if no parent parallel directive.
6780 if (isOpenMPParallelDirective(Kind))
6781 break;
6782 continue;
6783 case OMPC_ordered:
6784 case OMPC_device:
6785 case OMPC_num_teams:
6786 case OMPC_thread_limit:
6787 case OMPC_hint:
6788 case OMPC_collapse:
6789 case OMPC_safelen:
6790 case OMPC_simdlen:
6791 case OMPC_sizes:
6792 case OMPC_default:
6793 case OMPC_proc_bind:
6794 case OMPC_private:
6795 case OMPC_firstprivate:
6796 case OMPC_lastprivate:
6797 case OMPC_shared:
6798 case OMPC_reduction:
6799 case OMPC_task_reduction:
6800 case OMPC_in_reduction:
6801 case OMPC_linear:
6802 case OMPC_aligned:
6803 case OMPC_copyin:
6804 case OMPC_copyprivate:
6805 case OMPC_nowait:
6806 case OMPC_untied:
6807 case OMPC_mergeable:
6808 case OMPC_allocate:
6809 case OMPC_read:
6810 case OMPC_write:
6811 case OMPC_update:
6812 case OMPC_capture:
6813 case OMPC_compare:
6814 case OMPC_seq_cst:
6815 case OMPC_acq_rel:
6816 case OMPC_acquire:
6817 case OMPC_release:
6818 case OMPC_relaxed:
6819 case OMPC_depend:
6820 case OMPC_threads:
6821 case OMPC_simd:
6822 case OMPC_map:
6823 case OMPC_nogroup:
6824 case OMPC_defaultmap:
6825 case OMPC_to:
6826 case OMPC_from:
6827 case OMPC_use_device_ptr:
6828 case OMPC_use_device_addr:
6829 case OMPC_is_device_ptr:
6830 case OMPC_has_device_addr:
6831 case OMPC_nontemporal:
6832 case OMPC_order:
6833 case OMPC_destroy:
6834 case OMPC_inclusive:
6835 case OMPC_exclusive:
6836 case OMPC_uses_allocators:
6837 case OMPC_affinity:
6838 case OMPC_bind:
6839 case OMPC_filter:
6840 case OMPC_severity:
6841 case OMPC_message:
6842 continue;
6843 case OMPC_allocator:
6844 case OMPC_flush:
6845 case OMPC_depobj:
6846 case OMPC_threadprivate:
6847 case OMPC_groupprivate:
6848 case OMPC_uniform:
6849 case OMPC_unknown:
6850 case OMPC_unified_address:
6851 case OMPC_unified_shared_memory:
6852 case OMPC_reverse_offload:
6853 case OMPC_dynamic_allocators:
6854 case OMPC_atomic_default_mem_order:
6855 case OMPC_self_maps:
6856 case OMPC_device_type:
6857 case OMPC_match:
6858 case OMPC_when:
6859 case OMPC_at:
6860 default:
6861 llvm_unreachable("Unexpected clause");
6862 }
6863 for (Stmt *CC : C->children()) {
6864 if (CC)
6865 DSAChecker.Visit(CC);
6866 }
6867 }
6868 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6869 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6870 }
6871 for (const auto &P : VarsWithInheritedDSA) {
6872 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6873 continue;
6874 ErrorFound = true;
6875 if (DSAStack->getDefaultDSA() == DSA_none ||
6876 DSAStack->getDefaultDSA() == DSA_private ||
6877 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6878 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6879 << P.first << P.second->getSourceRange();
6880 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6881 } else if (getLangOpts().OpenMP >= 50) {
6882 Diag(P.second->getExprLoc(),
6883 diag::err_omp_defaultmap_no_attr_for_variable)
6884 << P.first << P.second->getSourceRange();
6885 Diag(DSAStack->getDefaultDSALocation(),
6886 diag::note_omp_defaultmap_attr_none);
6887 }
6888 }
6889
6890 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6891 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(Kind)) {
6892 if (isAllowedClauseForDirective(D, OMPC_if, getLangOpts().OpenMP))
6893 AllowedNameModifiers.push_back(D);
6894 }
6895 if (!AllowedNameModifiers.empty())
6896 ErrorFound = checkIfClauses(SemaRef, Kind, Clauses, AllowedNameModifiers) ||
6897 ErrorFound;
6898
6899 if (ErrorFound)
6900 return StmtError();
6901
6902 if (!SemaRef.CurContext->isDependentContext() &&
6904 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6905 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6906 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6907 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6908 // Register target to DSA Stack.
6909 DSAStack->addTargetDirLocation(StartLoc);
6910 }
6911
6912 return Res;
6913}
6914
6916 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6917 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6918 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6919 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6920 assert(Aligneds.size() == Alignments.size());
6921 assert(Linears.size() == LinModifiers.size());
6922 assert(Linears.size() == Steps.size());
6923 if (!DG || DG.get().isNull())
6924 return DeclGroupPtrTy();
6925
6926 const int SimdId = 0;
6927 if (!DG.get().isSingleDecl()) {
6928 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6929 << SimdId;
6930 return DG;
6931 }
6932 Decl *ADecl = DG.get().getSingleDecl();
6933 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6934 ADecl = FTD->getTemplatedDecl();
6935
6936 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6937 if (!FD) {
6938 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6939 return DeclGroupPtrTy();
6940 }
6941
6942 // OpenMP [2.8.2, declare simd construct, Description]
6943 // The parameter of the simdlen clause must be a constant positive integer
6944 // expression.
6945 ExprResult SL;
6946 if (Simdlen)
6947 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6948 // OpenMP [2.8.2, declare simd construct, Description]
6949 // The special this pointer can be used as if was one of the arguments to the
6950 // function in any of the linear, aligned, or uniform clauses.
6951 // The uniform clause declares one or more arguments to have an invariant
6952 // value for all concurrent invocations of the function in the execution of a
6953 // single SIMD loop.
6954 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6955 const Expr *UniformedLinearThis = nullptr;
6956 for (const Expr *E : Uniforms) {
6957 E = E->IgnoreParenImpCasts();
6958 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6959 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6960 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6961 FD->getParamDecl(PVD->getFunctionScopeIndex())
6962 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
6963 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6964 continue;
6965 }
6966 if (isa<CXXThisExpr>(E)) {
6967 UniformedLinearThis = E;
6968 continue;
6969 }
6970 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6971 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6972 }
6973 // OpenMP [2.8.2, declare simd construct, Description]
6974 // The aligned clause declares that the object to which each list item points
6975 // is aligned to the number of bytes expressed in the optional parameter of
6976 // the aligned clause.
6977 // The special this pointer can be used as if was one of the arguments to the
6978 // function in any of the linear, aligned, or uniform clauses.
6979 // The type of list items appearing in the aligned clause must be array,
6980 // pointer, reference to array, or reference to pointer.
6981 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6982 const Expr *AlignedThis = nullptr;
6983 for (const Expr *E : Aligneds) {
6984 E = E->IgnoreParenImpCasts();
6985 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6986 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6987 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6988 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6989 FD->getParamDecl(PVD->getFunctionScopeIndex())
6990 ->getCanonicalDecl() == CanonPVD) {
6991 // OpenMP [2.8.1, simd construct, Restrictions]
6992 // A list-item cannot appear in more than one aligned clause.
6993 auto [It, Inserted] = AlignedArgs.try_emplace(CanonPVD, E);
6994 if (!Inserted) {
6995 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6996 << 1 << getOpenMPClauseNameForDiag(OMPC_aligned)
6997 << E->getSourceRange();
6998 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
6999 << getOpenMPClauseNameForDiag(OMPC_aligned);
7000 continue;
7001 }
7002 QualType QTy = PVD->getType()
7003 .getNonReferenceType()
7004 .getUnqualifiedType()
7005 .getCanonicalType();
7006 const Type *Ty = QTy.getTypePtrOrNull();
7007 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
7008 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
7009 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
7010 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
7011 }
7012 continue;
7013 }
7014 }
7015 if (isa<CXXThisExpr>(E)) {
7016 if (AlignedThis) {
7017 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
7018 << 2 << getOpenMPClauseNameForDiag(OMPC_aligned)
7019 << E->getSourceRange();
7020 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
7021 << getOpenMPClauseNameForDiag(OMPC_aligned);
7022 }
7023 AlignedThis = E;
7024 continue;
7025 }
7026 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7027 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7028 }
7029 // The optional parameter of the aligned clause, alignment, must be a constant
7030 // positive integer expression. If no optional parameter is specified,
7031 // implementation-defined default alignments for SIMD instructions on the
7032 // target platforms are assumed.
7034 for (Expr *E : Alignments) {
7035 ExprResult Align;
7036 if (E)
7037 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
7038 NewAligns.push_back(Align.get());
7039 }
7040 // OpenMP [2.8.2, declare simd construct, Description]
7041 // The linear clause declares one or more list items to be private to a SIMD
7042 // lane and to have a linear relationship with respect to the iteration space
7043 // of a loop.
7044 // The special this pointer can be used as if was one of the arguments to the
7045 // function in any of the linear, aligned, or uniform clauses.
7046 // When a linear-step expression is specified in a linear clause it must be
7047 // either a constant integer expression or an integer-typed parameter that is
7048 // specified in a uniform clause on the directive.
7049 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7050 const bool IsUniformedThis = UniformedLinearThis != nullptr;
7051 auto MI = LinModifiers.begin();
7052 for (const Expr *E : Linears) {
7053 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
7054 ++MI;
7055 E = E->IgnoreParenImpCasts();
7056 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7057 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7058 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7059 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7060 FD->getParamDecl(PVD->getFunctionScopeIndex())
7061 ->getCanonicalDecl() == CanonPVD) {
7062 // OpenMP [2.15.3.7, linear Clause, Restrictions]
7063 // A list-item cannot appear in more than one linear clause.
7064 if (auto It = LinearArgs.find(CanonPVD); It != LinearArgs.end()) {
7065 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7066 << getOpenMPClauseNameForDiag(OMPC_linear)
7067 << getOpenMPClauseNameForDiag(OMPC_linear)
7068 << E->getSourceRange();
7069 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7070 << getOpenMPClauseNameForDiag(OMPC_linear);
7071 continue;
7072 }
7073 // Each argument can appear in at most one uniform or linear clause.
7074 if (auto It = UniformedArgs.find(CanonPVD);
7075 It != UniformedArgs.end()) {
7076 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7077 << getOpenMPClauseNameForDiag(OMPC_linear)
7078 << getOpenMPClauseNameForDiag(OMPC_uniform)
7079 << E->getSourceRange();
7080 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7081 << getOpenMPClauseNameForDiag(OMPC_uniform);
7082 continue;
7083 }
7084 LinearArgs[CanonPVD] = E;
7085 if (E->isValueDependent() || E->isTypeDependent() ||
7088 continue;
7089 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
7090 PVD->getOriginalType(),
7091 /*IsDeclareSimd=*/true);
7092 continue;
7093 }
7094 }
7095 if (isa<CXXThisExpr>(E)) {
7096 if (UniformedLinearThis) {
7097 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7098 << getOpenMPClauseNameForDiag(OMPC_linear)
7099 << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
7100 : OMPC_linear)
7101 << E->getSourceRange();
7102 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
7103 << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
7104 : OMPC_linear);
7105 continue;
7106 }
7107 UniformedLinearThis = E;
7108 if (E->isValueDependent() || E->isTypeDependent() ||
7110 continue;
7111 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
7112 E->getType(), /*IsDeclareSimd=*/true);
7113 continue;
7114 }
7115 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7116 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7117 }
7118 Expr *Step = nullptr;
7119 Expr *NewStep = nullptr;
7120 SmallVector<Expr *, 4> NewSteps;
7121 for (Expr *E : Steps) {
7122 // Skip the same step expression, it was checked already.
7123 if (Step == E || !E) {
7124 NewSteps.push_back(E ? NewStep : nullptr);
7125 continue;
7126 }
7127 Step = E;
7128 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
7129 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7130 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7131 if (UniformedArgs.count(CanonPVD) == 0) {
7132 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
7133 << Step->getSourceRange();
7134 } else if (E->isValueDependent() || E->isTypeDependent() ||
7137 CanonPVD->getType()->hasIntegerRepresentation()) {
7138 NewSteps.push_back(Step);
7139 } else {
7140 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
7141 << Step->getSourceRange();
7142 }
7143 continue;
7144 }
7145 NewStep = Step;
7146 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
7147 !Step->isInstantiationDependent() &&
7149 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
7150 .get();
7151 if (NewStep)
7152 NewStep = SemaRef
7153 .VerifyIntegerConstantExpression(
7154 NewStep, /*FIXME*/ AllowFoldKind::Allow)
7155 .get();
7156 }
7157 NewSteps.push_back(NewStep);
7158 }
7159 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7160 getASTContext(), BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
7161 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
7162 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
7163 const_cast<Expr **>(Linears.data()), Linears.size(),
7164 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
7165 NewSteps.data(), NewSteps.size(), SR);
7166 ADecl->addAttr(NewAttr);
7167 return DG;
7168}
7169
7171 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
7172 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
7173 SourceLocation EndLoc) {
7174 assert(isOpenMPInformationalDirective(Kind) &&
7175 "Unexpected directive category");
7176
7177 StmtResult Res = StmtError();
7178
7179 switch (Kind) {
7180 case OMPD_assume:
7181 Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc);
7182 break;
7183 default:
7184 llvm_unreachable("Unknown OpenMP directive");
7185 }
7186
7187 return Res;
7188}
7189
7190static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7191 QualType NewType) {
7192 assert(NewType->isFunctionProtoType() &&
7193 "Expected function type with prototype.");
7194 assert(FD->getType()->isFunctionNoProtoType() &&
7195 "Expected function with type with no prototype.");
7196 assert(FDWithProto->getType()->isFunctionProtoType() &&
7197 "Expected function with prototype.");
7198 // Synthesize parameters with the same types.
7199 FD->setType(NewType);
7201 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7202 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
7203 SourceLocation(), nullptr, P->getType(),
7204 /*TInfo=*/nullptr, SC_None, nullptr);
7205 Param->setScopeInfo(0, Params.size());
7206 Param->setImplicit();
7207 Params.push_back(Param);
7208 }
7209
7210 FD->setParams(Params);
7211}
7212
7214 if (D->isInvalidDecl())
7215 return;
7216 FunctionDecl *FD = nullptr;
7217 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7218 FD = UTemplDecl->getTemplatedDecl();
7219 else
7220 FD = cast<FunctionDecl>(D);
7221 assert(FD && "Expected a function declaration!");
7222
7223 // If we are instantiating templates we do *not* apply scoped assumptions but
7224 // only global ones. We apply scoped assumption to the template definition
7225 // though.
7226 if (!SemaRef.inTemplateInstantiation()) {
7227 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7228 FD->addAttr(AA);
7229 }
7230 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7231 FD->addAttr(AA);
7232}
7233
7234SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7235 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7236
7238 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7240 if (!D.getIdentifier())
7241 return;
7242
7243 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7244
7245 // Template specialization is an extension, check if we do it.
7246 bool IsTemplated = !TemplateParamLists.empty();
7247 if (IsTemplated &&
7248 !DVScope.TI->isExtensionActive(
7249 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7250 return;
7251
7252 const IdentifierInfo *BaseII = D.getIdentifier();
7255 SemaRef.LookupParsedName(Lookup, S, &D.getCXXScopeSpec(),
7256 /*ObjectType=*/QualType());
7257
7258 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
7259 QualType FType = TInfo->getType();
7260
7261 bool IsConstexpr =
7263 bool IsConsteval =
7265
7266 for (auto *Candidate : Lookup) {
7267 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7268 FunctionDecl *UDecl = nullptr;
7269 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7270 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7271 // FIXME: Should this compare the template parameter lists on all levels?
7272 if (SemaRef.Context.isSameTemplateParameterList(
7273 FTD->getTemplateParameters(), TemplateParamLists.back()))
7274 UDecl = FTD->getTemplatedDecl();
7275 } else if (!IsTemplated)
7276 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7277 if (!UDecl)
7278 continue;
7279
7280 // Don't specialize constexpr/consteval functions with
7281 // non-constexpr/consteval functions.
7282 if (UDecl->isConstexpr() && !IsConstexpr)
7283 continue;
7284 if (UDecl->isConsteval() && !IsConsteval)
7285 continue;
7286
7287 QualType UDeclTy = UDecl->getType();
7288 if (!UDeclTy->isDependentType()) {
7290 FType, UDeclTy, /*OfBlockPointer=*/false,
7291 /*Unqualified=*/false, /*AllowCXX=*/true);
7292 if (NewType.isNull())
7293 continue;
7294 }
7295
7296 // Found a base!
7297 Bases.push_back(UDecl);
7298 }
7299
7300 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7301 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7302 // If no base was found we create a declaration that we use as base.
7303 if (Bases.empty() && UseImplicitBase) {
7305 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7306 BaseD->setImplicit(true);
7307 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7308 Bases.push_back(BaseTemplD->getTemplatedDecl());
7309 else
7310 Bases.push_back(cast<FunctionDecl>(BaseD));
7311 }
7312
7313 std::string MangledName;
7314 MangledName += D.getIdentifier()->getName();
7315 MangledName += getOpenMPVariantManglingSeparatorStr();
7316 MangledName += DVScope.NameSuffix;
7317 IdentifierInfo &VariantII = getASTContext().Idents.get(MangledName);
7318
7319 VariantII.setMangledOpenMPVariantName(true);
7320 D.SetIdentifier(&VariantII, D.getBeginLoc());
7321}
7322
7325 // Do not mark function as is used to prevent its emission if this is the
7326 // only place where it is used.
7329
7330 FunctionDecl *FD = nullptr;
7331 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7332 FD = UTemplDecl->getTemplatedDecl();
7333 else
7334 FD = cast<FunctionDecl>(D);
7335 auto *VariantFuncRef = DeclRefExpr::Create(
7337 /*RefersToEnclosingVariableOrCapture=*/false,
7338 /*NameLoc=*/FD->getLocation(), FD->getType(), ExprValueKind::VK_PRValue);
7339
7340 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7341 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7342 getASTContext(), VariantFuncRef, DVScope.TI,
7343 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7344 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7345 /*NeedDeviceAddrArgs=*/nullptr, /*NeedDeviceAddrArgsSize=*/0,
7346 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7347 for (FunctionDecl *BaseFD : Bases)
7348 BaseFD->addAttr(OMPDeclareVariantA);
7349}
7350
7352 SourceLocation LParenLoc,
7353 MultiExprArg ArgExprs,
7354 SourceLocation RParenLoc,
7355 Expr *ExecConfig) {
7356 // The common case is a regular call we do not want to specialize at all. Try
7357 // to make that case fast by bailing early.
7358 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7359 if (!CE)
7360 return Call;
7361
7362 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7363 if (!CalleeFnDecl)
7364 return Call;
7365
7366 if (getLangOpts().OpenMP >= 50 && getLangOpts().OpenMP <= 60 &&
7367 CalleeFnDecl->getIdentifier() &&
7368 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7369 // checking for any calls inside an Order region
7371 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7372 }
7373
7374 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7375 return Call;
7376
7377 ASTContext &Context = getASTContext();
7378 std::function<void(StringRef)> DiagUnknownTrait = [this,
7379 CE](StringRef ISATrait) {
7380 // TODO Track the selector locations in a way that is accessible here to
7381 // improve the diagnostic location.
7382 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7383 << ISATrait;
7384 };
7385 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7386 SemaRef.getCurFunctionDecl(),
7387 DSAStack->getConstructTraits(), getOpenMPDeviceNum());
7388
7389 QualType CalleeFnType = CalleeFnDecl->getType();
7390
7393 while (CalleeFnDecl) {
7394 for (OMPDeclareVariantAttr *A :
7395 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7396 Expr *VariantRef = A->getVariantFuncRef();
7397
7398 VariantMatchInfo VMI;
7399 OMPTraitInfo &TI = A->getTraitInfo();
7400 TI.getAsVariantMatchInfo(Context, VMI);
7401 if (!isVariantApplicableInContext(VMI, OMPCtx,
7402 /*DeviceSetOnly=*/false))
7403 continue;
7404
7405 VMIs.push_back(VMI);
7406 Exprs.push_back(VariantRef);
7407 }
7408
7409 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7410 }
7411
7412 ExprResult NewCall;
7413 do {
7414 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7415 if (BestIdx < 0)
7416 return Call;
7417 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7418 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7419
7420 {
7421 // Try to build a (member) call expression for the current best applicable
7422 // variant expression. We allow this to fail in which case we continue
7423 // with the next best variant expression. The fail case is part of the
7424 // implementation defined behavior in the OpenMP standard when it talks
7425 // about what differences in the function prototypes: "Any differences
7426 // that the specific OpenMP context requires in the prototype of the
7427 // variant from the base function prototype are implementation defined."
7428 // This wording is there to allow the specialized variant to have a
7429 // different type than the base function. This is intended and OK but if
7430 // we cannot create a call the difference is not in the "implementation
7431 // defined range" we allow.
7433
7434 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7435 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7436 BestExpr = MemberExpr::CreateImplicit(
7437 Context, MemberCall->getImplicitObjectArgument(),
7438 /*IsArrow=*/false, SpecializedMethod, Context.BoundMemberTy,
7439 MemberCall->getValueKind(), MemberCall->getObjectKind());
7440 }
7441 NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs,
7442 RParenLoc, ExecConfig);
7443 if (NewCall.isUsable()) {
7444 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7445 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7447 CalleeFnType, NewCalleeFnDecl->getType(),
7448 /*OfBlockPointer=*/false,
7449 /*Unqualified=*/false, /*AllowCXX=*/true);
7450 if (!NewType.isNull())
7451 break;
7452 // Don't use the call if the function type was not compatible.
7453 NewCall = nullptr;
7454 }
7455 }
7456 }
7457
7458 VMIs.erase(VMIs.begin() + BestIdx);
7459 Exprs.erase(Exprs.begin() + BestIdx);
7460 } while (!VMIs.empty());
7461
7462 if (!NewCall.isUsable())
7463 return Call;
7464 return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
7465}
7466
7467std::optional<std::pair<FunctionDecl *, Expr *>>
7469 Expr *VariantRef,
7470 OMPTraitInfo &TI,
7471 unsigned NumAppendArgs,
7472 SourceRange SR) {
7473 ASTContext &Context = getASTContext();
7474 if (!DG || DG.get().isNull())
7475 return std::nullopt;
7476
7477 const int VariantId = 1;
7478 // Must be applied only to single decl.
7479 if (!DG.get().isSingleDecl()) {
7480 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7481 << VariantId << SR;
7482 return std::nullopt;
7483 }
7484 Decl *ADecl = DG.get().getSingleDecl();
7485 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7486 ADecl = FTD->getTemplatedDecl();
7487
7488 // Decl must be a function.
7489 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7490 if (!FD) {
7491 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7492 << VariantId << SR;
7493 return std::nullopt;
7494 }
7495
7496 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7497 // The 'target' attribute needs to be separately checked because it does
7498 // not always signify a multiversion function declaration.
7499 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7500 };
7501 // OpenMP is not compatible with multiversion function attributes.
7502 if (HasMultiVersionAttributes(FD)) {
7503 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7504 << SR;
7505 return std::nullopt;
7506 }
7507
7508 // Allow #pragma omp declare variant only if the function is not used.
7509 if (FD->isUsed(false))
7510 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7511 << FD->getLocation();
7512
7513 // Check if the function was emitted already.
7514 const FunctionDecl *Definition;
7515 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7516 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7517 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7518 << FD->getLocation();
7519
7520 // The VariantRef must point to function.
7521 if (!VariantRef) {
7522 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7523 return std::nullopt;
7524 }
7525
7526 auto ShouldDelayChecks = [](Expr *&E, bool) {
7527 return E && (E->isTypeDependent() || E->isValueDependent() ||
7530 };
7531 // Do not check templates, wait until instantiation.
7532 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7533 TI.anyScoreOrCondition(ShouldDelayChecks))
7534 return std::make_pair(FD, VariantRef);
7535
7536 // Deal with non-constant score and user condition expressions.
7537 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7538 bool IsScore) -> bool {
7539 if (!E || E->isIntegerConstantExpr(getASTContext()))
7540 return false;
7541
7542 if (IsScore) {
7543 // We warn on non-constant scores and pretend they were not present.
7544 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7545 << E;
7546 E = nullptr;
7547 } else {
7548 // We could replace a non-constant user condition with "false" but we
7549 // will soon need to handle these anyway for the dynamic version of
7550 // OpenMP context selectors.
7551 Diag(E->getExprLoc(),
7552 diag::err_omp_declare_variant_user_condition_not_constant)
7553 << E;
7554 }
7555 return true;
7556 };
7557 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7558 return std::nullopt;
7559
7560 QualType AdjustedFnType = FD->getType();
7561 if (NumAppendArgs) {
7562 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7563 if (!PTy) {
7564 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7565 << SR;
7566 return std::nullopt;
7567 }
7568 // Adjust the function type to account for an extra omp_interop_t for each
7569 // specified in the append_args clause.
7570 const TypeDecl *TD = nullptr;
7571 LookupResult Result(SemaRef, &Context.Idents.get("omp_interop_t"),
7573 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
7574 NamedDecl *ND = Result.getFoundDecl();
7575 TD = dyn_cast_or_null<TypeDecl>(ND);
7576 }
7577 if (!TD) {
7578 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7579 return std::nullopt;
7580 }
7581 QualType InteropType =
7582 Context.getTypeDeclType(ElaboratedTypeKeyword::None,
7583 /*Qualifier=*/std::nullopt, TD);
7584 if (PTy->isVariadic()) {
7585 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7586 return std::nullopt;
7587 }
7589 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7590 Params.insert(Params.end(), NumAppendArgs, InteropType);
7591 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7592 PTy->getExtProtoInfo());
7593 }
7594
7595 // Convert VariantRef expression to the type of the original function to
7596 // resolve possible conflicts.
7597 ExprResult VariantRefCast = VariantRef;
7598 if (getLangOpts().CPlusPlus) {
7599 QualType FnPtrType;
7600 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7601 if (Method && !Method->isStatic()) {
7602 FnPtrType = Context.getMemberPointerType(
7603 AdjustedFnType, /*Qualifier=*/std::nullopt, Method->getParent());
7604 ExprResult ER;
7605 {
7606 // Build addr_of unary op to correctly handle type checks for member
7607 // functions.
7609 ER = SemaRef.CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7610 VariantRef);
7611 }
7612 if (!ER.isUsable()) {
7613 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7614 << VariantId << VariantRef->getSourceRange();
7615 return std::nullopt;
7616 }
7617 VariantRef = ER.get();
7618 } else {
7619 FnPtrType = Context.getPointerType(AdjustedFnType);
7620 }
7621 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7622 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7623 ImplicitConversionSequence ICS = SemaRef.TryImplicitConversion(
7624 VariantRef, FnPtrType.getUnqualifiedType(),
7625 /*SuppressUserConversions=*/false, Sema::AllowedExplicit::None,
7626 /*InOverloadResolution=*/false,
7627 /*CStyle=*/false,
7628 /*AllowObjCWritebackConversion=*/false);
7629 if (ICS.isFailure()) {
7630 Diag(VariantRef->getExprLoc(),
7631 diag::err_omp_declare_variant_incompat_types)
7632 << VariantRef->getType()
7633 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7634 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7635 return std::nullopt;
7636 }
7637 VariantRefCast = SemaRef.PerformImplicitConversion(
7638 VariantRef, FnPtrType.getUnqualifiedType(),
7640 if (!VariantRefCast.isUsable())
7641 return std::nullopt;
7642 }
7643 // Drop previously built artificial addr_of unary op for member functions.
7644 if (Method && !Method->isStatic()) {
7645 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7646 if (auto *UO = dyn_cast<UnaryOperator>(
7647 PossibleAddrOfVariantRef->IgnoreImplicit()))
7648 VariantRefCast = UO->getSubExpr();
7649 }
7650 }
7651
7652 ExprResult ER = SemaRef.CheckPlaceholderExpr(VariantRefCast.get());
7653 if (!ER.isUsable() ||
7655 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7656 << VariantId << VariantRef->getSourceRange();
7657 return std::nullopt;
7658 }
7659
7660 // The VariantRef must point to function.
7661 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7662 if (!DRE) {
7663 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7664 << VariantId << VariantRef->getSourceRange();
7665 return std::nullopt;
7666 }
7667 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7668 if (!NewFD) {
7669 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7670 << VariantId << VariantRef->getSourceRange();
7671 return std::nullopt;
7672 }
7673
7674 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7675 Diag(VariantRef->getExprLoc(),
7676 diag::err_omp_declare_variant_same_base_function)
7677 << VariantRef->getSourceRange();
7678 return std::nullopt;
7679 }
7680
7681 // Check if function types are compatible in C.
7682 if (!getLangOpts().CPlusPlus) {
7683 QualType NewType =
7684 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7685 if (NewType.isNull()) {
7686 Diag(VariantRef->getExprLoc(),
7687 diag::err_omp_declare_variant_incompat_types)
7688 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7689 << VariantRef->getSourceRange();
7690 return std::nullopt;
7691 }
7692 if (NewType->isFunctionProtoType()) {
7693 if (FD->getType()->isFunctionNoProtoType())
7694 setPrototype(SemaRef, FD, NewFD, NewType);
7695 else if (NewFD->getType()->isFunctionNoProtoType())
7696 setPrototype(SemaRef, NewFD, FD, NewType);
7697 }
7698 }
7699
7700 // Check if variant function is not marked with declare variant directive.
7701 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7702 Diag(VariantRef->getExprLoc(),
7703 diag::warn_omp_declare_variant_marked_as_declare_variant)
7704 << VariantRef->getSourceRange();
7705 SourceRange SR =
7706 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7707 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7708 return std::nullopt;
7709 }
7710
7711 enum DoesntSupport {
7712 VirtFuncs = 1,
7713 Constructors = 3,
7714 Destructors = 4,
7715 DeletedFuncs = 5,
7716 DefaultedFuncs = 6,
7717 ConstexprFuncs = 7,
7718 ConstevalFuncs = 8,
7719 };
7720 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7721 if (CXXFD->isVirtual()) {
7722 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7723 << VirtFuncs;
7724 return std::nullopt;
7725 }
7726
7727 if (isa<CXXConstructorDecl>(FD)) {
7728 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7729 << Constructors;
7730 return std::nullopt;
7731 }
7732
7733 if (isa<CXXDestructorDecl>(FD)) {
7734 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7735 << Destructors;
7736 return std::nullopt;
7737 }
7738 }
7739
7740 if (FD->isDeleted()) {
7741 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7742 << DeletedFuncs;
7743 return std::nullopt;
7744 }
7745
7746 if (FD->isDefaulted()) {
7747 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7748 << DefaultedFuncs;
7749 return std::nullopt;
7750 }
7751
7752 if (FD->isConstexpr()) {
7753 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7754 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7755 return std::nullopt;
7756 }
7757
7758 // Check general compatibility.
7759 if (SemaRef.areMultiversionVariantFunctionsCompatible(
7764 VariantRef->getExprLoc(),
7765 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7766 PartialDiagnosticAt(VariantRef->getExprLoc(),
7767 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7768 << FD->getLocation()),
7769 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7770 /*CLinkageMayDiffer=*/true))
7771 return std::nullopt;
7772 return std::make_pair(FD, cast<Expr>(DRE));
7773}
7774
7776 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7777 ArrayRef<Expr *> AdjustArgsNothing,
7778 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7779 ArrayRef<Expr *> AdjustArgsNeedDeviceAddr,
7780 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7781 SourceLocation AppendArgsLoc, SourceRange SR) {
7782
7783 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7784 // An adjust_args clause or append_args clause can only be specified if the
7785 // dispatch selector of the construct selector set appears in the match
7786 // clause.
7787
7788 SmallVector<Expr *, 8> AllAdjustArgs;
7789 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7790 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7791 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDeviceAddr);
7792
7793 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7794 VariantMatchInfo VMI;
7796 if (!llvm::is_contained(
7797 VMI.ConstructTraits,
7798 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7799 if (!AllAdjustArgs.empty())
7800 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7801 << getOpenMPClauseNameForDiag(OMPC_adjust_args);
7802 if (!AppendArgs.empty())
7803 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7804 << getOpenMPClauseNameForDiag(OMPC_append_args);
7805 return;
7806 }
7807 }
7808
7809 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7810 // Each argument can only appear in a single adjust_args clause for each
7811 // declare variant directive.
7813
7814 for (Expr *E : AllAdjustArgs) {
7815 E = E->IgnoreParenImpCasts();
7816 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7817 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7818 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7819 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7820 FD->getParamDecl(PVD->getFunctionScopeIndex())
7821 ->getCanonicalDecl() == CanonPVD) {
7822 // It's a parameter of the function, check duplicates.
7823 if (!AdjustVars.insert(CanonPVD).second) {
7824 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7825 << PVD;
7826 return;
7827 }
7828 continue;
7829 }
7830 }
7831 }
7832 // Anything that is not a function parameter is an error.
7833 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7834 return;
7835 }
7836
7837 // OpenMP 6.0 [9.6.2 (page 332, line 31-33, adjust_args clause, Restrictions]
7838 // If the `need_device_addr` adjust-op modifier is present, each list item
7839 // that appears in the clause must refer to an argument in the declaration of
7840 // the function variant that has a reference type
7841 if (getLangOpts().OpenMP >= 60) {
7842 for (Expr *E : AdjustArgsNeedDeviceAddr) {
7843 E = E->IgnoreParenImpCasts();
7844 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7845 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
7846 if (!VD->getType()->isReferenceType())
7847 Diag(E->getExprLoc(),
7848 diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
7849 }
7850 }
7851 }
7852 }
7853
7854 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7855 getASTContext(), VariantRef, &TI,
7856 const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7857 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7858 AdjustArgsNeedDevicePtr.size(),
7859 const_cast<Expr **>(AdjustArgsNeedDeviceAddr.data()),
7860 AdjustArgsNeedDeviceAddr.size(),
7861 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7862 FD->addAttr(NewAttr);
7863}
7864
7865static CapturedStmt *
7867 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7868 assert(CS && "Captured statement expected");
7869 // 1.2.2 OpenMP Language Terminology
7870 // Structured block - An executable statement with a single entry at the
7871 // top and a single exit at the bottom.
7872 // The point of exit cannot be a branch out of the structured block.
7873 // longjmp() and throw() must not violate the entry/exit criteria.
7874 CS->getCapturedDecl()->setNothrow();
7875
7876 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
7877 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7879 // 1.2.2 OpenMP Language Terminology
7880 // Structured block - An executable statement with a single entry at the
7881 // top and a single exit at the bottom.
7882 // The point of exit cannot be a branch out of the structured block.
7883 // longjmp() and throw() must not violate the entry/exit criteria.
7884 CS->getCapturedDecl()->setNothrow();
7885 }
7887 return CS;
7888}
7889
7892 Stmt *AStmt, SourceLocation StartLoc,
7893 SourceLocation EndLoc) {
7894 if (!AStmt)
7895 return StmtError();
7896
7897 setBranchProtectedScope(SemaRef, OMPD_parallel, AStmt);
7898
7899 return OMPParallelDirective::Create(
7900 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
7901 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
7902}
7903
7904namespace {
7905/// Iteration space of a single for loop.
7906struct LoopIterationSpace final {
7907 /// True if the condition operator is the strict compare operator (<, > or
7908 /// !=).
7909 bool IsStrictCompare = false;
7910 /// Condition of the loop.
7911 Expr *PreCond = nullptr;
7912 /// This expression calculates the number of iterations in the loop.
7913 /// It is always possible to calculate it before starting the loop.
7914 Expr *NumIterations = nullptr;
7915 /// The loop counter variable.
7916 Expr *CounterVar = nullptr;
7917 /// Private loop counter variable.
7918 Expr *PrivateCounterVar = nullptr;
7919 /// This is initializer for the initial value of #CounterVar.
7920 Expr *CounterInit = nullptr;
7921 /// This is step for the #CounterVar used to generate its update:
7922 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7923 Expr *CounterStep = nullptr;
7924 /// Should step be subtracted?
7925 bool Subtract = false;
7926 /// Source range of the loop init.
7927 SourceRange InitSrcRange;
7928 /// Source range of the loop condition.
7929 SourceRange CondSrcRange;
7930 /// Source range of the loop increment.
7931 SourceRange IncSrcRange;
7932 /// Minimum value that can have the loop control variable. Used to support
7933 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7934 /// since only such variables can be used in non-loop invariant expressions.
7935 Expr *MinValue = nullptr;
7936 /// Maximum value that can have the loop control variable. Used to support
7937 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7938 /// since only such variables can be used in non-loop invariant expressions.
7939 Expr *MaxValue = nullptr;
7940 /// true, if the lower bound depends on the outer loop control var.
7941 bool IsNonRectangularLB = false;
7942 /// true, if the upper bound depends on the outer loop control var.
7943 bool IsNonRectangularUB = false;
7944 /// Index of the loop this loop depends on and forms non-rectangular loop
7945 /// nest.
7946 unsigned LoopDependentIdx = 0;
7947 /// Final condition for the non-rectangular loop nest support. It is used to
7948 /// check that the number of iterations for this particular counter must be
7949 /// finished.
7950 Expr *FinalCondition = nullptr;
7951};
7952
7953/// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls
7954/// set are referenced. Used for verifying loop nest structure before
7955/// performing a loop collapse operation.
7956class ForSubExprChecker : public DynamicRecursiveASTVisitor {
7957 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7958 VarDecl *ForbiddenVar = nullptr;
7959 SourceRange ErrLoc;
7960
7961public:
7962 explicit ForSubExprChecker(
7963 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7964 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
7965 // We want to visit implicit code, i.e. synthetic initialisation statements
7966 // created during range-for lowering.
7967 ShouldVisitImplicitCode = true;
7968 }
7969
7970 bool VisitDeclRefExpr(DeclRefExpr *E) override {
7971 ValueDecl *VD = E->getDecl();
7973 return true;
7974 VarDecl *V = VD->getPotentiallyDecomposedVarDecl();
7975 if (V->getType()->isReferenceType()) {
7976 VarDecl *VD = V->getDefinition();
7977 if (VD->hasInit()) {
7978 Expr *I = VD->getInit();
7979 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
7980 if (!DRE)
7981 return true;
7983 }
7984 }
7985 Decl *Canon = V->getCanonicalDecl();
7986 if (CollapsedLoopVarDecls.contains(Canon)) {
7987 ForbiddenVar = V;
7988 ErrLoc = E->getSourceRange();
7989 return false;
7990 }
7991
7992 return true;
7993 }
7994
7995 VarDecl *getForbiddenVar() const { return ForbiddenVar; }
7996 SourceRange getErrRange() const { return ErrLoc; }
7997};
7998
7999/// Helper class for checking canonical form of the OpenMP loops and
8000/// extracting iteration space of each loop in the loop nest, that will be used
8001/// for IR generation.
8002class OpenMPIterationSpaceChecker {
8003 /// Reference to Sema.
8004 Sema &SemaRef;
8005 /// Does the loop associated directive support non-rectangular loops?
8006 bool SupportsNonRectangular;
8007 /// Data-sharing stack.
8008 DSAStackTy &Stack;
8009 /// A location for diagnostics (when there is no some better location).
8010 SourceLocation DefaultLoc;
8011 /// A location for diagnostics (when increment is not compatible).
8012 SourceLocation ConditionLoc;
8013 /// The set of variables declared within the (to be collapsed) loop nest.
8014 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8015 /// A source location for referring to loop init later.
8016 SourceRange InitSrcRange;
8017 /// A source location for referring to condition later.
8018 SourceRange ConditionSrcRange;
8019 /// A source location for referring to increment later.
8020 SourceRange IncrementSrcRange;
8021 /// Loop variable.
8022 ValueDecl *LCDecl = nullptr;
8023 /// Reference to loop variable.
8024 Expr *LCRef = nullptr;
8025 /// Lower bound (initializer for the var).
8026 Expr *LB = nullptr;
8027 /// Upper bound.
8028 Expr *UB = nullptr;
8029 /// Loop step (increment).
8030 Expr *Step = nullptr;
8031 /// This flag is true when condition is one of:
8032 /// Var < UB
8033 /// Var <= UB
8034 /// UB > Var
8035 /// UB >= Var
8036 /// This will have no value when the condition is !=
8037 std::optional<bool> TestIsLessOp;
8038 /// This flag is true when condition is strict ( < or > ).
8039 bool TestIsStrictOp = false;
8040 /// This flag is true when step is subtracted on each iteration.
8041 bool SubtractStep = false;
8042 /// The outer loop counter this loop depends on (if any).
8043 const ValueDecl *DepDecl = nullptr;
8044 /// Contains number of loop (starts from 1) on which loop counter init
8045 /// expression of this loop depends on.
8046 std::optional<unsigned> InitDependOnLC;
8047 /// Contains number of loop (starts from 1) on which loop counter condition
8048 /// expression of this loop depends on.
8049 std::optional<unsigned> CondDependOnLC;
8050 /// Checks if the provide statement depends on the loop counter.
8051 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
8052 bool IsInitializer);
8053 /// Original condition required for checking of the exit condition for
8054 /// non-rectangular loop.
8055 Expr *Condition = nullptr;
8056
8057public:
8058 OpenMPIterationSpaceChecker(
8059 Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack,
8060 SourceLocation DefaultLoc,
8061 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
8062 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8063 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
8064 CollapsedLoopVarDecls(CollapsedLoopDecls) {}
8065 /// Check init-expr for canonical loop form and save loop counter
8066 /// variable - #Var and its initialization value - #LB.
8067 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
8068 /// Check test-expr for canonical form, save upper-bound (#UB), flags
8069 /// for less/greater and for strict/non-strict comparison.
8070 bool checkAndSetCond(Expr *S);
8071 /// Check incr-expr for canonical loop form and return true if it
8072 /// does not conform, otherwise save loop step (#Step).
8073 bool checkAndSetInc(Expr *S);
8074 /// Return the loop counter variable.
8075 ValueDecl *getLoopDecl() const { return LCDecl; }
8076 /// Return the reference expression to loop counter variable.
8077 Expr *getLoopDeclRefExpr() const { return LCRef; }
8078 /// Source range of the loop init.
8079 SourceRange getInitSrcRange() const { return InitSrcRange; }
8080 /// Source range of the loop condition.
8081 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
8082 /// Source range of the loop increment.
8083 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
8084 /// True if the step should be subtracted.
8085 bool shouldSubtractStep() const { return SubtractStep; }
8086 /// True, if the compare operator is strict (<, > or !=).
8087 bool isStrictTestOp() const { return TestIsStrictOp; }
8088 /// Build the expression to calculate the number of iterations.
8089 Expr *buildNumIterations(
8090 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8091 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8092 /// Build the precondition expression for the loops.
8093 Expr *
8094 buildPreCond(Scope *S, Expr *Cond,
8095 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8096 /// Build reference expression to the counter be used for codegen.
8097 DeclRefExpr *
8098 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8099 DSAStackTy &DSA) const;
8100 /// Build reference expression to the private counter be used for
8101 /// codegen.
8102 Expr *buildPrivateCounterVar() const;
8103 /// Build initialization of the counter be used for codegen.
8104 Expr *buildCounterInit() const;
8105 /// Build step of the counter be used for codegen.
8106 Expr *buildCounterStep() const;
8107 /// Build loop data with counter value for depend clauses in ordered
8108 /// directives.
8109 Expr *
8110 buildOrderedLoopData(Scope *S, Expr *Counter,
8111 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8112 SourceLocation Loc, Expr *Inc = nullptr,
8113 OverloadedOperatorKind OOK = OO_Amp);
8114 /// Builds the minimum value for the loop counter.
8115 std::pair<Expr *, Expr *> buildMinMaxValues(
8116 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8117 /// Builds final condition for the non-rectangular loops.
8118 Expr *buildFinalCondition(Scope *S) const;
8119 /// Return true if any expression is dependent.
8120 bool dependent() const;
8121 /// Returns true if the initializer forms non-rectangular loop.
8122 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
8123 /// Returns true if the condition forms non-rectangular loop.
8124 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
8125 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
8126 unsigned getLoopDependentIdx() const {
8127 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
8128 }
8129
8130private:
8131 /// Check the right-hand side of an assignment in the increment
8132 /// expression.
8133 bool checkAndSetIncRHS(Expr *RHS);
8134 /// Helper to set loop counter variable and its initializer.
8135 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8136 bool EmitDiags);
8137 /// Helper to set upper bound.
8138 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
8139 SourceRange SR, SourceLocation SL);
8140 /// Helper to set loop increment.
8141 bool setStep(Expr *NewStep, bool Subtract);
8142};
8143
8144bool OpenMPIterationSpaceChecker::dependent() const {
8145 if (!LCDecl) {
8146 assert(!LB && !UB && !Step);
8147 return false;
8148 }
8149 return LCDecl->getType()->isDependentType() ||
8150 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
8151 (Step && Step->isValueDependent());
8152}
8153
8154bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
8155 Expr *NewLCRefExpr,
8156 Expr *NewLB, bool EmitDiags) {
8157 // State consistency checking to ensure correct usage.
8158 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
8159 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8160 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
8161 return true;
8162 LCDecl = getCanonicalDecl(NewLCDecl);
8163 LCRef = NewLCRefExpr;
8164 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
8165 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8166 if ((Ctor->isCopyOrMoveConstructor() ||
8167 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8168 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8169 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
8170 LB = NewLB;
8171 if (EmitDiags)
8172 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
8173 return false;
8174}
8175
8176bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
8177 bool StrictOp, SourceRange SR,
8178 SourceLocation SL) {
8179 // State consistency checking to ensure correct usage.
8180 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
8181 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8182 if (!NewUB || NewUB->containsErrors())
8183 return true;
8184 UB = NewUB;
8185 if (LessOp)
8186 TestIsLessOp = LessOp;
8187 TestIsStrictOp = StrictOp;
8188 ConditionSrcRange = SR;
8189 ConditionLoc = SL;
8190 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
8191 return false;
8192}
8193
8194bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
8195 // State consistency checking to ensure correct usage.
8196 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
8197 if (!NewStep || NewStep->containsErrors())
8198 return true;
8199 if (!NewStep->isValueDependent()) {
8200 // Check that the step is integer expression.
8201 SourceLocation StepLoc = NewStep->getBeginLoc();
8203 StepLoc, getExprAsWritten(NewStep));
8204 if (Val.isInvalid())
8205 return true;
8206 NewStep = Val.get();
8207
8208 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8209 // If test-expr is of form var relational-op b and relational-op is < or
8210 // <= then incr-expr must cause var to increase on each iteration of the
8211 // loop. If test-expr is of form var relational-op b and relational-op is
8212 // > or >= then incr-expr must cause var to decrease on each iteration of
8213 // the loop.
8214 // If test-expr is of form b relational-op var and relational-op is < or
8215 // <= then incr-expr must cause var to decrease on each iteration of the
8216 // loop. If test-expr is of form b relational-op var and relational-op is
8217 // > or >= then incr-expr must cause var to increase on each iteration of
8218 // the loop.
8219 std::optional<llvm::APSInt> Result =
8220 NewStep->getIntegerConstantExpr(SemaRef.Context);
8221 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
8222 bool IsConstNeg =
8223 Result && Result->isSigned() && (Subtract != Result->isNegative());
8224 bool IsConstPos =
8225 Result && Result->isSigned() && (Subtract == Result->isNegative());
8226 bool IsConstZero = Result && !Result->getBoolValue();
8227
8228 // != with increment is treated as <; != with decrement is treated as >
8229 if (!TestIsLessOp)
8230 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8231 if (UB && (IsConstZero ||
8232 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8233 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8234 SemaRef.Diag(NewStep->getExprLoc(),
8235 diag::err_omp_loop_incr_not_compatible)
8236 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
8237 SemaRef.Diag(ConditionLoc,
8238 diag::note_omp_loop_cond_requires_compatible_incr)
8239 << *TestIsLessOp << ConditionSrcRange;
8240 return true;
8241 }
8242 if (*TestIsLessOp == Subtract) {
8243 NewStep =
8244 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
8245 .get();
8246 Subtract = !Subtract;
8247 }
8248 }
8249
8250 Step = NewStep;
8251 SubtractStep = Subtract;
8252 return false;
8253}
8254
8255namespace {
8256/// Checker for the non-rectangular loops. Checks if the initializer or
8257/// condition expression references loop counter variable.
8258class LoopCounterRefChecker final
8259 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8260 Sema &SemaRef;
8261 DSAStackTy &Stack;
8262 const ValueDecl *CurLCDecl = nullptr;
8263 const ValueDecl *DepDecl = nullptr;
8264 const ValueDecl *PrevDepDecl = nullptr;
8265 bool IsInitializer = true;
8266 bool SupportsNonRectangular;
8267 unsigned BaseLoopId = 0;
8268 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8269 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
8270 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8271 << (IsInitializer ? 0 : 1);
8272 return false;
8273 }
8274 const auto &&Data = Stack.isLoopControlVariable(VD);
8275 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8276 // The type of the loop iterator on which we depend may not have a random
8277 // access iterator type.
8278 if (Data.first && VD->getType()->isRecordType()) {
8279 SmallString<128> Name;
8280 llvm::raw_svector_ostream OS(Name);
8281 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8282 /*Qualified=*/true);
8283 SemaRef.Diag(E->getExprLoc(),
8284 diag::err_omp_wrong_dependency_iterator_type)
8285 << OS.str();
8286 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8287 return false;
8288 }
8289 if (Data.first && !SupportsNonRectangular) {
8290 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8291 return false;
8292 }
8293 if (Data.first &&
8294 (DepDecl || (PrevDepDecl &&
8295 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8296 if (!DepDecl && PrevDepDecl)
8297 DepDecl = PrevDepDecl;
8298 SmallString<128> Name;
8299 llvm::raw_svector_ostream OS(Name);
8300 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8301 /*Qualified=*/true);
8302 SemaRef.Diag(E->getExprLoc(),
8303 diag::err_omp_invariant_or_linear_dependency)
8304 << OS.str();
8305 return false;
8306 }
8307 if (Data.first) {
8308 DepDecl = VD;
8309 BaseLoopId = Data.first;
8310 }
8311 return Data.first;
8312 }
8313
8314public:
8315 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8316 const ValueDecl *VD = E->getDecl();
8317 if (isa<VarDecl>(VD))
8318 return checkDecl(E, VD);
8319 return false;
8320 }
8321 bool VisitMemberExpr(const MemberExpr *E) {
8322 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8323 const ValueDecl *VD = E->getMemberDecl();
8324 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8325 return checkDecl(E, VD);
8326 }
8327 return false;
8328 }
8329 bool VisitStmt(const Stmt *S) {
8330 bool Res = false;
8331 for (const Stmt *Child : S->children())
8332 Res = (Child && Visit(Child)) || Res;
8333 return Res;
8334 }
8335 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8336 const ValueDecl *CurLCDecl, bool IsInitializer,
8337 const ValueDecl *PrevDepDecl = nullptr,
8338 bool SupportsNonRectangular = true)
8339 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8340 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8341 SupportsNonRectangular(SupportsNonRectangular) {}
8342 unsigned getBaseLoopId() const {
8343 assert(CurLCDecl && "Expected loop dependency.");
8344 return BaseLoopId;
8345 }
8346 const ValueDecl *getDepDecl() const {
8347 assert(CurLCDecl && "Expected loop dependency.");
8348 return DepDecl;
8349 }
8350};
8351} // namespace
8352
8353std::optional<unsigned>
8354OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8355 bool IsInitializer) {
8356 // Check for the non-rectangular loops.
8357 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8358 DepDecl, SupportsNonRectangular);
8359 if (LoopStmtChecker.Visit(S)) {
8360 DepDecl = LoopStmtChecker.getDepDecl();
8361 return LoopStmtChecker.getBaseLoopId();
8362 }
8363 return std::nullopt;
8364}
8365
8366bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8367 // Check init-expr for canonical loop form and save loop counter
8368 // variable - #Var and its initialization value - #LB.
8369 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8370 // var = lb
8371 // integer-type var = lb
8372 // random-access-iterator-type var = lb
8373 // pointer-type var = lb
8374 //
8375 if (!S) {
8376 if (EmitDiags) {
8377 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8378 }
8379 return true;
8380 }
8381 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8382 if (!ExprTemp->cleanupsHaveSideEffects())
8383 S = ExprTemp->getSubExpr();
8384
8385 if (!CollapsedLoopVarDecls.empty()) {
8386 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8387 if (!FSEC.TraverseStmt(S)) {
8388 SourceRange Range = FSEC.getErrRange();
8389 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8390 << Range.getEnd() << 0 << FSEC.getForbiddenVar();
8391 return true;
8392 }
8393 }
8394
8395 InitSrcRange = S->getSourceRange();
8396 if (Expr *E = dyn_cast<Expr>(S))
8397 S = E->IgnoreParens();
8398 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8399 if (BO->getOpcode() == BO_Assign) {
8400 Expr *LHS = BO->getLHS()->IgnoreParens();
8401 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8402 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8403 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8404 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8405 EmitDiags);
8406 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8407 }
8408 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8409 if (ME->isArrow() &&
8410 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8411 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8412 EmitDiags);
8413 }
8414 }
8415 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8416 if (DS->isSingleDecl()) {
8417 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8418 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8419 // Accept non-canonical init form here but emit ext. warning.
8420 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8421 SemaRef.Diag(S->getBeginLoc(),
8422 diag::ext_omp_loop_not_canonical_init)
8423 << S->getSourceRange();
8424 return setLCDeclAndLB(
8425 Var,
8426 buildDeclRefExpr(SemaRef, Var,
8427 Var->getType().getNonReferenceType(),
8428 DS->getBeginLoc()),
8429 Var->getInit(), EmitDiags);
8430 }
8431 }
8432 }
8433 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8434 if (CE->getOperator() == OO_Equal) {
8435 Expr *LHS = CE->getArg(0);
8436 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8437 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8438 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8439 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8440 EmitDiags);
8441 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8442 }
8443 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8444 if (ME->isArrow() &&
8445 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8446 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8447 EmitDiags);
8448 }
8449 }
8450 }
8451
8452 if (dependent() || SemaRef.CurContext->isDependentContext())
8453 return false;
8454 if (EmitDiags) {
8455 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8456 << S->getSourceRange();
8457 }
8458 return true;
8459}
8460
8461/// Ignore parenthesizes, implicit casts, copy constructor and return the
8462/// variable (which may be the loop variable) if possible.
8463static const ValueDecl *getInitLCDecl(const Expr *E) {
8464 if (!E)
8465 return nullptr;
8466 E = getExprAsWritten(E);
8467 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8468 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8469 if ((Ctor->isCopyOrMoveConstructor() ||
8470 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8471 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8472 E = CE->getArg(0)->IgnoreParenImpCasts();
8473 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8474 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8475 return getCanonicalDecl(VD);
8476 }
8477 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8478 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8479 return getCanonicalDecl(ME->getMemberDecl());
8480 return nullptr;
8481}
8482
8483bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8484 // Check test-expr for canonical form, save upper-bound UB, flags for
8485 // less/greater and for strict/non-strict comparison.
8486 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8487 // var relational-op b
8488 // b relational-op var
8489 //
8490 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8491 if (!S) {
8492 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8493 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8494 return true;
8495 }
8496 Condition = S;
8497 S = getExprAsWritten(S);
8498
8499 if (!CollapsedLoopVarDecls.empty()) {
8500 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8501 if (!FSEC.TraverseStmt(S)) {
8502 SourceRange Range = FSEC.getErrRange();
8503 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8504 << Range.getEnd() << 1 << FSEC.getForbiddenVar();
8505 return true;
8506 }
8507 }
8508
8509 SourceLocation CondLoc = S->getBeginLoc();
8510 auto &&CheckAndSetCond =
8511 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8512 const Expr *RHS, SourceRange SR,
8513 SourceLocation OpLoc) -> std::optional<bool> {
8514 if (BinaryOperator::isRelationalOp(Opcode)) {
8515 if (getInitLCDecl(LHS) == LCDecl)
8516 return setUB(const_cast<Expr *>(RHS),
8517 (Opcode == BO_LT || Opcode == BO_LE),
8518 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8519 if (getInitLCDecl(RHS) == LCDecl)
8520 return setUB(const_cast<Expr *>(LHS),
8521 (Opcode == BO_GT || Opcode == BO_GE),
8522 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8523 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8524 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8525 /*LessOp=*/std::nullopt,
8526 /*StrictOp=*/true, SR, OpLoc);
8527 }
8528 return std::nullopt;
8529 };
8530 std::optional<bool> Res;
8531 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8532 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8533 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8534 RBO->getOperatorLoc());
8535 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8536 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8537 BO->getSourceRange(), BO->getOperatorLoc());
8538 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8539 if (CE->getNumArgs() == 2) {
8540 Res = CheckAndSetCond(
8541 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8542 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8543 }
8544 }
8545 if (Res)
8546 return *Res;
8547 if (dependent() || SemaRef.CurContext->isDependentContext())
8548 return false;
8549 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8550 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8551 return true;
8552}
8553
8554bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8555 // RHS of canonical loop form increment can be:
8556 // var + incr
8557 // incr + var
8558 // var - incr
8559 //
8560 RHS = RHS->IgnoreParenImpCasts();
8561 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8562 if (BO->isAdditiveOp()) {
8563 bool IsAdd = BO->getOpcode() == BO_Add;
8564 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8565 return setStep(BO->getRHS(), !IsAdd);
8566 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8567 return setStep(BO->getLHS(), /*Subtract=*/false);
8568 }
8569 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8570 bool IsAdd = CE->getOperator() == OO_Plus;
8571 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8572 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8573 return setStep(CE->getArg(1), !IsAdd);
8574 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8575 return setStep(CE->getArg(0), /*Subtract=*/false);
8576 }
8577 }
8578 if (dependent() || SemaRef.CurContext->isDependentContext())
8579 return false;
8580 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8581 << RHS->getSourceRange() << LCDecl;
8582 return true;
8583}
8584
8585bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8586 // Check incr-expr for canonical loop form and return true if it
8587 // does not conform.
8588 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8589 // ++var
8590 // var++
8591 // --var
8592 // var--
8593 // var += incr
8594 // var -= incr
8595 // var = var + incr
8596 // var = incr + var
8597 // var = var - incr
8598 //
8599 if (!S) {
8600 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8601 return true;
8602 }
8603 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8604 if (!ExprTemp->cleanupsHaveSideEffects())
8605 S = ExprTemp->getSubExpr();
8606
8607 if (!CollapsedLoopVarDecls.empty()) {
8608 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8609 if (!FSEC.TraverseStmt(S)) {
8610 SourceRange Range = FSEC.getErrRange();
8611 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8612 << Range.getEnd() << 2 << FSEC.getForbiddenVar();
8613 return true;
8614 }
8615 }
8616
8617 IncrementSrcRange = S->getSourceRange();
8618 S = S->IgnoreParens();
8619 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8620 if (UO->isIncrementDecrementOp() &&
8621 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8622 return setStep(SemaRef
8623 .ActOnIntegerConstant(UO->getBeginLoc(),
8624 (UO->isDecrementOp() ? -1 : 1))
8625 .get(),
8626 /*Subtract=*/false);
8627 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8628 switch (BO->getOpcode()) {
8629 case BO_AddAssign:
8630 case BO_SubAssign:
8631 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8632 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8633 break;
8634 case BO_Assign:
8635 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8636 return checkAndSetIncRHS(BO->getRHS());
8637 break;
8638 default:
8639 break;
8640 }
8641 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8642 switch (CE->getOperator()) {
8643 case OO_PlusPlus:
8644 case OO_MinusMinus:
8645 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8646 return setStep(SemaRef
8647 .ActOnIntegerConstant(
8648 CE->getBeginLoc(),
8649 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8650 .get(),
8651 /*Subtract=*/false);
8652 break;
8653 case OO_PlusEqual:
8654 case OO_MinusEqual:
8655 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8656 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8657 break;
8658 case OO_Equal:
8659 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8660 return checkAndSetIncRHS(CE->getArg(1));
8661 break;
8662 default:
8663 break;
8664 }
8665 }
8666 if (dependent() || SemaRef.CurContext->isDependentContext())
8667 return false;
8668 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8669 << S->getSourceRange() << LCDecl;
8670 return true;
8671}
8672
8673static ExprResult
8674tryBuildCapture(Sema &SemaRef, Expr *Capture,
8675 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8676 StringRef Name = ".capture_expr.") {
8677 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8678 return Capture;
8679 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8680 return SemaRef.PerformImplicitConversion(Capture->IgnoreImpCasts(),
8681 Capture->getType(),
8683 /*AllowExplicit=*/true);
8684 auto I = Captures.find(Capture);
8685 if (I != Captures.end())
8686 return buildCapture(SemaRef, Capture, I->second, Name);
8687 DeclRefExpr *Ref = nullptr;
8688 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8689 Captures[Capture] = Ref;
8690 return Res;
8691}
8692
8693/// Calculate number of iterations, transforming to unsigned, if number of
8694/// iterations may be larger than the original type.
8695static Expr *
8696calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8697 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8698 bool TestIsStrictOp, bool RoundToStep,
8699 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8700 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8701 if (!NewStep.isUsable())
8702 return nullptr;
8703 llvm::APSInt LRes, SRes;
8704 bool IsLowerConst = false, IsStepConst = false;
8705 if (std::optional<llvm::APSInt> Res =
8706 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8707 LRes = *Res;
8708 IsLowerConst = true;
8709 }
8710 if (std::optional<llvm::APSInt> Res =
8711 Step->getIntegerConstantExpr(SemaRef.Context)) {
8712 SRes = *Res;
8713 IsStepConst = true;
8714 }
8715 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8716 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8717 (TestIsStrictOp && LRes.isStrictlyPositive()));
8718 bool NeedToReorganize = false;
8719 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8720 if (!NoNeedToConvert && IsLowerConst &&
8721 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8722 NoNeedToConvert = true;
8723 if (RoundToStep) {
8724 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8725 ? LRes.getBitWidth()
8726 : SRes.getBitWidth();
8727 LRes = LRes.extend(BW + 1);
8728 LRes.setIsSigned(true);
8729 SRes = SRes.extend(BW + 1);
8730 SRes.setIsSigned(true);
8731 LRes -= SRes;
8732 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8733 LRes = LRes.trunc(BW);
8734 }
8735 if (TestIsStrictOp) {
8736 unsigned BW = LRes.getBitWidth();
8737 LRes = LRes.extend(BW + 1);
8738 LRes.setIsSigned(true);
8739 ++LRes;
8740 NoNeedToConvert =
8741 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8742 // truncate to the original bitwidth.
8743 LRes = LRes.trunc(BW);
8744 }
8745 NeedToReorganize = NoNeedToConvert;
8746 }
8747 llvm::APSInt URes;
8748 bool IsUpperConst = false;
8749 if (std::optional<llvm::APSInt> Res =
8750 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8751 URes = *Res;
8752 IsUpperConst = true;
8753 }
8754 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8755 (!RoundToStep || IsStepConst)) {
8756 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8757 : URes.getBitWidth();
8758 LRes = LRes.extend(BW + 1);
8759 LRes.setIsSigned(true);
8760 URes = URes.extend(BW + 1);
8761 URes.setIsSigned(true);
8762 URes -= LRes;
8763 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8764 NeedToReorganize = NoNeedToConvert;
8765 }
8766 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8767 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8768 // unsigned.
8769 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8770 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8771 QualType LowerTy = Lower->getType();
8772 QualType UpperTy = Upper->getType();
8773 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8774 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8775 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8776 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8778 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8779 Upper =
8780 SemaRef
8782 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8784 .get();
8785 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8786 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8787 }
8788 }
8789 if (!Lower || !Upper || NewStep.isInvalid())
8790 return nullptr;
8791
8792 ExprResult Diff;
8793 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8794 // 1]).
8795 if (NeedToReorganize) {
8796 Diff = Lower;
8797
8798 if (RoundToStep) {
8799 // Lower - Step
8800 Diff =
8801 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8802 if (!Diff.isUsable())
8803 return nullptr;
8804 }
8805
8806 // Lower - Step [+ 1]
8807 if (TestIsStrictOp)
8808 Diff = SemaRef.BuildBinOp(
8809 S, DefaultLoc, BO_Add, Diff.get(),
8810 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8811 if (!Diff.isUsable())
8812 return nullptr;
8813
8814 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8815 if (!Diff.isUsable())
8816 return nullptr;
8817
8818 // Upper - (Lower - Step [+ 1]).
8819 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8820 if (!Diff.isUsable())
8821 return nullptr;
8822 } else {
8823 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8824
8825 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8826 // BuildBinOp already emitted error, this one is to point user to upper
8827 // and lower bound, and to tell what is passed to 'operator-'.
8828 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8829 << Upper->getSourceRange() << Lower->getSourceRange();
8830 return nullptr;
8831 }
8832
8833 if (!Diff.isUsable())
8834 return nullptr;
8835
8836 // Upper - Lower [- 1]
8837 if (TestIsStrictOp)
8838 Diff = SemaRef.BuildBinOp(
8839 S, DefaultLoc, BO_Sub, Diff.get(),
8840 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8841 if (!Diff.isUsable())
8842 return nullptr;
8843
8844 if (RoundToStep) {
8845 // Upper - Lower [- 1] + Step
8846 Diff =
8847 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8848 if (!Diff.isUsable())
8849 return nullptr;
8850 }
8851 }
8852
8853 // Parentheses (for dumping/debugging purposes only).
8854 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8855 if (!Diff.isUsable())
8856 return nullptr;
8857
8858 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8859 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8860 if (!Diff.isUsable())
8861 return nullptr;
8862
8863 return Diff.get();
8864}
8865
8866/// Build the expression to calculate the number of iterations.
8867Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8868 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8869 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8870 QualType VarType = LCDecl->getType().getNonReferenceType();
8871 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8872 !SemaRef.getLangOpts().CPlusPlus)
8873 return nullptr;
8874 Expr *LBVal = LB;
8875 Expr *UBVal = UB;
8876 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8877 // max(LB(MinVal), LB(MaxVal)))
8878 if (InitDependOnLC) {
8879 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8880 if (!IS.MinValue || !IS.MaxValue)
8881 return nullptr;
8882 // OuterVar = Min
8883 ExprResult MinValue =
8884 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8885 if (!MinValue.isUsable())
8886 return nullptr;
8887
8888 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8889 IS.CounterVar, MinValue.get());
8890 if (!LBMinVal.isUsable())
8891 return nullptr;
8892 // OuterVar = Min, LBVal
8893 LBMinVal =
8894 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8895 if (!LBMinVal.isUsable())
8896 return nullptr;
8897 // (OuterVar = Min, LBVal)
8898 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8899 if (!LBMinVal.isUsable())
8900 return nullptr;
8901
8902 // OuterVar = Max
8903 ExprResult MaxValue =
8904 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8905 if (!MaxValue.isUsable())
8906 return nullptr;
8907
8908 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8909 IS.CounterVar, MaxValue.get());
8910 if (!LBMaxVal.isUsable())
8911 return nullptr;
8912 // OuterVar = Max, LBVal
8913 LBMaxVal =
8914 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8915 if (!LBMaxVal.isUsable())
8916 return nullptr;
8917 // (OuterVar = Max, LBVal)
8918 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8919 if (!LBMaxVal.isUsable())
8920 return nullptr;
8921
8922 Expr *LBMin =
8923 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
8924 Expr *LBMax =
8925 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
8926 if (!LBMin || !LBMax)
8927 return nullptr;
8928 // LB(MinVal) < LB(MaxVal)
8929 ExprResult MinLessMaxRes =
8930 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8931 if (!MinLessMaxRes.isUsable())
8932 return nullptr;
8933 Expr *MinLessMax =
8934 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
8935 .get();
8936 if (!MinLessMax)
8937 return nullptr;
8938 if (*TestIsLessOp) {
8939 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8940 // LB(MaxVal))
8941 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8942 MinLessMax, LBMin, LBMax);
8943 if (!MinLB.isUsable())
8944 return nullptr;
8945 LBVal = MinLB.get();
8946 } else {
8947 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8948 // LB(MaxVal))
8949 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8950 MinLessMax, LBMax, LBMin);
8951 if (!MaxLB.isUsable())
8952 return nullptr;
8953 LBVal = MaxLB.get();
8954 }
8955 // OuterVar = LB
8956 LBMinVal =
8957 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8958 if (!LBMinVal.isUsable())
8959 return nullptr;
8960 LBVal = LBMinVal.get();
8961 }
8962 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8963 // min(UB(MinVal), UB(MaxVal))
8964 if (CondDependOnLC) {
8965 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8966 if (!IS.MinValue || !IS.MaxValue)
8967 return nullptr;
8968 // OuterVar = Min
8969 ExprResult MinValue =
8970 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8971 if (!MinValue.isUsable())
8972 return nullptr;
8973
8974 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8975 IS.CounterVar, MinValue.get());
8976 if (!UBMinVal.isUsable())
8977 return nullptr;
8978 // OuterVar = Min, UBVal
8979 UBMinVal =
8980 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
8981 if (!UBMinVal.isUsable())
8982 return nullptr;
8983 // (OuterVar = Min, UBVal)
8984 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
8985 if (!UBMinVal.isUsable())
8986 return nullptr;
8987
8988 // OuterVar = Max
8989 ExprResult MaxValue =
8990 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8991 if (!MaxValue.isUsable())
8992 return nullptr;
8993
8994 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8995 IS.CounterVar, MaxValue.get());
8996 if (!UBMaxVal.isUsable())
8997 return nullptr;
8998 // OuterVar = Max, UBVal
8999 UBMaxVal =
9000 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
9001 if (!UBMaxVal.isUsable())
9002 return nullptr;
9003 // (OuterVar = Max, UBVal)
9004 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
9005 if (!UBMaxVal.isUsable())
9006 return nullptr;
9007
9008 Expr *UBMin =
9009 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
9010 Expr *UBMax =
9011 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
9012 if (!UBMin || !UBMax)
9013 return nullptr;
9014 // UB(MinVal) > UB(MaxVal)
9015 ExprResult MinGreaterMaxRes =
9016 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
9017 if (!MinGreaterMaxRes.isUsable())
9018 return nullptr;
9019 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
9020 Captures, ".min_greater_max")
9021 .get();
9022 if (!MinGreaterMax)
9023 return nullptr;
9024 if (*TestIsLessOp) {
9025 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
9026 // UB(MaxVal))
9027 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
9028 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
9029 if (!MaxUB.isUsable())
9030 return nullptr;
9031 UBVal = MaxUB.get();
9032 } else {
9033 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
9034 // UB(MaxVal))
9035 ExprResult MinUB = SemaRef.ActOnConditionalOp(
9036 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
9037 if (!MinUB.isUsable())
9038 return nullptr;
9039 UBVal = MinUB.get();
9040 }
9041 }
9042 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9043 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9044 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
9045 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
9046 if (!Upper || !Lower)
9047 return nullptr;
9048
9049 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9050 Step, VarType, TestIsStrictOp,
9051 /*RoundToStep=*/true, Captures);
9052 if (!Diff.isUsable())
9053 return nullptr;
9054
9055 // OpenMP runtime requires 32-bit or 64-bit loop variables.
9056 QualType Type = Diff.get()->getType();
9057 ASTContext &C = SemaRef.Context;
9058 bool UseVarType = VarType->hasIntegerRepresentation() &&
9059 C.getTypeSize(Type) > C.getTypeSize(VarType);
9060 if (!Type->isIntegerType() || UseVarType) {
9061 unsigned NewSize =
9062 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
9063 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
9065 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
9066 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
9067 Diff = SemaRef.PerformImplicitConversion(Diff.get(), Type,
9069 /*AllowExplicit=*/true);
9070 if (!Diff.isUsable())
9071 return nullptr;
9072 }
9073 }
9074 if (LimitedType) {
9075 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
9076 if (NewSize != C.getTypeSize(Type)) {
9077 if (NewSize < C.getTypeSize(Type)) {
9078 assert(NewSize == 64 && "incorrect loop var size");
9079 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
9080 << InitSrcRange << ConditionSrcRange;
9081 }
9082 QualType NewType = C.getIntTypeForBitwidth(
9084 C.getTypeSize(Type) < NewSize);
9085 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
9086 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
9088 /*AllowExplicit=*/true);
9089 if (!Diff.isUsable())
9090 return nullptr;
9091 }
9092 }
9093 }
9094
9095 return Diff.get();
9096}
9097
9098std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9099 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9100 // Do not build for iterators, they cannot be used in non-rectangular loop
9101 // nests.
9102 if (LCDecl->getType()->isRecordType())
9103 return std::make_pair(nullptr, nullptr);
9104 // If we subtract, the min is in the condition, otherwise the min is in the
9105 // init value.
9106 Expr *MinExpr = nullptr;
9107 Expr *MaxExpr = nullptr;
9108 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9109 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9110 bool LBNonRect =
9111 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9112 bool UBNonRect =
9113 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9114 Expr *Lower =
9115 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
9116 Expr *Upper =
9117 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
9118 if (!Upper || !Lower)
9119 return std::make_pair(nullptr, nullptr);
9120
9121 if (*TestIsLessOp)
9122 MinExpr = Lower;
9123 else
9124 MaxExpr = Upper;
9125
9126 // Build minimum/maximum value based on number of iterations.
9127 QualType VarType = LCDecl->getType().getNonReferenceType();
9128
9129 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9130 Step, VarType, TestIsStrictOp,
9131 /*RoundToStep=*/false, Captures);
9132 if (!Diff.isUsable())
9133 return std::make_pair(nullptr, nullptr);
9134
9135 // ((Upper - Lower [- 1]) / Step) * Step
9136 // Parentheses (for dumping/debugging purposes only).
9137 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9138 if (!Diff.isUsable())
9139 return std::make_pair(nullptr, nullptr);
9140
9141 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
9142 if (!NewStep.isUsable())
9143 return std::make_pair(nullptr, nullptr);
9144 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
9145 if (!Diff.isUsable())
9146 return std::make_pair(nullptr, nullptr);
9147
9148 // Parentheses (for dumping/debugging purposes only).
9149 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9150 if (!Diff.isUsable())
9151 return std::make_pair(nullptr, nullptr);
9152
9153 // Convert to the ptrdiff_t, if original type is pointer.
9154 if (VarType->isAnyPointerType() &&
9155 !SemaRef.Context.hasSameType(
9156 Diff.get()->getType(),
9158 Diff = SemaRef.PerformImplicitConversion(
9159 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
9160 AssignmentAction::Converting, /*AllowExplicit=*/true);
9161 }
9162 if (!Diff.isUsable())
9163 return std::make_pair(nullptr, nullptr);
9164
9165 if (*TestIsLessOp) {
9166 // MinExpr = Lower;
9167 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
9168 Diff = SemaRef.BuildBinOp(
9169 S, DefaultLoc, BO_Add,
9170 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
9171 Diff.get());
9172 if (!Diff.isUsable())
9173 return std::make_pair(nullptr, nullptr);
9174 } else {
9175 // MaxExpr = Upper;
9176 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
9177 Diff = SemaRef.BuildBinOp(
9178 S, DefaultLoc, BO_Sub,
9179 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
9180 Diff.get());
9181 if (!Diff.isUsable())
9182 return std::make_pair(nullptr, nullptr);
9183 }
9184
9185 // Convert to the original type.
9186 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
9187 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
9189 /*AllowExplicit=*/true);
9190 if (!Diff.isUsable())
9191 return std::make_pair(nullptr, nullptr);
9192
9193 Sema::TentativeAnalysisScope Trap(SemaRef);
9194 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
9195 if (!Diff.isUsable())
9196 return std::make_pair(nullptr, nullptr);
9197
9198 if (*TestIsLessOp)
9199 MaxExpr = Diff.get();
9200 else
9201 MinExpr = Diff.get();
9202
9203 return std::make_pair(MinExpr, MaxExpr);
9204}
9205
9206Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
9207 if (InitDependOnLC || CondDependOnLC)
9208 return Condition;
9209 return nullptr;
9210}
9211
9212Expr *OpenMPIterationSpaceChecker::buildPreCond(
9213 Scope *S, Expr *Cond,
9214 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9215 // Do not build a precondition when the condition/initialization is dependent
9216 // to prevent pessimistic early loop exit.
9217 // TODO: this can be improved by calculating min/max values but not sure that
9218 // it will be very effective.
9219 if (CondDependOnLC || InitDependOnLC)
9220 return SemaRef
9222 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
9223 SemaRef.Context.BoolTy, /*Action=*/AssignmentAction::Casting,
9224 /*AllowExplicit=*/true)
9225 .get();
9226
9227 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
9228 Sema::TentativeAnalysisScope Trap(SemaRef);
9229
9230 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9231 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9232 if (!NewLB.isUsable() || !NewUB.isUsable())
9233 return nullptr;
9234
9235 ExprResult CondExpr =
9236 SemaRef.BuildBinOp(S, DefaultLoc,
9237 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9238 : (TestIsStrictOp ? BO_GT : BO_GE),
9239 NewLB.get(), NewUB.get());
9240 if (CondExpr.isUsable()) {
9241 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
9242 SemaRef.Context.BoolTy))
9243 CondExpr = SemaRef.PerformImplicitConversion(
9244 CondExpr.get(), SemaRef.Context.BoolTy,
9245 /*Action=*/AssignmentAction::Casting,
9246 /*AllowExplicit=*/true);
9247 }
9248
9249 // Otherwise use original loop condition and evaluate it in runtime.
9250 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9251}
9252
9253/// Build reference expression to the counter be used for codegen.
9254DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9255 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9256 DSAStackTy &DSA) const {
9257 auto *VD = dyn_cast<VarDecl>(LCDecl);
9258 if (!VD) {
9259 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(LCDecl);
9261 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
9262 const DSAStackTy::DSAVarData Data =
9263 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
9264 // If the loop control decl is explicitly marked as private, do not mark it
9265 // as captured again.
9266 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
9267 Captures.insert(std::make_pair(LCRef, Ref));
9268 return Ref;
9269 }
9270 return cast<DeclRefExpr>(LCRef);
9271}
9272
9273Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9274 if (LCDecl && !LCDecl->isInvalidDecl()) {
9276 VarDecl *PrivateVar = buildVarDecl(
9277 SemaRef, DefaultLoc, Type, LCDecl->getName(),
9278 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9279 isa<VarDecl>(LCDecl)
9280 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
9281 : nullptr);
9282 if (PrivateVar->isInvalidDecl())
9283 return nullptr;
9284 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
9285 }
9286 return nullptr;
9287}
9288
9289/// Build initialization of the counter to be used for codegen.
9290Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9291
9292/// Build step of the counter be used for codegen.
9293Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9294
9295Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9296 Scope *S, Expr *Counter,
9297 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9298 Expr *Inc, OverloadedOperatorKind OOK) {
9299 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
9300 if (!Cnt)
9301 return nullptr;
9302 if (Inc) {
9303 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9304 "Expected only + or - operations for depend clauses.");
9305 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9306 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
9307 if (!Cnt)
9308 return nullptr;
9309 }
9310 QualType VarType = LCDecl->getType().getNonReferenceType();
9311 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9312 !SemaRef.getLangOpts().CPlusPlus)
9313 return nullptr;
9314 // Upper - Lower
9315 Expr *Upper =
9316 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9317 Expr *Lower =
9318 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9319 if (!Upper || !Lower)
9320 return nullptr;
9321
9322 ExprResult Diff = calculateNumIters(
9323 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9324 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9325 if (!Diff.isUsable())
9326 return nullptr;
9327
9328 return Diff.get();
9329}
9330} // namespace
9331
9333 Stmt *Init) {
9334 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9335 assert(Init && "Expected loop in canonical form.");
9336 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9337 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9338 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
9339 return;
9340
9341 DSAStack->loopStart();
9343 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9344 *DSAStack, ForLoc, EmptyDeclSet);
9345 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9346 if (ValueDecl *D = ISC.getLoopDecl()) {
9347 auto *VD = dyn_cast<VarDecl>(D);
9348 DeclRefExpr *PrivateRef = nullptr;
9349 if (!VD) {
9351 VD = Private;
9352 } else {
9353 PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(),
9354 /*WithInit=*/false);
9355 VD = cast<VarDecl>(PrivateRef->getDecl());
9356 }
9357 }
9358 DSAStack->addLoopControlVariable(D, VD);
9359 const Decl *LD = DSAStack->getPossiblyLoopCounter();
9360 if (LD != D->getCanonicalDecl()) {
9361 DSAStack->resetPossibleLoopCounter();
9362 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9363 SemaRef.MarkDeclarationsReferencedInExpr(buildDeclRefExpr(
9364 SemaRef, const_cast<VarDecl *>(Var),
9365 Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
9366 /*RefersToCapture=*/true));
9367 }
9368 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9369 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9370 // associated for-loop of a simd construct with just one associated
9371 // for-loop may be listed in a linear clause with a constant-linear-step
9372 // that is the increment of the associated for-loop. The loop iteration
9373 // variable(s) in the associated for-loop(s) of a for or parallel for
9374 // construct may be listed in a private or lastprivate clause.
9375 DSAStackTy::DSAVarData DVar =
9376 DSAStack->getTopDSA(D, /*FromParent=*/false);
9377 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9378 // is declared in the loop and it is predetermined as a private.
9379 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9380 OpenMPClauseKind PredeterminedCKind =
9382 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9383 : OMPC_private;
9384 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
9385 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9386 };
9387 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9388 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9389 (getLangOpts().OpenMP <= 45 ||
9390 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9392 IsOpenMPTaskloopDirective(DKind) ||
9394 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9395 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9396 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9397 unsigned OMPVersion = getLangOpts().OpenMP;
9398 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9399 << getOpenMPClauseNameForDiag(DVar.CKind)
9400 << getOpenMPDirectiveName(DKind, OMPVersion)
9401 << getOpenMPClauseNameForDiag(PredeterminedCKind);
9402 if (DVar.RefExpr == nullptr)
9403 DVar.CKind = PredeterminedCKind;
9404 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
9405 } else if (LoopDeclRefExpr) {
9406 // Make the loop iteration variable private (for worksharing
9407 // constructs), linear (for simd directives with the only one
9408 // associated loop) or lastprivate (for simd directives with several
9409 // collapsed or ordered loops).
9410 if (DVar.CKind == OMPC_unknown)
9411 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9412 }
9413 }
9414 }
9415 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9416}
9417
9418namespace {
9419// Utility for OpenMP doacross clause kind
9420class OMPDoacrossKind {
9421public:
9422 bool isSource(const OMPDoacrossClause *C) {
9423 return C->getDependenceType() == OMPC_DOACROSS_source ||
9424 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9425 }
9426 bool isSink(const OMPDoacrossClause *C) {
9427 return C->getDependenceType() == OMPC_DOACROSS_sink;
9428 }
9429 bool isSinkIter(const OMPDoacrossClause *C) {
9430 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9431 }
9432};
9433} // namespace
9434/// Called on a for stmt to check and extract its iteration space
9435/// for further processing (such as collapsing).
9437 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9438 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9439 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9440 Expr *OrderedLoopCountExpr,
9441 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9443 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9444 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9445 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9446 // OpenMP [2.9.1, Canonical Loop Form]
9447 // for (init-expr; test-expr; incr-expr) structured-block
9448 // for (range-decl: range-expr) structured-block
9449 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9450 S = CanonLoop->getLoopStmt();
9451 auto *For = dyn_cast_or_null<ForStmt>(S);
9452 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9453 // Ranged for is supported only in OpenMP 5.0.
9454 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9455 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
9456 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9457 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9458 << getOpenMPDirectiveName(DKind, OMPVersion) << TotalNestedLoopCount
9459 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9460 if (TotalNestedLoopCount > 1) {
9461 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9462 SemaRef.Diag(DSA.getConstructLoc(),
9463 diag::note_omp_collapse_ordered_expr)
9464 << 2 << CollapseLoopCountExpr->getSourceRange()
9465 << OrderedLoopCountExpr->getSourceRange();
9466 else if (CollapseLoopCountExpr)
9467 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9468 diag::note_omp_collapse_ordered_expr)
9469 << 0 << CollapseLoopCountExpr->getSourceRange();
9470 else if (OrderedLoopCountExpr)
9471 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9472 diag::note_omp_collapse_ordered_expr)
9473 << 1 << OrderedLoopCountExpr->getSourceRange();
9474 }
9475 return true;
9476 }
9477 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9478 "No loop body.");
9479 // Postpone analysis in dependent contexts for ranged for loops.
9480 if (CXXFor && SemaRef.CurContext->isDependentContext())
9481 return false;
9482
9483 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9484 For ? For->getForLoc() : CXXFor->getForLoc(),
9485 CollapsedLoopVarDecls);
9486
9487 // Check init.
9488 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9489 if (ISC.checkAndSetInit(Init))
9490 return true;
9491
9492 bool HasErrors = false;
9493
9494 // Check loop variable's type.
9495 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9496 // OpenMP [2.6, Canonical Loop Form]
9497 // Var is one of the following:
9498 // A variable of signed or unsigned integer type.
9499 // For C++, a variable of a random access iterator type.
9500 // For C, a variable of a pointer type.
9501 QualType VarType = LCDecl->getType().getNonReferenceType();
9502 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9503 !VarType->isPointerType() &&
9504 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9505 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9506 << SemaRef.getLangOpts().CPlusPlus;
9507 HasErrors = true;
9508 }
9509
9510 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9511 // a Construct
9512 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9513 // parallel for construct is (are) private.
9514 // The loop iteration variable in the associated for-loop of a simd
9515 // construct with just one associated for-loop is linear with a
9516 // constant-linear-step that is the increment of the associated for-loop.
9517 // Exclude loop var from the list of variables with implicitly defined data
9518 // sharing attributes.
9519 VarsWithImplicitDSA.erase(LCDecl);
9520
9521 assert((isOpenMPLoopDirective(DKind) ||
9523 "DSA for non-loop vars");
9524
9525 // Check test-expr.
9526 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9527
9528 // Check incr-expr.
9529 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9530 }
9531
9532 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9533 return HasErrors;
9534
9535 // Build the loop's iteration space representation.
9536 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9537 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9538 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9539 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9545 Captures);
9546 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9547 ISC.buildCounterVar(Captures, DSA);
9548 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9549 ISC.buildPrivateCounterVar();
9550 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9551 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9552 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9553 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9554 ISC.getConditionSrcRange();
9555 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9556 ISC.getIncrementSrcRange();
9557 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9558 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9559 ISC.isStrictTestOp();
9560 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9561 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9562 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9563 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9564 ISC.buildFinalCondition(DSA.getCurScope());
9565 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9566 ISC.doesInitDependOnLC();
9567 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9568 ISC.doesCondDependOnLC();
9569 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9570 ISC.getLoopDependentIdx();
9571
9572 HasErrors |=
9573 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9574 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9575 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9576 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9577 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9578 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9579 if (!HasErrors && DSA.isOrderedRegion()) {
9580 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9581 if (CurrentNestedLoopCount <
9582 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9583 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9584 CurrentNestedLoopCount,
9585 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9586 DSA.getOrderedRegionParam().second->setLoopCounter(
9587 CurrentNestedLoopCount,
9588 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9589 }
9590 }
9591 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9592 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9593 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9594 unsigned NumLoops =
9595 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9596 if (CurrentNestedLoopCount >= NumLoops) {
9597 // Erroneous case - clause has some problems.
9598 continue;
9599 }
9600 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9601 Pair.second.size() <= CurrentNestedLoopCount) {
9602 // Erroneous case - clause has some problems.
9603 DependC->setLoopData(CurrentNestedLoopCount, nullptr);
9604 continue;
9605 }
9606 OMPDoacrossKind ODK;
9607 if (DoacrossC && ODK.isSink(DoacrossC) &&
9608 Pair.second.size() <= CurrentNestedLoopCount) {
9609 // Erroneous case - clause has some problems.
9610 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
9611 continue;
9612 }
9613 Expr *CntValue;
9614 SourceLocation DepLoc =
9615 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9616 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9617 (DoacrossC && ODK.isSource(DoacrossC)))
9618 CntValue = ISC.buildOrderedLoopData(
9619 DSA.getCurScope(),
9620 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9621 DepLoc);
9622 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9623 Expr *Cnt = SemaRef
9625 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9626 .get();
9627 if (!Cnt)
9628 continue;
9629 // build CounterVar - 1
9630 Expr *Inc =
9631 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
9632 .get();
9633 CntValue = ISC.buildOrderedLoopData(
9634 DSA.getCurScope(),
9635 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9636 DepLoc, Inc, clang::OO_Minus);
9637 } else
9638 CntValue = ISC.buildOrderedLoopData(
9639 DSA.getCurScope(),
9640 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9641 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9642 Pair.second[CurrentNestedLoopCount].second);
9643 if (DependC)
9644 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9645 else
9646 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9647 }
9648 }
9649
9650 return HasErrors;
9651}
9652
9653/// Build 'VarRef = Start.
9654static ExprResult
9656 ExprResult Start, bool IsNonRectangularLB,
9657 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9658 // Build 'VarRef = Start.
9659 ExprResult NewStart = IsNonRectangularLB
9660 ? Start.get()
9661 : tryBuildCapture(SemaRef, Start.get(), Captures);
9662 if (!NewStart.isUsable())
9663 return ExprError();
9664 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9665 VarRef.get()->getType())) {
9666 NewStart = SemaRef.PerformImplicitConversion(
9667 NewStart.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9668 /*AllowExplicit=*/true);
9669 if (!NewStart.isUsable())
9670 return ExprError();
9671 }
9672
9674 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9675 return Init;
9676}
9677
9678/// Build 'VarRef = Start + Iter * Step'.
9680 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9681 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9682 bool IsNonRectangularLB,
9683 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9684 // Add parentheses (for debugging purposes only).
9685 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9686 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9687 !Step.isUsable())
9688 return ExprError();
9689
9690 ExprResult NewStep = Step;
9691 if (Captures)
9692 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9693 if (NewStep.isInvalid())
9694 return ExprError();
9696 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9697 if (!Update.isUsable())
9698 return ExprError();
9699
9700 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9701 // 'VarRef = Start (+|-) Iter * Step'.
9702 if (!Start.isUsable())
9703 return ExprError();
9704 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9705 if (!NewStart.isUsable())
9706 return ExprError();
9707 if (Captures && !IsNonRectangularLB)
9708 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9709 if (NewStart.isInvalid())
9710 return ExprError();
9711
9712 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9713 ExprResult SavedUpdate = Update;
9714 ExprResult UpdateVal;
9715 if (VarRef.get()->getType()->isOverloadableType() ||
9716 NewStart.get()->getType()->isOverloadableType() ||
9717 Update.get()->getType()->isOverloadableType()) {
9718 Sema::TentativeAnalysisScope Trap(SemaRef);
9719
9720 Update =
9721 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9722 if (Update.isUsable()) {
9723 UpdateVal =
9724 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9725 VarRef.get(), SavedUpdate.get());
9726 if (UpdateVal.isUsable()) {
9727 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9728 UpdateVal.get());
9729 }
9730 }
9731 }
9732
9733 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9734 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9735 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9736 NewStart.get(), SavedUpdate.get());
9737 if (!Update.isUsable())
9738 return ExprError();
9739
9740 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9741 VarRef.get()->getType())) {
9743 Update.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9744 /*AllowExplicit=*/true);
9745 if (!Update.isUsable())
9746 return ExprError();
9747 }
9748
9749 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9750 }
9751 return Update;
9752}
9753
9754/// Convert integer expression \a E to make it have at least \a Bits
9755/// bits.
9756static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9757 if (E == nullptr)
9758 return ExprError();
9759 ASTContext &C = SemaRef.Context;
9760 QualType OldType = E->getType();
9761 unsigned HasBits = C.getTypeSize(OldType);
9762 if (HasBits >= Bits)
9763 return ExprResult(E);
9764 // OK to convert to signed, because new type has more bits than old.
9765 QualType NewType = C.getIntTypeForBitwidth(Bits, /*Signed=*/true);
9766 return SemaRef.PerformImplicitConversion(
9767 E, NewType, AssignmentAction::Converting, /*AllowExplicit=*/true);
9768}
9769
9770/// Check if the given expression \a E is a constant integer that fits
9771/// into \a Bits bits.
9772static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9773 if (E == nullptr)
9774 return false;
9775 if (std::optional<llvm::APSInt> Result =
9776 E->getIntegerConstantExpr(SemaRef.Context))
9777 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9778 return false;
9779}
9780
9781/// Build preinits statement for the given declarations.
9783 MutableArrayRef<Decl *> PreInits) {
9784 if (!PreInits.empty()) {
9785 return new (Context) DeclStmt(
9786 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9788 }
9789 return nullptr;
9790}
9791
9792/// Append the \p Item or the content of a CompoundStmt to the list \p
9793/// TargetList.
9794///
9795/// A CompoundStmt is used as container in case multiple statements need to be
9796/// stored in lieu of using an explicit list. Flattening is necessary because
9797/// contained DeclStmts need to be visible after the execution of the list. Used
9798/// for OpenMP pre-init declarations/statements.
9800 Stmt *Item) {
9801 // nullptr represents an empty list.
9802 if (!Item)
9803 return;
9804
9805 if (auto *CS = dyn_cast<CompoundStmt>(Item))
9806 llvm::append_range(TargetList, CS->body());
9807 else
9808 TargetList.push_back(Item);
9809}
9810
9811/// Build preinits statement for the given declarations.
9812static Stmt *
9814 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9815 if (!Captures.empty()) {
9816 SmallVector<Decl *, 16> PreInits;
9817 for (const auto &Pair : Captures)
9818 PreInits.push_back(Pair.second->getDecl());
9819 return buildPreInits(Context, PreInits);
9820 }
9821 return nullptr;
9822}
9823
9824/// Build pre-init statement for the given statements.
9825static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
9826 if (PreInits.empty())
9827 return nullptr;
9828
9829 SmallVector<Stmt *> Stmts;
9830 for (Stmt *S : PreInits)
9831 appendFlattenedStmtList(Stmts, S);
9832 return CompoundStmt::Create(Context, PreInits, FPOptionsOverride(), {}, {});
9833}
9834
9835/// Build postupdate expression for the given list of postupdates expressions.
9836static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9837 Expr *PostUpdate = nullptr;
9838 if (!PostUpdates.empty()) {
9839 for (Expr *E : PostUpdates) {
9840 Expr *ConvE = S.BuildCStyleCastExpr(
9841 E->getExprLoc(),
9843 E->getExprLoc(), E)
9844 .get();
9845 PostUpdate = PostUpdate
9846 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9847 PostUpdate, ConvE)
9848 .get()
9849 : ConvE;
9850 }
9851 }
9852 return PostUpdate;
9853}
9854
9855/// Look for variables declared in the body parts of a for-loop nest. Used
9856/// for verifying loop nest structure before performing a loop collapse
9857/// operation.
9859 int NestingDepth = 0;
9860 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9861
9862public:
9863 explicit ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl *> &VD)
9864 : VarDecls(VD) {}
9865
9866 bool VisitForStmt(ForStmt *F) override {
9867 ++NestingDepth;
9868 TraverseStmt(F->getBody());
9869 --NestingDepth;
9870 return false;
9871 }
9872
9874 ++NestingDepth;
9875 TraverseStmt(RF->getBody());
9876 --NestingDepth;
9877 return false;
9878 }
9879
9880 bool VisitVarDecl(VarDecl *D) override {
9881 Decl *C = D->getCanonicalDecl();
9882 if (NestingDepth > 0)
9883 VarDecls.insert(C);
9884 return true;
9885 }
9886};
9887
9888/// Called on a for stmt to check itself and nested loops (if any).
9889/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9890/// number of collapsed loops otherwise.
9891static unsigned
9892checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9893 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9894 DSAStackTy &DSA,
9895 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9896 OMPLoopBasedDirective::HelperExprs &Built) {
9897 // If either of the loop expressions exist and contain errors, we bail out
9898 // early because diagnostics have already been emitted and we can't reliably
9899 // check more about the loop.
9900 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->containsErrors()) ||
9901 (OrderedLoopCountExpr && OrderedLoopCountExpr->containsErrors()))
9902 return 0;
9903
9904 unsigned NestedLoopCount = 1;
9905 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9907 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopVarDecls;
9908
9909 if (CollapseLoopCountExpr) {
9910 // Found 'collapse' clause - calculate collapse number.
9911 Expr::EvalResult Result;
9912 if (!CollapseLoopCountExpr->isValueDependent() &&
9913 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9914 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9915
9916 ForVarDeclFinder FVDF{CollapsedLoopVarDecls};
9917 FVDF.TraverseStmt(AStmt);
9918 } else {
9919 Built.clear(/*Size=*/1);
9920 return 1;
9921 }
9922 }
9923 unsigned OrderedLoopCount = 1;
9924 if (OrderedLoopCountExpr) {
9925 // Found 'ordered' clause - calculate collapse number.
9926 Expr::EvalResult EVResult;
9927 if (!OrderedLoopCountExpr->isValueDependent() &&
9928 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9929 SemaRef.getASTContext())) {
9930 llvm::APSInt Result = EVResult.Val.getInt();
9931 if (Result.getLimitedValue() < NestedLoopCount) {
9932 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9933 diag::err_omp_wrong_ordered_loop_count)
9934 << OrderedLoopCountExpr->getSourceRange();
9935 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9936 diag::note_collapse_loop_count)
9937 << CollapseLoopCountExpr->getSourceRange();
9938 }
9939 OrderedLoopCount = Result.getLimitedValue();
9940 } else {
9941 Built.clear(/*Size=*/1);
9942 return 1;
9943 }
9944 }
9945 // This is helper routine for loop directives (e.g., 'for', 'simd',
9946 // 'for simd', etc.).
9947 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9948 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9949 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9950 if (!OMPLoopBasedDirective::doForAllLoops(
9951 AStmt->IgnoreContainers(
9953 SupportsNonPerfectlyNested, NumLoops,
9954 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9955 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9956 &IterSpaces, &Captures,
9957 &CollapsedLoopVarDecls](unsigned Cnt, Stmt *CurStmt) {
9959 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9960 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9961 VarsWithImplicitDSA, IterSpaces, Captures,
9962 CollapsedLoopVarDecls))
9963 return true;
9964 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9965 IterSpaces[Cnt].CounterVar) {
9966 // Handle initialization of captured loop iterator variables.
9967 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9968 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9969 Captures[DRE] = DRE;
9970 }
9971 }
9972 return false;
9973 },
9974 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9975 Stmt *DependentPreInits = Transform->getPreInits();
9976 if (!DependentPreInits)
9977 return;
9978
9979 // Search for pre-init declared variables that need to be captured
9980 // to be referenceable inside the directive.
9981 SmallVector<Stmt *> Constituents;
9982 appendFlattenedStmtList(Constituents, DependentPreInits);
9983 for (Stmt *S : Constituents) {
9984 if (auto *DC = dyn_cast<DeclStmt>(S)) {
9985 for (Decl *C : DC->decls()) {
9986 auto *D = cast<VarDecl>(C);
9988 SemaRef, D, D->getType().getNonReferenceType(),
9989 cast<OMPExecutableDirective>(Transform->getDirective())
9990 ->getBeginLoc());
9991 Captures[Ref] = Ref;
9992 }
9993 }
9994 }
9995 }))
9996 return 0;
9997
9998 Built.clear(/*size=*/NestedLoopCount);
9999
10000 if (SemaRef.CurContext->isDependentContext())
10001 return NestedLoopCount;
10002
10003 // An example of what is generated for the following code:
10004 //
10005 // #pragma omp simd collapse(2) ordered(2)
10006 // for (i = 0; i < NI; ++i)
10007 // for (k = 0; k < NK; ++k)
10008 // for (j = J0; j < NJ; j+=2) {
10009 // <loop body>
10010 // }
10011 //
10012 // We generate the code below.
10013 // Note: the loop body may be outlined in CodeGen.
10014 // Note: some counters may be C++ classes, operator- is used to find number of
10015 // iterations and operator+= to calculate counter value.
10016 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
10017 // or i64 is currently supported).
10018 //
10019 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
10020 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
10021 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
10022 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
10023 // // similar updates for vars in clauses (e.g. 'linear')
10024 // <loop body (using local i and j)>
10025 // }
10026 // i = NI; // assign final values of counters
10027 // j = NJ;
10028 //
10029
10030 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
10031 // the iteration counts of the collapsed for loops.
10032 // Precondition tests if there is at least one iteration (all conditions are
10033 // true).
10034 auto PreCond = ExprResult(IterSpaces[0].PreCond);
10035 Expr *N0 = IterSpaces[0].NumIterations;
10036 ExprResult LastIteration32 = widenIterationCount(
10037 /*Bits=*/32,
10038 SemaRef
10039 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
10041 /*AllowExplicit=*/true)
10042 .get(),
10043 SemaRef);
10044 ExprResult LastIteration64 = widenIterationCount(
10045 /*Bits=*/64,
10046 SemaRef
10047 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
10049 /*AllowExplicit=*/true)
10050 .get(),
10051 SemaRef);
10052
10053 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
10054 return NestedLoopCount;
10055
10056 ASTContext &C = SemaRef.Context;
10057 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
10058
10059 Scope *CurScope = DSA.getCurScope();
10060 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
10061 if (PreCond.isUsable()) {
10062 PreCond =
10063 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
10064 PreCond.get(), IterSpaces[Cnt].PreCond);
10065 }
10066 Expr *N = IterSpaces[Cnt].NumIterations;
10067 SourceLocation Loc = N->getExprLoc();
10068 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
10069 if (LastIteration32.isUsable())
10070 LastIteration32 = SemaRef.BuildBinOp(
10071 CurScope, Loc, BO_Mul, LastIteration32.get(),
10072 SemaRef
10075 /*AllowExplicit=*/true)
10076 .get());
10077 if (LastIteration64.isUsable())
10078 LastIteration64 = SemaRef.BuildBinOp(
10079 CurScope, Loc, BO_Mul, LastIteration64.get(),
10080 SemaRef
10083 /*AllowExplicit=*/true)
10084 .get());
10085 }
10086
10087 // Choose either the 32-bit or 64-bit version.
10088 ExprResult LastIteration = LastIteration64;
10089 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
10090 (LastIteration32.isUsable() &&
10091 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
10092 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
10093 fitsInto(
10094 /*Bits=*/32,
10095 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
10096 LastIteration64.get(), SemaRef))))
10097 LastIteration = LastIteration32;
10098 QualType VType = LastIteration.get()->getType();
10099 QualType RealVType = VType;
10100 QualType StrideVType = VType;
10101 if (isOpenMPTaskLoopDirective(DKind)) {
10102 VType =
10103 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
10104 StrideVType =
10105 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
10106 }
10107
10108 if (!LastIteration.isUsable())
10109 return 0;
10110
10111 // Save the number of iterations.
10112 ExprResult NumIterations = LastIteration;
10113 {
10114 LastIteration = SemaRef.BuildBinOp(
10115 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
10116 LastIteration.get(),
10117 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
10118 if (!LastIteration.isUsable())
10119 return 0;
10120 }
10121
10122 // Calculate the last iteration number beforehand instead of doing this on
10123 // each iteration. Do not do this if the number of iterations may be kfold-ed.
10124 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
10125 ExprResult CalcLastIteration;
10126 if (!IsConstant) {
10127 ExprResult SaveRef =
10128 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
10129 LastIteration = SaveRef;
10130
10131 // Prepare SaveRef + 1.
10132 NumIterations = SemaRef.BuildBinOp(
10133 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
10134 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
10135 if (!NumIterations.isUsable())
10136 return 0;
10137 }
10138
10139 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
10140
10141 // Build variables passed into runtime, necessary for worksharing directives.
10142 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
10147 // Lower bound variable, initialized with zero.
10148 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
10149 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
10150 SemaRef.AddInitializerToDecl(LBDecl,
10151 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10152 /*DirectInit=*/false);
10153
10154 // Upper bound variable, initialized with last iteration number.
10155 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
10156 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
10157 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
10158 /*DirectInit=*/false);
10159
10160 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
10161 // This will be used to implement clause 'lastprivate'.
10162 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
10163 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
10164 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
10165 SemaRef.AddInitializerToDecl(ILDecl,
10166 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10167 /*DirectInit=*/false);
10168
10169 // Stride variable returned by runtime (we initialize it to 1 by default).
10170 VarDecl *STDecl =
10171 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
10172 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
10173 SemaRef.AddInitializerToDecl(STDecl,
10174 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
10175 /*DirectInit=*/false);
10176
10177 // Build expression: UB = min(UB, LastIteration)
10178 // It is necessary for CodeGen of directives with static scheduling.
10179 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
10180 UB.get(), LastIteration.get());
10181 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10182 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
10183 LastIteration.get(), UB.get());
10184 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
10185 CondOp.get());
10186 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue=*/false);
10187
10188 // If we have a combined directive that combines 'distribute', 'for' or
10189 // 'simd' we need to be able to access the bounds of the schedule of the
10190 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
10191 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
10193 // Lower bound variable, initialized with zero.
10194 VarDecl *CombLBDecl =
10195 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
10196 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
10197 SemaRef.AddInitializerToDecl(
10198 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10199 /*DirectInit=*/false);
10200
10201 // Upper bound variable, initialized with last iteration number.
10202 VarDecl *CombUBDecl =
10203 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
10204 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
10205 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
10206 /*DirectInit=*/false);
10207
10208 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
10209 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
10210 ExprResult CombCondOp =
10211 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
10212 LastIteration.get(), CombUB.get());
10213 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
10214 CombCondOp.get());
10215 CombEUB =
10216 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue=*/false);
10217
10218 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
10219 // We expect to have at least 2 more parameters than the 'parallel'
10220 // directive does - the lower and upper bounds of the previous schedule.
10221 assert(CD->getNumParams() >= 4 &&
10222 "Unexpected number of parameters in loop combined directive");
10223
10224 // Set the proper type for the bounds given what we learned from the
10225 // enclosed loops.
10226 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
10227 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
10228
10229 // Previous lower and upper bounds are obtained from the region
10230 // parameters.
10231 PrevLB =
10232 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
10233 PrevUB =
10234 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
10235 }
10236 }
10237
10238 // Build the iteration variable and its initialization before loop.
10239 ExprResult IV;
10240 ExprResult Init, CombInit;
10241 {
10242 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
10243 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
10244 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
10249 ? LB.get()
10250 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10251 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
10252 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue=*/false);
10253
10255 Expr *CombRHS =
10260 ? CombLB.get()
10261 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10262 CombInit =
10263 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
10264 CombInit =
10265 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue=*/false);
10266 }
10267 }
10268
10269 bool UseStrictCompare =
10270 RealVType->hasUnsignedIntegerRepresentation() &&
10271 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
10272 return LIS.IsStrictCompare;
10273 });
10274 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10275 // unsigned IV)) for worksharing loops.
10276 SourceLocation CondLoc = AStmt->getBeginLoc();
10277 Expr *BoundUB = UB.get();
10278 if (UseStrictCompare) {
10279 BoundUB =
10280 SemaRef
10281 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10282 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10283 .get();
10284 BoundUB =
10285 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue=*/false).get();
10286 }
10292 ? SemaRef.BuildBinOp(CurScope, CondLoc,
10293 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
10294 BoundUB)
10295 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10296 NumIterations.get());
10297 ExprResult CombDistCond;
10299 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10300 NumIterations.get());
10301 }
10302
10303 ExprResult CombCond;
10305 Expr *BoundCombUB = CombUB.get();
10306 if (UseStrictCompare) {
10307 BoundCombUB =
10308 SemaRef
10309 .BuildBinOp(
10310 CurScope, CondLoc, BO_Add, BoundCombUB,
10311 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10312 .get();
10313 BoundCombUB =
10314 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue=*/false)
10315 .get();
10316 }
10317 CombCond =
10318 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10319 IV.get(), BoundCombUB);
10320 }
10321 // Loop increment (IV = IV + 1)
10322 SourceLocation IncLoc = AStmt->getBeginLoc();
10323 ExprResult Inc =
10324 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
10325 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
10326 if (!Inc.isUsable())
10327 return 0;
10328 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
10329 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue=*/false);
10330 if (!Inc.isUsable())
10331 return 0;
10332
10333 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10334 // Used for directives with static scheduling.
10335 // In combined construct, add combined version that use CombLB and CombUB
10336 // base variables for the update
10337 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10342 // LB + ST
10343 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
10344 if (!NextLB.isUsable())
10345 return 0;
10346 // LB = LB + ST
10347 NextLB =
10348 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
10349 NextLB =
10350 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue=*/false);
10351 if (!NextLB.isUsable())
10352 return 0;
10353 // UB + ST
10354 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
10355 if (!NextUB.isUsable())
10356 return 0;
10357 // UB = UB + ST
10358 NextUB =
10359 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
10360 NextUB =
10361 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue=*/false);
10362 if (!NextUB.isUsable())
10363 return 0;
10365 CombNextLB =
10366 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
10367 if (!NextLB.isUsable())
10368 return 0;
10369 // LB = LB + ST
10370 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
10371 CombNextLB.get());
10372 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
10373 /*DiscardedValue=*/false);
10374 if (!CombNextLB.isUsable())
10375 return 0;
10376 // UB + ST
10377 CombNextUB =
10378 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
10379 if (!CombNextUB.isUsable())
10380 return 0;
10381 // UB = UB + ST
10382 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
10383 CombNextUB.get());
10384 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
10385 /*DiscardedValue=*/false);
10386 if (!CombNextUB.isUsable())
10387 return 0;
10388 }
10389 }
10390
10391 // Create increment expression for distribute loop when combined in a same
10392 // directive with for as IV = IV + ST; ensure upper bound expression based
10393 // on PrevUB instead of NumIterations - used to implement 'for' when found
10394 // in combination with 'distribute', like in 'distribute parallel for'
10395 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10396 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10398 DistCond = SemaRef.BuildBinOp(
10399 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10400 assert(DistCond.isUsable() && "distribute cond expr was not built");
10401
10402 DistInc =
10403 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10404 assert(DistInc.isUsable() && "distribute inc expr was not built");
10405 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10406 DistInc.get());
10407 DistInc =
10408 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue=*/false);
10409 assert(DistInc.isUsable() && "distribute inc expr was not built");
10410
10411 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10412 // construct
10413 ExprResult NewPrevUB = PrevUB;
10414 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10415 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10416 PrevUB.get()->getType())) {
10417 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10418 DistEUBLoc,
10420 DistEUBLoc, NewPrevUB.get());
10421 if (!NewPrevUB.isUsable())
10422 return 0;
10423 }
10424 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10425 UB.get(), NewPrevUB.get());
10426 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10427 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10428 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10429 CondOp.get());
10430 PrevEUB =
10431 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue=*/false);
10432
10433 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10434 // parallel for is in combination with a distribute directive with
10435 // schedule(static, 1)
10436 Expr *BoundPrevUB = PrevUB.get();
10437 if (UseStrictCompare) {
10438 BoundPrevUB =
10439 SemaRef
10440 .BuildBinOp(
10441 CurScope, CondLoc, BO_Add, BoundPrevUB,
10442 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10443 .get();
10444 BoundPrevUB =
10445 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue=*/false)
10446 .get();
10447 }
10448 ParForInDistCond =
10449 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10450 IV.get(), BoundPrevUB);
10451 }
10452
10453 // Build updates and final values of the loop counters.
10454 bool HasErrors = false;
10455 Built.Counters.resize(NestedLoopCount);
10456 Built.Inits.resize(NestedLoopCount);
10457 Built.Updates.resize(NestedLoopCount);
10458 Built.Finals.resize(NestedLoopCount);
10459 Built.DependentCounters.resize(NestedLoopCount);
10460 Built.DependentInits.resize(NestedLoopCount);
10461 Built.FinalsConditions.resize(NestedLoopCount);
10462 {
10463 // We implement the following algorithm for obtaining the
10464 // original loop iteration variable values based on the
10465 // value of the collapsed loop iteration variable IV.
10466 //
10467 // Let n+1 be the number of collapsed loops in the nest.
10468 // Iteration variables (I0, I1, .... In)
10469 // Iteration counts (N0, N1, ... Nn)
10470 //
10471 // Acc = IV;
10472 //
10473 // To compute Ik for loop k, 0 <= k <= n, generate:
10474 // Prod = N(k+1) * N(k+2) * ... * Nn;
10475 // Ik = Acc / Prod;
10476 // Acc -= Ik * Prod;
10477 //
10478 ExprResult Acc = IV;
10479 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10480 LoopIterationSpace &IS = IterSpaces[Cnt];
10481 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10482 ExprResult Iter;
10483
10484 // Compute prod
10485 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10486 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10487 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10488 IterSpaces[K].NumIterations);
10489
10490 // Iter = Acc / Prod
10491 // If there is at least one more inner loop to avoid
10492 // multiplication by 1.
10493 if (Cnt + 1 < NestedLoopCount)
10494 Iter =
10495 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10496 else
10497 Iter = Acc;
10498 if (!Iter.isUsable()) {
10499 HasErrors = true;
10500 break;
10501 }
10502
10503 // Update Acc:
10504 // Acc -= Iter * Prod
10505 // Check if there is at least one more inner loop to avoid
10506 // multiplication by 1.
10507 if (Cnt + 1 < NestedLoopCount)
10508 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10509 Prod.get());
10510 else
10511 Prod = Iter;
10512 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10513
10514 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10515 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10516 DeclRefExpr *CounterVar = buildDeclRefExpr(
10517 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10518 /*RefersToCapture=*/true);
10520 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10521 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10522 if (!Init.isUsable()) {
10523 HasErrors = true;
10524 break;
10525 }
10527 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10528 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10529 if (!Update.isUsable()) {
10530 HasErrors = true;
10531 break;
10532 }
10533
10534 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10535 ExprResult Final =
10536 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10537 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10538 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10539 if (!Final.isUsable()) {
10540 HasErrors = true;
10541 break;
10542 }
10543
10544 if (!Update.isUsable() || !Final.isUsable()) {
10545 HasErrors = true;
10546 break;
10547 }
10548 // Save results
10549 Built.Counters[Cnt] = IS.CounterVar;
10550 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10551 Built.Inits[Cnt] = Init.get();
10552 Built.Updates[Cnt] = Update.get();
10553 Built.Finals[Cnt] = Final.get();
10554 Built.DependentCounters[Cnt] = nullptr;
10555 Built.DependentInits[Cnt] = nullptr;
10556 Built.FinalsConditions[Cnt] = nullptr;
10557 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10558 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10559 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10560 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10561 }
10562 }
10563 }
10564
10565 if (HasErrors)
10566 return 0;
10567
10568 // Save results
10569 Built.IterationVarRef = IV.get();
10570 Built.LastIteration = LastIteration.get();
10571 Built.NumIterations = NumIterations.get();
10572 Built.CalcLastIteration = SemaRef
10573 .ActOnFinishFullExpr(CalcLastIteration.get(),
10574 /*DiscardedValue=*/false)
10575 .get();
10576 Built.PreCond = PreCond.get();
10577 Built.PreInits = buildPreInits(C, Captures);
10578 Built.Cond = Cond.get();
10579 Built.Init = Init.get();
10580 Built.Inc = Inc.get();
10581 Built.LB = LB.get();
10582 Built.UB = UB.get();
10583 Built.IL = IL.get();
10584 Built.ST = ST.get();
10585 Built.EUB = EUB.get();
10586 Built.NLB = NextLB.get();
10587 Built.NUB = NextUB.get();
10588 Built.PrevLB = PrevLB.get();
10589 Built.PrevUB = PrevUB.get();
10590 Built.DistInc = DistInc.get();
10591 Built.PrevEUB = PrevEUB.get();
10592 Built.DistCombinedFields.LB = CombLB.get();
10593 Built.DistCombinedFields.UB = CombUB.get();
10594 Built.DistCombinedFields.EUB = CombEUB.get();
10595 Built.DistCombinedFields.Init = CombInit.get();
10596 Built.DistCombinedFields.Cond = CombCond.get();
10597 Built.DistCombinedFields.NLB = CombNextLB.get();
10598 Built.DistCombinedFields.NUB = CombNextUB.get();
10599 Built.DistCombinedFields.DistCond = CombDistCond.get();
10600 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10601
10602 return NestedLoopCount;
10603}
10604
10606 auto CollapseClauses =
10607 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10608 if (CollapseClauses.begin() != CollapseClauses.end())
10609 return (*CollapseClauses.begin())->getNumForLoops();
10610 return nullptr;
10611}
10612
10614 auto OrderedClauses =
10615 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10616 if (OrderedClauses.begin() != OrderedClauses.end())
10617 return (*OrderedClauses.begin())->getNumForLoops();
10618 return nullptr;
10619}
10620
10622 const ArrayRef<OMPClause *> Clauses) {
10623 const OMPSafelenClause *Safelen = nullptr;
10624 const OMPSimdlenClause *Simdlen = nullptr;
10625
10626 for (const OMPClause *Clause : Clauses) {
10627 if (Clause->getClauseKind() == OMPC_safelen)
10628 Safelen = cast<OMPSafelenClause>(Clause);
10629 else if (Clause->getClauseKind() == OMPC_simdlen)
10630 Simdlen = cast<OMPSimdlenClause>(Clause);
10631 if (Safelen && Simdlen)
10632 break;
10633 }
10634
10635 if (Simdlen && Safelen) {
10636 const Expr *SimdlenLength = Simdlen->getSimdlen();
10637 const Expr *SafelenLength = Safelen->getSafelen();
10638 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10639 SimdlenLength->isInstantiationDependent() ||
10640 SimdlenLength->containsUnexpandedParameterPack())
10641 return false;
10642 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10643 SafelenLength->isInstantiationDependent() ||
10644 SafelenLength->containsUnexpandedParameterPack())
10645 return false;
10646 Expr::EvalResult SimdlenResult, SafelenResult;
10647 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10648 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10649 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10650 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10651 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10652 // If both simdlen and safelen clauses are specified, the value of the
10653 // simdlen parameter must be less than or equal to the value of the safelen
10654 // parameter.
10655 if (SimdlenRes > SafelenRes) {
10656 S.Diag(SimdlenLength->getExprLoc(),
10657 diag::err_omp_wrong_simdlen_safelen_values)
10658 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10659 return true;
10660 }
10661 }
10662 return false;
10663}
10664
10666 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10667 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10668 if (!AStmt)
10669 return StmtError();
10670
10671 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_simd, AStmt);
10672
10673 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10674 OMPLoopBasedDirective::HelperExprs B;
10675 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10676 // define the nested loops number.
10677 unsigned NestedLoopCount = checkOpenMPLoop(
10678 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10679 CS, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10680 if (NestedLoopCount == 0)
10681 return StmtError();
10682
10683 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10684 return StmtError();
10685
10687 return StmtError();
10688
10689 auto *SimdDirective = OMPSimdDirective::Create(
10690 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10691 return SimdDirective;
10692}
10693
10695 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10696 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10697 if (!AStmt)
10698 return StmtError();
10699
10700 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10701 OMPLoopBasedDirective::HelperExprs B;
10702 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10703 // define the nested loops number.
10704 unsigned NestedLoopCount = checkOpenMPLoop(
10705 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10706 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10707 if (NestedLoopCount == 0)
10708 return StmtError();
10709
10710 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10711 return StmtError();
10712
10713 auto *ForDirective = OMPForDirective::Create(
10714 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10715 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10716 return ForDirective;
10717}
10718
10720 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10721 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10722 if (!AStmt)
10723 return StmtError();
10724
10725 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_for_simd, AStmt);
10726
10727 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10728 OMPLoopBasedDirective::HelperExprs B;
10729 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10730 // define the nested loops number.
10731 unsigned NestedLoopCount =
10732 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10733 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10734 VarsWithImplicitDSA, B);
10735 if (NestedLoopCount == 0)
10736 return StmtError();
10737
10738 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10739 return StmtError();
10740
10742 return StmtError();
10743
10744 return OMPForSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
10745 NestedLoopCount, Clauses, AStmt, B);
10746}
10747
10749 Stmt *AStmt, DSAStackTy *Stack) {
10750 if (!AStmt)
10751 return true;
10752
10753 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10754 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
10755 auto BaseStmt = AStmt;
10756 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10757 BaseStmt = CS->getCapturedStmt();
10758 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10759 auto S = C->children();
10760 if (S.begin() == S.end())
10761 return true;
10762 // All associated statements must be '#pragma omp section' except for
10763 // the first one.
10764 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10765 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10766 if (SectionStmt)
10767 SemaRef.Diag(SectionStmt->getBeginLoc(),
10768 diag::err_omp_sections_substmt_not_section)
10769 << getOpenMPDirectiveName(DKind, OMPVersion);
10770 return true;
10771 }
10772 cast<OMPSectionDirective>(SectionStmt)
10773 ->setHasCancel(Stack->isCancelRegion());
10774 }
10775 } else {
10776 SemaRef.Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10777 << getOpenMPDirectiveName(DKind, OMPVersion);
10778 return true;
10779 }
10780 return false;
10781}
10782
10785 Stmt *AStmt, SourceLocation StartLoc,
10786 SourceLocation EndLoc) {
10787 if (checkSectionsDirective(SemaRef, OMPD_sections, AStmt, DSAStack))
10788 return StmtError();
10789
10790 SemaRef.setFunctionHasBranchProtectedScope();
10791
10792 return OMPSectionsDirective::Create(
10793 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10794 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10795}
10796
10798 SourceLocation StartLoc,
10799 SourceLocation EndLoc) {
10800 if (!AStmt)
10801 return StmtError();
10802
10803 SemaRef.setFunctionHasBranchProtectedScope();
10804 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10805
10806 return OMPSectionDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt,
10807 DSAStack->isCancelRegion());
10808}
10809
10811 E = E->IgnoreParenCasts()->IgnoreImplicit();
10812 if (auto *CE = dyn_cast<CallExpr>(E))
10813 if (CE->getDirectCallee())
10814 return E;
10815 return nullptr;
10816}
10817
10820 Stmt *AStmt, SourceLocation StartLoc,
10821 SourceLocation EndLoc) {
10822 if (!AStmt)
10823 return StmtError();
10824
10825 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10826
10827 // 5.1 OpenMP
10828 // expression-stmt : an expression statement with one of the following forms:
10829 // expression = target-call ( [expression-list] );
10830 // target-call ( [expression-list] );
10831
10832 SourceLocation TargetCallLoc;
10833
10834 if (!SemaRef.CurContext->isDependentContext()) {
10835 Expr *TargetCall = nullptr;
10836
10837 auto *E = dyn_cast<Expr>(S);
10838 if (!E) {
10839 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10840 return StmtError();
10841 }
10842
10843 E = E->IgnoreParenCasts()->IgnoreImplicit();
10844
10845 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10846 if (BO->getOpcode() == BO_Assign)
10847 TargetCall = getDirectCallExpr(BO->getRHS());
10848 } else {
10849 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10850 if (COCE->getOperator() == OO_Equal)
10851 TargetCall = getDirectCallExpr(COCE->getArg(1));
10852 if (!TargetCall)
10853 TargetCall = getDirectCallExpr(E);
10854 }
10855 if (!TargetCall) {
10856 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10857 return StmtError();
10858 }
10859 TargetCallLoc = TargetCall->getExprLoc();
10860 }
10861
10862 SemaRef.setFunctionHasBranchProtectedScope();
10863
10864 return OMPDispatchDirective::Create(getASTContext(), StartLoc, EndLoc,
10865 Clauses, AStmt, TargetCallLoc);
10866}
10867
10870 DSAStackTy *Stack) {
10871 bool ErrorFound = false;
10872 for (OMPClause *C : Clauses) {
10873 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10874 for (Expr *RefExpr : LPC->varlist()) {
10875 SourceLocation ELoc;
10876 SourceRange ERange;
10877 Expr *SimpleRefExpr = RefExpr;
10878 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10879 if (ValueDecl *D = Res.first) {
10880 auto &&Info = Stack->isLoopControlVariable(D);
10881 if (!Info.first) {
10882 unsigned OMPVersion = S.getLangOpts().OpenMP;
10883 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10884 << getOpenMPDirectiveName(K, OMPVersion);
10885 ErrorFound = true;
10886 }
10887 }
10888 }
10889 }
10890 }
10891 return ErrorFound;
10892}
10893
10895 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10896 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10897 if (!AStmt)
10898 return StmtError();
10899
10900 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10901 // A list item may not appear in a lastprivate clause unless it is the
10902 // loop iteration variable of a loop that is associated with the construct.
10903 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack))
10904 return StmtError();
10905
10906 setBranchProtectedScope(SemaRef, OMPD_loop, AStmt);
10907
10908 OMPLoopDirective::HelperExprs B;
10909 // In presence of clause 'collapse', it will define the nested loops number.
10910 unsigned NestedLoopCount = checkOpenMPLoop(
10911 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10912 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10913 if (NestedLoopCount == 0)
10914 return StmtError();
10915
10916 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10917 "omp loop exprs were not built");
10918
10919 return OMPGenericLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
10920 NestedLoopCount, Clauses, AStmt, B);
10921}
10922
10924 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10925 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10926 if (!AStmt)
10927 return StmtError();
10928
10929 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10930 // A list item may not appear in a lastprivate clause unless it is the
10931 // loop iteration variable of a loop that is associated with the construct.
10932 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack))
10933 return StmtError();
10934
10935 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_teams_loop, AStmt);
10936
10937 OMPLoopDirective::HelperExprs B;
10938 // In presence of clause 'collapse', it will define the nested loops number.
10939 unsigned NestedLoopCount =
10940 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10941 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10942 VarsWithImplicitDSA, B);
10943 if (NestedLoopCount == 0)
10944 return StmtError();
10945
10946 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10947 "omp loop exprs were not built");
10948
10949 DSAStack->setParentTeamsRegionLoc(StartLoc);
10950
10952 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10953}
10954
10956 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10957 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10958 if (!AStmt)
10959 return StmtError();
10960
10961 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10962 // A list item may not appear in a lastprivate clause unless it is the
10963 // loop iteration variable of a loop that is associated with the construct.
10964 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop,
10965 DSAStack))
10966 return StmtError();
10967
10968 CapturedStmt *CS =
10969 setBranchProtectedScope(SemaRef, OMPD_target_teams_loop, AStmt);
10970
10971 OMPLoopDirective::HelperExprs B;
10972 // In presence of clause 'collapse', it will define the nested loops number.
10973 unsigned NestedLoopCount =
10974 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10975 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10976 VarsWithImplicitDSA, B);
10977 if (NestedLoopCount == 0)
10978 return StmtError();
10979
10980 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10981 "omp loop exprs were not built");
10982
10984 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10986}
10987
10989 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10990 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10991 if (!AStmt)
10992 return StmtError();
10993
10994 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10995 // A list item may not appear in a lastprivate clause unless it is the
10996 // loop iteration variable of a loop that is associated with the construct.
10997 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_parallel_loop,
10998 DSAStack))
10999 return StmtError();
11000
11001 CapturedStmt *CS =
11002 setBranchProtectedScope(SemaRef, OMPD_parallel_loop, AStmt);
11003
11004 OMPLoopDirective::HelperExprs B;
11005 // In presence of clause 'collapse', it will define the nested loops number.
11006 unsigned NestedLoopCount =
11007 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
11008 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
11009 VarsWithImplicitDSA, B);
11010 if (NestedLoopCount == 0)
11011 return StmtError();
11012
11013 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11014 "omp loop exprs were not built");
11015
11017 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11018}
11019
11021 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11022 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11023 if (!AStmt)
11024 return StmtError();
11025
11026 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11027 // A list item may not appear in a lastprivate clause unless it is the
11028 // loop iteration variable of a loop that is associated with the construct.
11029 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_parallel_loop,
11030 DSAStack))
11031 return StmtError();
11032
11033 CapturedStmt *CS =
11034 setBranchProtectedScope(SemaRef, OMPD_target_parallel_loop, AStmt);
11035
11036 OMPLoopDirective::HelperExprs B;
11037 // In presence of clause 'collapse', it will define the nested loops number.
11038 unsigned NestedLoopCount =
11039 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
11040 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
11041 VarsWithImplicitDSA, B);
11042 if (NestedLoopCount == 0)
11043 return StmtError();
11044
11045 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11046 "omp loop exprs were not built");
11047
11049 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11050}
11051
11053 Stmt *AStmt,
11054 SourceLocation StartLoc,
11055 SourceLocation EndLoc) {
11056 if (!AStmt)
11057 return StmtError();
11058
11059 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11060
11061 SemaRef.setFunctionHasBranchProtectedScope();
11062
11063 // OpenMP [2.7.3, single Construct, Restrictions]
11064 // The copyprivate clause must not be used with the nowait clause.
11065 const OMPClause *Nowait = nullptr;
11066 const OMPClause *Copyprivate = nullptr;
11067 for (const OMPClause *Clause : Clauses) {
11068 if (Clause->getClauseKind() == OMPC_nowait)
11069 Nowait = Clause;
11070 else if (Clause->getClauseKind() == OMPC_copyprivate)
11071 Copyprivate = Clause;
11072 if (Copyprivate && Nowait) {
11073 Diag(Copyprivate->getBeginLoc(),
11074 diag::err_omp_single_copyprivate_with_nowait);
11075 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
11076 return StmtError();
11077 }
11078 }
11079
11080 return OMPSingleDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11081 AStmt);
11082}
11083
11085 SourceLocation StartLoc,
11086 SourceLocation EndLoc) {
11087 if (!AStmt)
11088 return StmtError();
11089
11090 SemaRef.setFunctionHasBranchProtectedScope();
11091
11092 return OMPMasterDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt);
11093}
11094
11096 Stmt *AStmt,
11097 SourceLocation StartLoc,
11098 SourceLocation EndLoc) {
11099 if (!AStmt)
11100 return StmtError();
11101
11102 SemaRef.setFunctionHasBranchProtectedScope();
11103
11104 return OMPMaskedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11105 AStmt);
11106}
11107
11109 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
11110 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
11111 if (!AStmt)
11112 return StmtError();
11113
11114 bool ErrorFound = false;
11115 llvm::APSInt Hint;
11116 SourceLocation HintLoc;
11117 bool DependentHint = false;
11118 for (const OMPClause *C : Clauses) {
11119 if (C->getClauseKind() == OMPC_hint) {
11120 if (!DirName.getName()) {
11121 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
11122 ErrorFound = true;
11123 }
11124 Expr *E = cast<OMPHintClause>(C)->getHint();
11125 if (E->isTypeDependent() || E->isValueDependent() ||
11127 DependentHint = true;
11128 } else {
11130 HintLoc = C->getBeginLoc();
11131 }
11132 }
11133 }
11134 if (ErrorFound)
11135 return StmtError();
11136 const auto Pair = DSAStack->getCriticalWithHint(DirName);
11137 if (Pair.first && DirName.getName() && !DependentHint) {
11138 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
11139 Diag(StartLoc, diag::err_omp_critical_with_hint);
11140 if (HintLoc.isValid())
11141 Diag(HintLoc, diag::note_omp_critical_hint_here)
11142 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
11143 else
11144 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
11145 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
11146 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
11147 << 1
11148 << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()),
11149 /*Radix=*/10, /*Signed=*/false);
11150 } else {
11151 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
11152 }
11153 }
11154 }
11155
11156 SemaRef.setFunctionHasBranchProtectedScope();
11157
11158 auto *Dir = OMPCriticalDirective::Create(getASTContext(), DirName, StartLoc,
11159 EndLoc, Clauses, AStmt);
11160 if (!Pair.first && DirName.getName() && !DependentHint)
11161 DSAStack->addCriticalWithHint(Dir, Hint);
11162 return Dir;
11163}
11164
11166 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11167 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11168 if (!AStmt)
11169 return StmtError();
11170
11171 setBranchProtectedScope(SemaRef, OMPD_parallel_for, AStmt);
11172
11173 OMPLoopBasedDirective::HelperExprs B;
11174 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11175 // define the nested loops number.
11176 unsigned NestedLoopCount =
11177 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
11178 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
11179 VarsWithImplicitDSA, B);
11180 if (NestedLoopCount == 0)
11181 return StmtError();
11182
11183 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11184 return StmtError();
11185
11186 return OMPParallelForDirective::Create(
11187 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11188 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11189}
11190
11192 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11193 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11194 if (!AStmt)
11195 return StmtError();
11196
11197 CapturedStmt *CS =
11198 setBranchProtectedScope(SemaRef, OMPD_parallel_for_simd, AStmt);
11199
11200 OMPLoopBasedDirective::HelperExprs B;
11201 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11202 // define the nested loops number.
11203 unsigned NestedLoopCount =
11204 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
11205 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
11206 VarsWithImplicitDSA, B);
11207 if (NestedLoopCount == 0)
11208 return StmtError();
11209
11210 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11211 return StmtError();
11212
11214 return StmtError();
11215
11216 return OMPParallelForSimdDirective::Create(
11217 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11218}
11219
11221 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11222 SourceLocation EndLoc) {
11223 if (!AStmt)
11224 return StmtError();
11225
11226 setBranchProtectedScope(SemaRef, OMPD_parallel_master, AStmt);
11227
11228 return OMPParallelMasterDirective::Create(
11229 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11230 DSAStack->getTaskgroupReductionRef());
11231}
11232
11234 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11235 SourceLocation EndLoc) {
11236 if (!AStmt)
11237 return StmtError();
11238
11239 setBranchProtectedScope(SemaRef, OMPD_parallel_masked, AStmt);
11240
11241 return OMPParallelMaskedDirective::Create(
11242 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11243 DSAStack->getTaskgroupReductionRef());
11244}
11245
11247 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11248 SourceLocation EndLoc) {
11249 if (checkSectionsDirective(SemaRef, OMPD_parallel_sections, AStmt, DSAStack))
11250 return StmtError();
11251
11252 SemaRef.setFunctionHasBranchProtectedScope();
11253
11254 return OMPParallelSectionsDirective::Create(
11255 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11256 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11257}
11258
11259/// Find and diagnose mutually exclusive clause kinds.
11261 Sema &S, ArrayRef<OMPClause *> Clauses,
11262 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11263 const OMPClause *PrevClause = nullptr;
11264 bool ErrorFound = false;
11265 for (const OMPClause *C : Clauses) {
11266 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
11267 if (!PrevClause) {
11268 PrevClause = C;
11269 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11270 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11271 << getOpenMPClauseNameForDiag(C->getClauseKind())
11272 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11273 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
11274 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11275 ErrorFound = true;
11276 }
11277 }
11278 }
11279 return ErrorFound;
11280}
11281
11283 Stmt *AStmt,
11284 SourceLocation StartLoc,
11285 SourceLocation EndLoc) {
11286 if (!AStmt)
11287 return StmtError();
11288
11289 // OpenMP 5.0, 2.10.1 task Construct
11290 // If a detach clause appears on the directive, then a mergeable clause cannot
11291 // appear on the same directive.
11293 {OMPC_detach, OMPC_mergeable}))
11294 return StmtError();
11295
11296 setBranchProtectedScope(SemaRef, OMPD_task, AStmt);
11297
11298 return OMPTaskDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11299 AStmt, DSAStack->isCancelRegion());
11300}
11301
11303 SourceLocation EndLoc) {
11304 return OMPTaskyieldDirective::Create(getASTContext(), StartLoc, EndLoc);
11305}
11306
11308 SourceLocation EndLoc) {
11309 return OMPBarrierDirective::Create(getASTContext(), StartLoc, EndLoc);
11310}
11311
11313 SourceLocation StartLoc,
11314 SourceLocation EndLoc,
11315 bool InExContext) {
11316 const OMPAtClause *AtC =
11317 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11318
11319 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11320 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11321 return StmtError();
11322 }
11323
11324 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11325 const OMPSeverityClause *SeverityC =
11326 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11327 const OMPMessageClause *MessageC =
11328 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11329 std::optional<std::string> SL =
11330 MessageC ? MessageC->tryEvaluateString(getASTContext()) : std::nullopt;
11331
11332 if (MessageC && !SL)
11333 Diag(MessageC->getMessageString()->getBeginLoc(),
11334 diag::warn_clause_expected_string)
11335 << getOpenMPClauseNameForDiag(OMPC_message) << 1;
11336 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11337 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11338 << SL.value_or("WARNING");
11339 else
11340 Diag(StartLoc, diag::err_diagnose_if_succeeded) << SL.value_or("ERROR");
11341 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11342 return StmtError();
11343 }
11344
11345 return OMPErrorDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11346}
11347
11350 SourceLocation StartLoc,
11351 SourceLocation EndLoc) {
11352 const OMPNowaitClause *NowaitC =
11353 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11354 bool HasDependC =
11355 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11356 .empty();
11357 if (NowaitC && !HasDependC) {
11358 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11359 return StmtError();
11360 }
11361
11362 return OMPTaskwaitDirective::Create(getASTContext(), StartLoc, EndLoc,
11363 Clauses);
11364}
11365
11368 Stmt *AStmt, SourceLocation StartLoc,
11369 SourceLocation EndLoc) {
11370 if (!AStmt)
11371 return StmtError();
11372
11373 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11374
11375 SemaRef.setFunctionHasBranchProtectedScope();
11376
11377 return OMPTaskgroupDirective::Create(getASTContext(), StartLoc, EndLoc,
11378 Clauses, AStmt,
11379 DSAStack->getTaskgroupReductionRef());
11380}
11381
11383 SourceLocation StartLoc,
11384 SourceLocation EndLoc) {
11385 OMPFlushClause *FC = nullptr;
11386 OMPClause *OrderClause = nullptr;
11387 for (OMPClause *C : Clauses) {
11388 if (C->getClauseKind() == OMPC_flush)
11389 FC = cast<OMPFlushClause>(C);
11390 else
11391 OrderClause = C;
11392 }
11393 unsigned OMPVersion = getLangOpts().OpenMP;
11394 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11395 SourceLocation MemOrderLoc;
11396 for (const OMPClause *C : Clauses) {
11397 if (C->getClauseKind() == OMPC_acq_rel ||
11398 C->getClauseKind() == OMPC_acquire ||
11399 C->getClauseKind() == OMPC_release ||
11400 C->getClauseKind() == OMPC_seq_cst /*OpenMP 5.1*/) {
11401 if (MemOrderKind != OMPC_unknown) {
11402 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11403 << getOpenMPDirectiveName(OMPD_flush, OMPVersion) << 1
11404 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11405 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11406 << getOpenMPClauseNameForDiag(MemOrderKind);
11407 } else {
11408 MemOrderKind = C->getClauseKind();
11409 MemOrderLoc = C->getBeginLoc();
11410 }
11411 }
11412 }
11413 if (FC && OrderClause) {
11414 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11415 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11416 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11417 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11418 return StmtError();
11419 }
11420 return OMPFlushDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11421}
11422
11424 SourceLocation StartLoc,
11425 SourceLocation EndLoc) {
11426 if (Clauses.empty()) {
11427 Diag(StartLoc, diag::err_omp_depobj_expected);
11428 return StmtError();
11429 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11430 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11431 return StmtError();
11432 }
11433 // Only depobj expression and another single clause is allowed.
11434 if (Clauses.size() > 2) {
11435 Diag(Clauses[2]->getBeginLoc(),
11436 diag::err_omp_depobj_single_clause_expected);
11437 return StmtError();
11438 } else if (Clauses.size() < 1) {
11439 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11440 return StmtError();
11441 }
11442 return OMPDepobjDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11443}
11444
11446 SourceLocation StartLoc,
11447 SourceLocation EndLoc) {
11448 // Check that exactly one clause is specified.
11449 if (Clauses.size() != 1) {
11450 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11451 diag::err_omp_scan_single_clause_expected);
11452 return StmtError();
11453 }
11454 // Check that scan directive is used in the scope of the OpenMP loop body.
11455 if (Scope *S = DSAStack->getCurScope()) {
11456 Scope *ParentS = S->getParent();
11457 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11458 !ParentS->getBreakParent()->isOpenMPLoopScope()) {
11459 unsigned OMPVersion = getLangOpts().OpenMP;
11460 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11461 << getOpenMPDirectiveName(OMPD_scan, OMPVersion) << 5);
11462 }
11463 }
11464 // Check that only one instance of scan directives is used in the same outer
11465 // region.
11466 if (DSAStack->doesParentHasScanDirective()) {
11467 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11468 Diag(DSAStack->getParentScanDirectiveLoc(),
11469 diag::note_omp_previous_directive)
11470 << "scan";
11471 return StmtError();
11472 }
11473 DSAStack->setParentHasScanDirective(StartLoc);
11474 return OMPScanDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11475}
11476
11479 Stmt *AStmt, SourceLocation StartLoc,
11480 SourceLocation EndLoc) {
11481 const OMPClause *DependFound = nullptr;
11482 const OMPClause *DependSourceClause = nullptr;
11483 const OMPClause *DependSinkClause = nullptr;
11484 const OMPClause *DoacrossFound = nullptr;
11485 const OMPClause *DoacrossSourceClause = nullptr;
11486 const OMPClause *DoacrossSinkClause = nullptr;
11487 bool ErrorFound = false;
11488 const OMPThreadsClause *TC = nullptr;
11489 const OMPSIMDClause *SC = nullptr;
11490 for (const OMPClause *C : Clauses) {
11491 auto DOC = dyn_cast<OMPDoacrossClause>(C);
11492 auto DC = dyn_cast<OMPDependClause>(C);
11493 if (DC || DOC) {
11494 DependFound = DC ? C : nullptr;
11495 DoacrossFound = DOC ? C : nullptr;
11496 OMPDoacrossKind ODK;
11497 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11498 (DOC && (ODK.isSource(DOC)))) {
11499 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11500 unsigned OMPVersion = getLangOpts().OpenMP;
11501 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11502 << getOpenMPDirectiveName(OMPD_ordered, OMPVersion)
11503 << getOpenMPClauseNameForDiag(DC ? OMPC_depend : OMPC_doacross)
11504 << 2;
11505 ErrorFound = true;
11506 } else {
11507 if (DC)
11508 DependSourceClause = C;
11509 else
11510 DoacrossSourceClause = C;
11511 }
11512 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11513 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11514 << (DC ? "depend" : "doacross") << 0;
11515 ErrorFound = true;
11516 }
11517 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11518 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11519 if (DependSourceClause || DoacrossSourceClause) {
11520 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11521 << (DC ? "depend" : "doacross") << 1;
11522 ErrorFound = true;
11523 }
11524 if (DC)
11525 DependSinkClause = C;
11526 else
11527 DoacrossSinkClause = C;
11528 }
11529 } else if (C->getClauseKind() == OMPC_threads) {
11531 } else if (C->getClauseKind() == OMPC_simd) {
11532 SC = cast<OMPSIMDClause>(C);
11533 }
11534 }
11535 if (!ErrorFound && !SC &&
11536 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11537 // OpenMP [2.8.1,simd Construct, Restrictions]
11538 // An ordered construct with the simd clause is the only OpenMP construct
11539 // that can appear in the simd region.
11540 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11541 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11542 ErrorFound = true;
11543 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11544 SourceLocation Loc =
11545 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11546 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11547 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend : OMPC_doacross)
11549 : SC->getClauseKind());
11550 ErrorFound = true;
11551 } else if ((DependFound || DoacrossFound) &&
11552 !DSAStack->getParentOrderedRegionParam().first) {
11553 SourceLocation Loc =
11554 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11555 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11556 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend
11557 : OMPC_doacross);
11558 ErrorFound = true;
11559 } else if (TC || Clauses.empty()) {
11560 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11561 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11562 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11563 << (TC != nullptr);
11564 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11565 ErrorFound = true;
11566 }
11567 }
11568 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11569 return StmtError();
11570
11571 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11572 // During execution of an iteration of a worksharing-loop or a loop nest
11573 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11574 // must not execute more than one ordered region corresponding to an ordered
11575 // construct without a depend clause.
11576 if (!DependFound && !DoacrossFound) {
11577 if (DSAStack->doesParentHasOrderedDirective()) {
11578 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11579 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11580 diag::note_omp_previous_directive)
11581 << "ordered";
11582 return StmtError();
11583 }
11584 DSAStack->setParentHasOrderedDirective(StartLoc);
11585 }
11586
11587 if (AStmt) {
11588 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11589
11590 SemaRef.setFunctionHasBranchProtectedScope();
11591 }
11592
11593 return OMPOrderedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11594 AStmt);
11595}
11596
11597namespace {
11598/// Helper class for checking expression in 'omp atomic [update]'
11599/// construct.
11600class OpenMPAtomicUpdateChecker {
11601 /// Error results for atomic update expressions.
11602 enum ExprAnalysisErrorCode {
11603 /// A statement is not an expression statement.
11604 NotAnExpression,
11605 /// Expression is not builtin binary or unary operation.
11606 NotABinaryOrUnaryExpression,
11607 /// Unary operation is not post-/pre- increment/decrement operation.
11608 NotAnUnaryIncDecExpression,
11609 /// An expression is not of scalar type.
11610 NotAScalarType,
11611 /// A binary operation is not an assignment operation.
11612 NotAnAssignmentOp,
11613 /// RHS part of the binary operation is not a binary expression.
11614 NotABinaryExpression,
11615 /// RHS part is not additive/multiplicative/shift/bitwise binary
11616 /// expression.
11617 NotABinaryOperator,
11618 /// RHS binary operation does not have reference to the updated LHS
11619 /// part.
11620 NotAnUpdateExpression,
11621 /// An expression contains semantical error not related to
11622 /// 'omp atomic [update]'
11623 NotAValidExpression,
11624 /// No errors is found.
11625 NoError
11626 };
11627 /// Reference to Sema.
11628 Sema &SemaRef;
11629 /// A location for note diagnostics (when error is found).
11630 SourceLocation NoteLoc;
11631 /// 'x' lvalue part of the source atomic expression.
11632 Expr *X;
11633 /// 'expr' rvalue part of the source atomic expression.
11634 Expr *E;
11635 /// Helper expression of the form
11636 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11637 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11638 Expr *UpdateExpr;
11639 /// Is 'x' a LHS in a RHS part of full update expression. It is
11640 /// important for non-associative operations.
11641 bool IsXLHSInRHSPart;
11643 SourceLocation OpLoc;
11644 /// true if the source expression is a postfix unary operation, false
11645 /// if it is a prefix unary operation.
11646 bool IsPostfixUpdate;
11647
11648public:
11649 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11650 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11651 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11652 /// Check specified statement that it is suitable for 'atomic update'
11653 /// constructs and extract 'x', 'expr' and Operation from the original
11654 /// expression. If DiagId and NoteId == 0, then only check is performed
11655 /// without error notification.
11656 /// \param DiagId Diagnostic which should be emitted if error is found.
11657 /// \param NoteId Diagnostic note for the main error message.
11658 /// \return true if statement is not an update expression, false otherwise.
11659 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11660 /// Return the 'x' lvalue part of the source atomic expression.
11661 Expr *getX() const { return X; }
11662 /// Return the 'expr' rvalue part of the source atomic expression.
11663 Expr *getExpr() const { return E; }
11664 /// Return the update expression used in calculation of the updated
11665 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11666 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11667 Expr *getUpdateExpr() const { return UpdateExpr; }
11668 /// Return true if 'x' is LHS in RHS part of full update expression,
11669 /// false otherwise.
11670 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11671
11672 /// true if the source expression is a postfix unary operation, false
11673 /// if it is a prefix unary operation.
11674 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11675
11676private:
11677 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11678 unsigned NoteId = 0);
11679};
11680
11681bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11682 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11683 ExprAnalysisErrorCode ErrorFound = NoError;
11684 SourceLocation ErrorLoc, NoteLoc;
11685 SourceRange ErrorRange, NoteRange;
11686 // Allowed constructs are:
11687 // x = x binop expr;
11688 // x = expr binop x;
11689 if (AtomicBinOp->getOpcode() == BO_Assign) {
11690 X = AtomicBinOp->getLHS();
11691 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11692 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11693 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11694 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11695 AtomicInnerBinOp->isBitwiseOp()) {
11696 Op = AtomicInnerBinOp->getOpcode();
11697 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11698 Expr *LHS = AtomicInnerBinOp->getLHS();
11699 Expr *RHS = AtomicInnerBinOp->getRHS();
11700 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11701 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11702 /*Canonical=*/true);
11703 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11704 /*Canonical=*/true);
11705 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11706 /*Canonical=*/true);
11707 if (XId == LHSId) {
11708 E = RHS;
11709 IsXLHSInRHSPart = true;
11710 } else if (XId == RHSId) {
11711 E = LHS;
11712 IsXLHSInRHSPart = false;
11713 } else {
11714 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11715 ErrorRange = AtomicInnerBinOp->getSourceRange();
11716 NoteLoc = X->getExprLoc();
11717 NoteRange = X->getSourceRange();
11718 ErrorFound = NotAnUpdateExpression;
11719 }
11720 } else {
11721 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11722 ErrorRange = AtomicInnerBinOp->getSourceRange();
11723 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11724 NoteRange = SourceRange(NoteLoc, NoteLoc);
11725 ErrorFound = NotABinaryOperator;
11726 }
11727 } else {
11728 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11729 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11730 ErrorFound = NotABinaryExpression;
11731 }
11732 } else {
11733 ErrorLoc = AtomicBinOp->getExprLoc();
11734 ErrorRange = AtomicBinOp->getSourceRange();
11735 NoteLoc = AtomicBinOp->getOperatorLoc();
11736 NoteRange = SourceRange(NoteLoc, NoteLoc);
11737 ErrorFound = NotAnAssignmentOp;
11738 }
11739 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11740 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11741 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11742 return true;
11743 }
11744 if (SemaRef.CurContext->isDependentContext())
11745 E = X = UpdateExpr = nullptr;
11746 return ErrorFound != NoError;
11747}
11748
11749bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11750 unsigned NoteId) {
11751 ExprAnalysisErrorCode ErrorFound = NoError;
11752 SourceLocation ErrorLoc, NoteLoc;
11753 SourceRange ErrorRange, NoteRange;
11754 // Allowed constructs are:
11755 // x++;
11756 // x--;
11757 // ++x;
11758 // --x;
11759 // x binop= expr;
11760 // x = x binop expr;
11761 // x = expr binop x;
11762 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11763 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11764 if (AtomicBody->getType()->isScalarType() ||
11765 AtomicBody->isInstantiationDependent()) {
11766 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11767 AtomicBody->IgnoreParenImpCasts())) {
11768 // Check for Compound Assignment Operation
11770 AtomicCompAssignOp->getOpcode());
11771 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11772 E = AtomicCompAssignOp->getRHS();
11773 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11774 IsXLHSInRHSPart = true;
11775 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11776 AtomicBody->IgnoreParenImpCasts())) {
11777 // Check for Binary Operation
11778 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11779 return true;
11780 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11781 AtomicBody->IgnoreParenImpCasts())) {
11782 // Check for Unary Operation
11783 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11784 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11785 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11786 OpLoc = AtomicUnaryOp->getOperatorLoc();
11787 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11788 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11789 IsXLHSInRHSPart = true;
11790 } else {
11791 ErrorFound = NotAnUnaryIncDecExpression;
11792 ErrorLoc = AtomicUnaryOp->getExprLoc();
11793 ErrorRange = AtomicUnaryOp->getSourceRange();
11794 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11795 NoteRange = SourceRange(NoteLoc, NoteLoc);
11796 }
11797 } else if (!AtomicBody->isInstantiationDependent()) {
11798 ErrorFound = NotABinaryOrUnaryExpression;
11799 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11800 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11801 } else if (AtomicBody->containsErrors()) {
11802 ErrorFound = NotAValidExpression;
11803 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11804 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11805 }
11806 } else {
11807 ErrorFound = NotAScalarType;
11808 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11809 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11810 }
11811 } else {
11812 ErrorFound = NotAnExpression;
11813 NoteLoc = ErrorLoc = S->getBeginLoc();
11814 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11815 }
11816 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11817 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11818 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11819 return true;
11820 }
11821 if (SemaRef.CurContext->isDependentContext())
11822 E = X = UpdateExpr = nullptr;
11823 if (ErrorFound == NoError && E && X) {
11824 // Build an update expression of form 'OpaqueValueExpr(x) binop
11825 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11826 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11827 auto *OVEX = new (SemaRef.getASTContext())
11828 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11829 auto *OVEExpr = new (SemaRef.getASTContext())
11832 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11833 IsXLHSInRHSPart ? OVEExpr : OVEX);
11834 if (Update.isInvalid())
11835 return true;
11836 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11838 if (Update.isInvalid())
11839 return true;
11840 UpdateExpr = Update.get();
11841 }
11842 return ErrorFound != NoError;
11843}
11844
11845/// Get the node id of the fixed point of an expression \a S.
11846llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11847 llvm::FoldingSetNodeID Id;
11848 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11849 return Id;
11850}
11851
11852/// Check if two expressions are same.
11853bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11854 const Expr *RHS) {
11855 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11856}
11857
11858class OpenMPAtomicCompareChecker {
11859public:
11860 /// All kinds of errors that can occur in `atomic compare`
11861 enum ErrorTy {
11862 /// Empty compound statement.
11863 NoStmt = 0,
11864 /// More than one statement in a compound statement.
11865 MoreThanOneStmt,
11866 /// Not an assignment binary operator.
11867 NotAnAssignment,
11868 /// Not a conditional operator.
11869 NotCondOp,
11870 /// Wrong false expr. According to the spec, 'x' should be at the false
11871 /// expression of a conditional expression.
11872 WrongFalseExpr,
11873 /// The condition of a conditional expression is not a binary operator.
11874 NotABinaryOp,
11875 /// Invalid binary operator (not <, >, or ==).
11876 InvalidBinaryOp,
11877 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11878 InvalidComparison,
11879 /// X is not a lvalue.
11880 XNotLValue,
11881 /// Not a scalar.
11882 NotScalar,
11883 /// Not an integer.
11884 NotInteger,
11885 /// 'else' statement is not expected.
11886 UnexpectedElse,
11887 /// Not an equality operator.
11888 NotEQ,
11889 /// Invalid assignment (not v == x).
11890 InvalidAssignment,
11891 /// Not if statement
11892 NotIfStmt,
11893 /// More than two statements in a compound statement.
11894 MoreThanTwoStmts,
11895 /// Not a compound statement.
11896 NotCompoundStmt,
11897 /// No else statement.
11898 NoElse,
11899 /// Not 'if (r)'.
11900 InvalidCondition,
11901 /// No error.
11902 NoError,
11903 };
11904
11905 struct ErrorInfoTy {
11906 ErrorTy Error;
11907 SourceLocation ErrorLoc;
11908 SourceRange ErrorRange;
11909 SourceLocation NoteLoc;
11910 SourceRange NoteRange;
11911 };
11912
11913 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11914
11915 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11916 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11917
11918 Expr *getX() const { return X; }
11919 Expr *getE() const { return E; }
11920 Expr *getD() const { return D; }
11921 Expr *getCond() const { return C; }
11922 bool isXBinopExpr() const { return IsXBinopExpr; }
11923
11924protected:
11925 /// Reference to ASTContext
11926 ASTContext &ContextRef;
11927 /// 'x' lvalue part of the source atomic expression.
11928 Expr *X = nullptr;
11929 /// 'expr' or 'e' rvalue part of the source atomic expression.
11930 Expr *E = nullptr;
11931 /// 'd' rvalue part of the source atomic expression.
11932 Expr *D = nullptr;
11933 /// 'cond' part of the source atomic expression. It is in one of the following
11934 /// forms:
11935 /// expr ordop x
11936 /// x ordop expr
11937 /// x == e
11938 /// e == x
11939 Expr *C = nullptr;
11940 /// True if the cond expr is in the form of 'x ordop expr'.
11941 bool IsXBinopExpr = true;
11942
11943 /// Check if it is a valid conditional update statement (cond-update-stmt).
11944 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11945
11946 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11947 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11948
11949 /// Check if all captured values have right type.
11950 bool checkType(ErrorInfoTy &ErrorInfo) const;
11951
11952 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11953 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11954 if (E->isInstantiationDependent())
11955 return true;
11956
11957 if (ShouldBeLValue && !E->isLValue()) {
11958 ErrorInfo.Error = ErrorTy::XNotLValue;
11959 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11960 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11961 return false;
11962 }
11963
11964 QualType QTy = E->getType();
11965 if (!QTy->isScalarType()) {
11966 ErrorInfo.Error = ErrorTy::NotScalar;
11967 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11968 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11969 return false;
11970 }
11971 if (ShouldBeInteger && !QTy->isIntegerType()) {
11972 ErrorInfo.Error = ErrorTy::NotInteger;
11973 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11974 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11975 return false;
11976 }
11977
11978 return true;
11979 }
11980};
11981
11982bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11983 ErrorInfoTy &ErrorInfo) {
11984 auto *Then = S->getThen();
11985 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11986 if (CS->body_empty()) {
11987 ErrorInfo.Error = ErrorTy::NoStmt;
11988 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11989 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11990 return false;
11991 }
11992 if (CS->size() > 1) {
11993 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11994 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11995 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11996 return false;
11997 }
11998 Then = CS->body_front();
11999 }
12000
12001 auto *BO = dyn_cast<BinaryOperator>(Then);
12002 if (!BO) {
12003 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12004 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12005 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12006 return false;
12007 }
12008 if (BO->getOpcode() != BO_Assign) {
12009 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12010 ErrorInfo.ErrorLoc = BO->getExprLoc();
12011 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12012 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12013 return false;
12014 }
12015
12016 X = BO->getLHS();
12017
12018 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12019 auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
12020 Expr *LHS = nullptr;
12021 Expr *RHS = nullptr;
12022 if (Cond) {
12023 LHS = Cond->getLHS();
12024 RHS = Cond->getRHS();
12025 } else if (Call) {
12026 LHS = Call->getArg(0);
12027 RHS = Call->getArg(1);
12028 } else {
12029 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12030 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12031 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12032 return false;
12033 }
12034
12035 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12036 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12037 C = S->getCond();
12038 D = BO->getRHS();
12039 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12040 E = RHS;
12041 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12042 E = LHS;
12043 } else {
12044 ErrorInfo.Error = ErrorTy::InvalidComparison;
12045 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12046 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12047 S->getCond()->getSourceRange();
12048 return false;
12049 }
12050 } else if ((Cond &&
12051 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12052 (Call &&
12053 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12054 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12055 E = BO->getRHS();
12056 if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
12057 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12058 C = S->getCond();
12059 } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12060 checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12061 C = S->getCond();
12062 IsXBinopExpr = false;
12063 } else {
12064 ErrorInfo.Error = ErrorTy::InvalidComparison;
12065 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12066 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12067 S->getCond()->getSourceRange();
12068 return false;
12069 }
12070 } else {
12071 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12072 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12073 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12074 return false;
12075 }
12076
12077 if (S->getElse()) {
12078 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12079 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
12080 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
12081 return false;
12082 }
12083
12084 return true;
12085}
12086
12087bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
12088 ErrorInfoTy &ErrorInfo) {
12089 auto *BO = dyn_cast<BinaryOperator>(S);
12090 if (!BO) {
12091 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12092 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12093 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12094 return false;
12095 }
12096 if (BO->getOpcode() != BO_Assign) {
12097 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12098 ErrorInfo.ErrorLoc = BO->getExprLoc();
12099 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12100 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12101 return false;
12102 }
12103
12104 X = BO->getLHS();
12105
12106 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
12107 if (!CO) {
12108 ErrorInfo.Error = ErrorTy::NotCondOp;
12109 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12110 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12111 return false;
12112 }
12113
12114 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
12115 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12116 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12117 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12118 CO->getFalseExpr()->getSourceRange();
12119 return false;
12120 }
12121
12122 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
12123 auto *Call = dyn_cast<CXXOperatorCallExpr>(CO->getCond());
12124 Expr *LHS = nullptr;
12125 Expr *RHS = nullptr;
12126 if (Cond) {
12127 LHS = Cond->getLHS();
12128 RHS = Cond->getRHS();
12129 } else if (Call) {
12130 LHS = Call->getArg(0);
12131 RHS = Call->getArg(1);
12132 } else {
12133 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12134 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12135 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12136 CO->getCond()->getSourceRange();
12137 return false;
12138 }
12139
12140 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12141 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12142 C = CO->getCond();
12143 D = CO->getTrueExpr();
12144 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12145 E = RHS;
12146 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12147 E = LHS;
12148 } else {
12149 ErrorInfo.Error = ErrorTy::InvalidComparison;
12150 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12151 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12152 CO->getCond()->getSourceRange();
12153 return false;
12154 }
12155 } else if ((Cond &&
12156 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12157 (Call &&
12158 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12159 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12160
12161 E = CO->getTrueExpr();
12162 if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
12163 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12164 C = CO->getCond();
12165 } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12166 checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12167 C = CO->getCond();
12168 IsXBinopExpr = false;
12169 } else {
12170 ErrorInfo.Error = ErrorTy::InvalidComparison;
12171 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12172 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12173 CO->getCond()->getSourceRange();
12174 return false;
12175 }
12176 } else {
12177 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12178 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12179 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12180 CO->getCond()->getSourceRange();
12181 return false;
12182 }
12183
12184 return true;
12185}
12186
12187bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
12188 // 'x' and 'e' cannot be nullptr
12189 assert(X && E && "X and E cannot be nullptr");
12190
12191 if (!CheckValue(X, ErrorInfo, true))
12192 return false;
12193
12194 if (!CheckValue(E, ErrorInfo, false))
12195 return false;
12196
12197 if (D && !CheckValue(D, ErrorInfo, false))
12198 return false;
12199
12200 return true;
12201}
12202
12203bool OpenMPAtomicCompareChecker::checkStmt(
12204 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12205 auto *CS = dyn_cast<CompoundStmt>(S);
12206 if (CS) {
12207 if (CS->body_empty()) {
12208 ErrorInfo.Error = ErrorTy::NoStmt;
12209 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12210 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12211 return false;
12212 }
12213
12214 if (CS->size() != 1) {
12215 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12216 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12217 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12218 return false;
12219 }
12220 S = CS->body_front();
12221 }
12222
12223 auto Res = false;
12224
12225 if (auto *IS = dyn_cast<IfStmt>(S)) {
12226 // Check if the statement is in one of the following forms
12227 // (cond-update-stmt):
12228 // if (expr ordop x) { x = expr; }
12229 // if (x ordop expr) { x = expr; }
12230 // if (x == e) { x = d; }
12231 Res = checkCondUpdateStmt(IS, ErrorInfo);
12232 } else {
12233 // Check if the statement is in one of the following forms (cond-expr-stmt):
12234 // x = expr ordop x ? expr : x;
12235 // x = x ordop expr ? expr : x;
12236 // x = x == e ? d : x;
12237 Res = checkCondExprStmt(S, ErrorInfo);
12238 }
12239
12240 if (!Res)
12241 return false;
12242
12243 return checkType(ErrorInfo);
12244}
12245
12246class OpenMPAtomicCompareCaptureChecker final
12247 : public OpenMPAtomicCompareChecker {
12248public:
12249 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12250
12251 Expr *getV() const { return V; }
12252 Expr *getR() const { return R; }
12253 bool isFailOnly() const { return IsFailOnly; }
12254 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12255
12256 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12257 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12258
12259private:
12260 bool checkType(ErrorInfoTy &ErrorInfo);
12261
12262 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12263 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12264 // spec p.p. 82:
12265 // (1) { v = x; cond-update-stmt }
12266 // (2) { cond-update-stmt v = x; }
12267 // (3) if(x == e) { x = d; } else { v = x; }
12268 // (4) { r = x == e; if(r) { x = d; } }
12269 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12270
12271 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12272 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12273
12274 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12275 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12276 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12277
12278 /// 'v' lvalue part of the source atomic expression.
12279 Expr *V = nullptr;
12280 /// 'r' lvalue part of the source atomic expression.
12281 Expr *R = nullptr;
12282 /// If 'v' is only updated when the comparison fails.
12283 bool IsFailOnly = false;
12284 /// If original value of 'x' must be stored in 'v', not an updated one.
12285 bool IsPostfixUpdate = false;
12286};
12287
12288bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12289 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12290 return false;
12291
12292 if (V && !CheckValue(V, ErrorInfo, true))
12293 return false;
12294
12295 if (R && !CheckValue(R, ErrorInfo, true, true))
12296 return false;
12297
12298 return true;
12299}
12300
12301bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12302 ErrorInfoTy &ErrorInfo) {
12303 IsFailOnly = true;
12304
12305 auto *Then = S->getThen();
12306 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12307 if (CS->body_empty()) {
12308 ErrorInfo.Error = ErrorTy::NoStmt;
12309 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12310 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12311 return false;
12312 }
12313 if (CS->size() > 1) {
12314 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12315 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12316 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12317 return false;
12318 }
12319 Then = CS->body_front();
12320 }
12321
12322 auto *BO = dyn_cast<BinaryOperator>(Then);
12323 if (!BO) {
12324 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12325 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12326 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12327 return false;
12328 }
12329 if (BO->getOpcode() != BO_Assign) {
12330 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12331 ErrorInfo.ErrorLoc = BO->getExprLoc();
12332 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12333 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12334 return false;
12335 }
12336
12337 X = BO->getLHS();
12338 D = BO->getRHS();
12339
12340 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12341 auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
12342 Expr *LHS = nullptr;
12343 Expr *RHS = nullptr;
12344 if (Cond) {
12345 LHS = Cond->getLHS();
12346 RHS = Cond->getRHS();
12347 } else if (Call) {
12348 LHS = Call->getArg(0);
12349 RHS = Call->getArg(1);
12350 } else {
12351 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12352 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12353 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12354 return false;
12355 }
12356 if ((Cond && Cond->getOpcode() != BO_EQ) ||
12357 (Call && Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12358 ErrorInfo.Error = ErrorTy::NotEQ;
12359 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12360 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12361 return false;
12362 }
12363
12364 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12365 E = RHS;
12366 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12367 E = LHS;
12368 } else {
12369 ErrorInfo.Error = ErrorTy::InvalidComparison;
12370 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12371 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12372 return false;
12373 }
12374
12375 C = S->getCond();
12376
12377 if (!S->getElse()) {
12378 ErrorInfo.Error = ErrorTy::NoElse;
12379 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12380 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12381 return false;
12382 }
12383
12384 auto *Else = S->getElse();
12385 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12386 if (CS->body_empty()) {
12387 ErrorInfo.Error = ErrorTy::NoStmt;
12388 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12389 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12390 return false;
12391 }
12392 if (CS->size() > 1) {
12393 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12394 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12395 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12396 return false;
12397 }
12398 Else = CS->body_front();
12399 }
12400
12401 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12402 if (!ElseBO) {
12403 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12404 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12405 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12406 return false;
12407 }
12408 if (ElseBO->getOpcode() != BO_Assign) {
12409 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12410 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12411 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12412 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12413 return false;
12414 }
12415
12416 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12417 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12418 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12419 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12420 ElseBO->getRHS()->getSourceRange();
12421 return false;
12422 }
12423
12424 V = ElseBO->getLHS();
12425
12426 return checkType(ErrorInfo);
12427}
12428
12429bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12430 ErrorInfoTy &ErrorInfo) {
12431 // We don't check here as they should be already done before call this
12432 // function.
12433 auto *CS = cast<CompoundStmt>(S);
12434 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12435 auto *S1 = cast<BinaryOperator>(CS->body_front());
12436 auto *S2 = cast<IfStmt>(CS->body_back());
12437 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12438
12439 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12440 ErrorInfo.Error = ErrorTy::InvalidCondition;
12441 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12442 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12443 return false;
12444 }
12445
12446 R = S1->getLHS();
12447
12448 auto *Then = S2->getThen();
12449 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12450 if (ThenCS->body_empty()) {
12451 ErrorInfo.Error = ErrorTy::NoStmt;
12452 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12453 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12454 return false;
12455 }
12456 if (ThenCS->size() > 1) {
12457 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12458 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12459 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12460 return false;
12461 }
12462 Then = ThenCS->body_front();
12463 }
12464
12465 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12466 if (!ThenBO) {
12467 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12468 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12469 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12470 return false;
12471 }
12472 if (ThenBO->getOpcode() != BO_Assign) {
12473 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12474 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12475 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12476 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12477 return false;
12478 }
12479
12480 X = ThenBO->getLHS();
12481 D = ThenBO->getRHS();
12482
12483 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12484 if (BO->getOpcode() != BO_EQ) {
12485 ErrorInfo.Error = ErrorTy::NotEQ;
12486 ErrorInfo.ErrorLoc = BO->getExprLoc();
12487 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12488 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12489 return false;
12490 }
12491
12492 C = BO;
12493
12494 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12495 E = BO->getRHS();
12496 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12497 E = BO->getLHS();
12498 } else {
12499 ErrorInfo.Error = ErrorTy::InvalidComparison;
12500 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12501 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12502 return false;
12503 }
12504
12505 if (S2->getElse()) {
12506 IsFailOnly = true;
12507
12508 auto *Else = S2->getElse();
12509 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12510 if (ElseCS->body_empty()) {
12511 ErrorInfo.Error = ErrorTy::NoStmt;
12512 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12513 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12514 return false;
12515 }
12516 if (ElseCS->size() > 1) {
12517 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12518 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12519 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12520 return false;
12521 }
12522 Else = ElseCS->body_front();
12523 }
12524
12525 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12526 if (!ElseBO) {
12527 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12528 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12529 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12530 return false;
12531 }
12532 if (ElseBO->getOpcode() != BO_Assign) {
12533 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12534 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12535 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12536 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12537 return false;
12538 }
12539 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12540 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12541 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12542 ErrorInfo.NoteLoc = X->getExprLoc();
12543 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12544 ErrorInfo.NoteRange = X->getSourceRange();
12545 return false;
12546 }
12547
12548 V = ElseBO->getLHS();
12549 }
12550
12551 return checkType(ErrorInfo);
12552}
12553
12554bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12555 ErrorInfoTy &ErrorInfo) {
12556 // if(x == e) { x = d; } else { v = x; }
12557 if (auto *IS = dyn_cast<IfStmt>(S))
12558 return checkForm3(IS, ErrorInfo);
12559
12560 auto *CS = dyn_cast<CompoundStmt>(S);
12561 if (!CS) {
12562 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12563 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12564 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12565 return false;
12566 }
12567 if (CS->body_empty()) {
12568 ErrorInfo.Error = ErrorTy::NoStmt;
12569 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12570 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12571 return false;
12572 }
12573
12574 // { if(x == e) { x = d; } else { v = x; } }
12575 if (CS->size() == 1) {
12576 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12577 if (!IS) {
12578 ErrorInfo.Error = ErrorTy::NotIfStmt;
12579 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12580 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12581 CS->body_front()->getSourceRange();
12582 return false;
12583 }
12584
12585 return checkForm3(IS, ErrorInfo);
12586 } else if (CS->size() == 2) {
12587 auto *S1 = CS->body_front();
12588 auto *S2 = CS->body_back();
12589
12590 Stmt *UpdateStmt = nullptr;
12591 Stmt *CondUpdateStmt = nullptr;
12592 Stmt *CondExprStmt = nullptr;
12593
12594 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12595 // It could be one of the following cases:
12596 // { v = x; cond-update-stmt }
12597 // { v = x; cond-expr-stmt }
12598 // { cond-expr-stmt; v = x; }
12599 // form 45
12600 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12601 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12602 // check if form 45
12603 if (isa<IfStmt>(S2))
12604 return checkForm45(CS, ErrorInfo);
12605 // { cond-expr-stmt; v = x; }
12606 CondExprStmt = S1;
12607 UpdateStmt = S2;
12608 } else {
12609 IsPostfixUpdate = true;
12610 UpdateStmt = S1;
12611 if (isa<IfStmt>(S2)) {
12612 // { v = x; cond-update-stmt }
12613 CondUpdateStmt = S2;
12614 } else {
12615 // { v = x; cond-expr-stmt }
12616 CondExprStmt = S2;
12617 }
12618 }
12619 } else {
12620 // { cond-update-stmt v = x; }
12621 UpdateStmt = S2;
12622 CondUpdateStmt = S1;
12623 }
12624
12625 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12626 auto *IS = dyn_cast<IfStmt>(CUS);
12627 if (!IS) {
12628 ErrorInfo.Error = ErrorTy::NotIfStmt;
12629 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12630 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12631 return false;
12632 }
12633
12634 return checkCondUpdateStmt(IS, ErrorInfo);
12635 };
12636
12637 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12638 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12639 auto *BO = dyn_cast<BinaryOperator>(US);
12640 if (!BO) {
12641 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12642 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12643 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12644 return false;
12645 }
12646 if (BO->getOpcode() != BO_Assign) {
12647 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12648 ErrorInfo.ErrorLoc = BO->getExprLoc();
12649 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12650 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12651 return false;
12652 }
12653 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12654 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12655 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12656 ErrorInfo.NoteLoc = this->X->getExprLoc();
12657 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12658 ErrorInfo.NoteRange = this->X->getSourceRange();
12659 return false;
12660 }
12661
12662 this->V = BO->getLHS();
12663
12664 return true;
12665 };
12666
12667 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12668 return false;
12669 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12670 return false;
12671 if (!CheckUpdateStmt(UpdateStmt))
12672 return false;
12673 } else {
12674 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12675 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12676 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12677 return false;
12678 }
12679
12680 return checkType(ErrorInfo);
12681}
12682} // namespace
12683
12685 Stmt *AStmt,
12686 SourceLocation StartLoc,
12687 SourceLocation EndLoc) {
12688 ASTContext &Context = getASTContext();
12689 unsigned OMPVersion = getLangOpts().OpenMP;
12690 // Register location of the first atomic directive.
12691 DSAStack->addAtomicDirectiveLoc(StartLoc);
12692 if (!AStmt)
12693 return StmtError();
12694
12695 // 1.2.2 OpenMP Language Terminology
12696 // Structured block - An executable statement with a single entry at the
12697 // top and a single exit at the bottom.
12698 // The point of exit cannot be a branch out of the structured block.
12699 // longjmp() and throw() must not violate the entry/exit criteria.
12700 OpenMPClauseKind AtomicKind = OMPC_unknown;
12701 SourceLocation AtomicKindLoc;
12702 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12703 SourceLocation MemOrderLoc;
12704 bool MutexClauseEncountered = false;
12705 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12706 for (const OMPClause *C : Clauses) {
12707 switch (C->getClauseKind()) {
12708 case OMPC_read:
12709 case OMPC_write:
12710 case OMPC_update:
12711 MutexClauseEncountered = true;
12712 [[fallthrough]];
12713 case OMPC_capture:
12714 case OMPC_compare: {
12715 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12716 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12717 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12718 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12719 << getOpenMPClauseNameForDiag(AtomicKind);
12720 } else {
12721 AtomicKind = C->getClauseKind();
12722 AtomicKindLoc = C->getBeginLoc();
12723 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12724 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12725 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12726 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12727 << getOpenMPClauseNameForDiag(AtomicKind);
12728 }
12729 }
12730 break;
12731 }
12732 case OMPC_weak:
12733 case OMPC_fail: {
12734 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12735 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12736 << getOpenMPClauseNameForDiag(C->getClauseKind())
12737 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12738 return StmtError();
12739 }
12740 break;
12741 }
12742 case OMPC_seq_cst:
12743 case OMPC_acq_rel:
12744 case OMPC_acquire:
12745 case OMPC_release:
12746 case OMPC_relaxed: {
12747 if (MemOrderKind != OMPC_unknown) {
12748 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12749 << getOpenMPDirectiveName(OMPD_atomic, OMPVersion) << 0
12750 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12751 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12752 << getOpenMPClauseNameForDiag(MemOrderKind);
12753 } else {
12754 MemOrderKind = C->getClauseKind();
12755 MemOrderLoc = C->getBeginLoc();
12756 }
12757 break;
12758 }
12759 // The following clauses are allowed, but we don't need to do anything here.
12760 case OMPC_hint:
12761 break;
12762 default:
12763 llvm_unreachable("unknown clause is encountered");
12764 }
12765 }
12766 bool IsCompareCapture = false;
12767 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12768 EncounteredAtomicKinds.contains(OMPC_capture)) {
12769 IsCompareCapture = true;
12770 AtomicKind = OMPC_compare;
12771 }
12772 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12773 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12774 // release.
12775 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12776 // acquire.
12777 // If atomic-clause is update or not present then memory-order-clause must not
12778 // be acq_rel or acquire.
12779 if ((AtomicKind == OMPC_read &&
12780 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12781 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12782 AtomicKind == OMPC_unknown) &&
12783 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12784 SourceLocation Loc = AtomicKindLoc;
12785 if (AtomicKind == OMPC_unknown)
12786 Loc = StartLoc;
12787 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12788 << getOpenMPClauseNameForDiag(AtomicKind)
12789 << (AtomicKind == OMPC_unknown ? 1 : 0)
12790 << getOpenMPClauseNameForDiag(MemOrderKind);
12791 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12792 << getOpenMPClauseNameForDiag(MemOrderKind);
12793 }
12794
12795 Stmt *Body = AStmt;
12796 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12797 Body = EWC->getSubExpr();
12798
12799 Expr *X = nullptr;
12800 Expr *V = nullptr;
12801 Expr *E = nullptr;
12802 Expr *UE = nullptr;
12803 Expr *D = nullptr;
12804 Expr *CE = nullptr;
12805 Expr *R = nullptr;
12806 bool IsXLHSInRHSPart = false;
12807 bool IsPostfixUpdate = false;
12808 bool IsFailOnly = false;
12809 // OpenMP [2.12.6, atomic Construct]
12810 // In the next expressions:
12811 // * x and v (as applicable) are both l-value expressions with scalar type.
12812 // * During the execution of an atomic region, multiple syntactic
12813 // occurrences of x must designate the same storage location.
12814 // * Neither of v and expr (as applicable) may access the storage location
12815 // designated by x.
12816 // * Neither of x and expr (as applicable) may access the storage location
12817 // designated by v.
12818 // * expr is an expression with scalar type.
12819 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12820 // * binop, binop=, ++, and -- are not overloaded operators.
12821 // * The expression x binop expr must be numerically equivalent to x binop
12822 // (expr). This requirement is satisfied if the operators in expr have
12823 // precedence greater than binop, or by using parentheses around expr or
12824 // subexpressions of expr.
12825 // * The expression expr binop x must be numerically equivalent to (expr)
12826 // binop x. This requirement is satisfied if the operators in expr have
12827 // precedence equal to or greater than binop, or by using parentheses around
12828 // expr or subexpressions of expr.
12829 // * For forms that allow multiple occurrences of x, the number of times
12830 // that x is evaluated is unspecified.
12831 if (AtomicKind == OMPC_read) {
12832 enum {
12833 NotAnExpression,
12834 NotAnAssignmentOp,
12835 NotAScalarType,
12836 NotAnLValue,
12837 NoError
12838 } ErrorFound = NoError;
12839 SourceLocation ErrorLoc, NoteLoc;
12840 SourceRange ErrorRange, NoteRange;
12841 // If clause is read:
12842 // v = x;
12843 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12844 const auto *AtomicBinOp =
12845 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12846 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12847 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12848 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12849 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12850 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12851 if (!X->isLValue() || !V->isLValue()) {
12852 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12853 ErrorFound = NotAnLValue;
12854 ErrorLoc = AtomicBinOp->getExprLoc();
12855 ErrorRange = AtomicBinOp->getSourceRange();
12856 NoteLoc = NotLValueExpr->getExprLoc();
12857 NoteRange = NotLValueExpr->getSourceRange();
12858 }
12859 } else if (!X->isInstantiationDependent() ||
12860 !V->isInstantiationDependent()) {
12861 const Expr *NotScalarExpr =
12862 (X->isInstantiationDependent() || X->getType()->isScalarType())
12863 ? V
12864 : X;
12865 ErrorFound = NotAScalarType;
12866 ErrorLoc = AtomicBinOp->getExprLoc();
12867 ErrorRange = AtomicBinOp->getSourceRange();
12868 NoteLoc = NotScalarExpr->getExprLoc();
12869 NoteRange = NotScalarExpr->getSourceRange();
12870 }
12871 } else if (!AtomicBody->isInstantiationDependent()) {
12872 ErrorFound = NotAnAssignmentOp;
12873 ErrorLoc = AtomicBody->getExprLoc();
12874 ErrorRange = AtomicBody->getSourceRange();
12875 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12876 : AtomicBody->getExprLoc();
12877 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12878 : AtomicBody->getSourceRange();
12879 }
12880 } else {
12881 ErrorFound = NotAnExpression;
12882 NoteLoc = ErrorLoc = Body->getBeginLoc();
12883 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12884 }
12885 if (ErrorFound != NoError) {
12886 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12887 << ErrorRange;
12888 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12889 << ErrorFound << NoteRange;
12890 return StmtError();
12891 }
12892 if (SemaRef.CurContext->isDependentContext())
12893 V = X = nullptr;
12894 } else if (AtomicKind == OMPC_write) {
12895 enum {
12896 NotAnExpression,
12897 NotAnAssignmentOp,
12898 NotAScalarType,
12899 NotAnLValue,
12900 NoError
12901 } ErrorFound = NoError;
12902 SourceLocation ErrorLoc, NoteLoc;
12903 SourceRange ErrorRange, NoteRange;
12904 // If clause is write:
12905 // x = expr;
12906 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12907 const auto *AtomicBinOp =
12908 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12909 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12910 X = AtomicBinOp->getLHS();
12911 E = AtomicBinOp->getRHS();
12912 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12913 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
12914 if (!X->isLValue()) {
12915 ErrorFound = NotAnLValue;
12916 ErrorLoc = AtomicBinOp->getExprLoc();
12917 ErrorRange = AtomicBinOp->getSourceRange();
12918 NoteLoc = X->getExprLoc();
12919 NoteRange = X->getSourceRange();
12920 }
12921 } else if (!X->isInstantiationDependent() ||
12923 const Expr *NotScalarExpr =
12924 (X->isInstantiationDependent() || X->getType()->isScalarType())
12925 ? E
12926 : X;
12927 ErrorFound = NotAScalarType;
12928 ErrorLoc = AtomicBinOp->getExprLoc();
12929 ErrorRange = AtomicBinOp->getSourceRange();
12930 NoteLoc = NotScalarExpr->getExprLoc();
12931 NoteRange = NotScalarExpr->getSourceRange();
12932 }
12933 } else if (!AtomicBody->isInstantiationDependent()) {
12934 ErrorFound = NotAnAssignmentOp;
12935 ErrorLoc = AtomicBody->getExprLoc();
12936 ErrorRange = AtomicBody->getSourceRange();
12937 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12938 : AtomicBody->getExprLoc();
12939 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12940 : AtomicBody->getSourceRange();
12941 }
12942 } else {
12943 ErrorFound = NotAnExpression;
12944 NoteLoc = ErrorLoc = Body->getBeginLoc();
12945 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12946 }
12947 if (ErrorFound != NoError) {
12948 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12949 << ErrorRange;
12950 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12951 << ErrorFound << NoteRange;
12952 return StmtError();
12953 }
12954 if (SemaRef.CurContext->isDependentContext())
12955 E = X = nullptr;
12956 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12957 // If clause is update:
12958 // x++;
12959 // x--;
12960 // ++x;
12961 // --x;
12962 // x binop= expr;
12963 // x = x binop expr;
12964 // x = expr binop x;
12965 OpenMPAtomicUpdateChecker Checker(SemaRef);
12966 if (Checker.checkStatement(
12967 Body,
12968 (AtomicKind == OMPC_update)
12969 ? diag::err_omp_atomic_update_not_expression_statement
12970 : diag::err_omp_atomic_not_expression_statement,
12971 diag::note_omp_atomic_update))
12972 return StmtError();
12973 if (!SemaRef.CurContext->isDependentContext()) {
12974 E = Checker.getExpr();
12975 X = Checker.getX();
12976 UE = Checker.getUpdateExpr();
12977 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12978 }
12979 } else if (AtomicKind == OMPC_capture) {
12980 enum {
12981 NotAnAssignmentOp,
12982 NotACompoundStatement,
12983 NotTwoSubstatements,
12984 NotASpecificExpression,
12985 NoError
12986 } ErrorFound = NoError;
12987 SourceLocation ErrorLoc, NoteLoc;
12988 SourceRange ErrorRange, NoteRange;
12989 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12990 // If clause is a capture:
12991 // v = x++;
12992 // v = x--;
12993 // v = ++x;
12994 // v = --x;
12995 // v = x binop= expr;
12996 // v = x = x binop expr;
12997 // v = x = expr binop x;
12998 const auto *AtomicBinOp =
12999 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
13000 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
13001 V = AtomicBinOp->getLHS();
13002 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
13003 OpenMPAtomicUpdateChecker Checker(SemaRef);
13004 if (Checker.checkStatement(
13005 Body, diag::err_omp_atomic_capture_not_expression_statement,
13006 diag::note_omp_atomic_update))
13007 return StmtError();
13008 E = Checker.getExpr();
13009 X = Checker.getX();
13010 UE = Checker.getUpdateExpr();
13011 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13012 IsPostfixUpdate = Checker.isPostfixUpdate();
13013 } else if (!AtomicBody->isInstantiationDependent()) {
13014 ErrorLoc = AtomicBody->getExprLoc();
13015 ErrorRange = AtomicBody->getSourceRange();
13016 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13017 : AtomicBody->getExprLoc();
13018 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13019 : AtomicBody->getSourceRange();
13020 ErrorFound = NotAnAssignmentOp;
13021 }
13022 if (ErrorFound != NoError) {
13023 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
13024 << ErrorRange;
13025 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13026 return StmtError();
13027 }
13028 if (SemaRef.CurContext->isDependentContext())
13029 UE = V = E = X = nullptr;
13030 } else {
13031 // If clause is a capture:
13032 // { v = x; x = expr; }
13033 // { v = x; x++; }
13034 // { v = x; x--; }
13035 // { v = x; ++x; }
13036 // { v = x; --x; }
13037 // { v = x; x binop= expr; }
13038 // { v = x; x = x binop expr; }
13039 // { v = x; x = expr binop x; }
13040 // { x++; v = x; }
13041 // { x--; v = x; }
13042 // { ++x; v = x; }
13043 // { --x; v = x; }
13044 // { x binop= expr; v = x; }
13045 // { x = x binop expr; v = x; }
13046 // { x = expr binop x; v = x; }
13047 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
13048 // Check that this is { expr1; expr2; }
13049 if (CS->size() == 2) {
13050 Stmt *First = CS->body_front();
13051 Stmt *Second = CS->body_back();
13052 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
13053 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13054 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
13055 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13056 // Need to find what subexpression is 'v' and what is 'x'.
13057 OpenMPAtomicUpdateChecker Checker(SemaRef);
13058 bool IsUpdateExprFound = !Checker.checkStatement(Second);
13059 BinaryOperator *BinOp = nullptr;
13060 if (IsUpdateExprFound) {
13061 BinOp = dyn_cast<BinaryOperator>(First);
13062 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13063 }
13064 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
13065 // { v = x; x++; }
13066 // { v = x; x--; }
13067 // { v = x; ++x; }
13068 // { v = x; --x; }
13069 // { v = x; x binop= expr; }
13070 // { v = x; x = x binop expr; }
13071 // { v = x; x = expr binop x; }
13072 // Check that the first expression has form v = x.
13073 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13074 llvm::FoldingSetNodeID XId, PossibleXId;
13075 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13076 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13077 IsUpdateExprFound = XId == PossibleXId;
13078 if (IsUpdateExprFound) {
13079 V = BinOp->getLHS();
13080 X = Checker.getX();
13081 E = Checker.getExpr();
13082 UE = Checker.getUpdateExpr();
13083 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13084 IsPostfixUpdate = true;
13085 }
13086 }
13087 if (!IsUpdateExprFound) {
13088 IsUpdateExprFound = !Checker.checkStatement(First);
13089 BinOp = nullptr;
13090 if (IsUpdateExprFound) {
13091 BinOp = dyn_cast<BinaryOperator>(Second);
13092 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13093 }
13094 if (IsUpdateExprFound &&
13095 !SemaRef.CurContext->isDependentContext()) {
13096 // { x++; v = x; }
13097 // { x--; v = x; }
13098 // { ++x; v = x; }
13099 // { --x; v = x; }
13100 // { x binop= expr; v = x; }
13101 // { x = x binop expr; v = x; }
13102 // { x = expr binop x; v = x; }
13103 // Check that the second expression has form v = x.
13104 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13105 llvm::FoldingSetNodeID XId, PossibleXId;
13106 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13107 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13108 IsUpdateExprFound = XId == PossibleXId;
13109 if (IsUpdateExprFound) {
13110 V = BinOp->getLHS();
13111 X = Checker.getX();
13112 E = Checker.getExpr();
13113 UE = Checker.getUpdateExpr();
13114 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13115 IsPostfixUpdate = false;
13116 }
13117 }
13118 }
13119 if (!IsUpdateExprFound) {
13120 // { v = x; x = expr; }
13121 auto *FirstExpr = dyn_cast<Expr>(First);
13122 auto *SecondExpr = dyn_cast<Expr>(Second);
13123 if (!FirstExpr || !SecondExpr ||
13124 !(FirstExpr->isInstantiationDependent() ||
13125 SecondExpr->isInstantiationDependent())) {
13126 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
13127 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13128 ErrorFound = NotAnAssignmentOp;
13129 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13130 : First->getBeginLoc();
13131 NoteRange = ErrorRange = FirstBinOp
13132 ? FirstBinOp->getSourceRange()
13133 : SourceRange(ErrorLoc, ErrorLoc);
13134 } else {
13135 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
13136 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13137 ErrorFound = NotAnAssignmentOp;
13138 NoteLoc = ErrorLoc = SecondBinOp
13139 ? SecondBinOp->getOperatorLoc()
13140 : Second->getBeginLoc();
13141 NoteRange = ErrorRange =
13142 SecondBinOp ? SecondBinOp->getSourceRange()
13143 : SourceRange(ErrorLoc, ErrorLoc);
13144 } else {
13145 Expr *PossibleXRHSInFirst =
13146 FirstBinOp->getRHS()->IgnoreParenImpCasts();
13147 Expr *PossibleXLHSInSecond =
13148 SecondBinOp->getLHS()->IgnoreParenImpCasts();
13149 llvm::FoldingSetNodeID X1Id, X2Id;
13150 PossibleXRHSInFirst->Profile(X1Id, Context,
13151 /*Canonical=*/true);
13152 PossibleXLHSInSecond->Profile(X2Id, Context,
13153 /*Canonical=*/true);
13154 IsUpdateExprFound = X1Id == X2Id;
13155 if (IsUpdateExprFound) {
13156 V = FirstBinOp->getLHS();
13157 X = SecondBinOp->getLHS();
13158 E = SecondBinOp->getRHS();
13159 UE = nullptr;
13160 IsXLHSInRHSPart = false;
13161 IsPostfixUpdate = true;
13162 } else {
13163 ErrorFound = NotASpecificExpression;
13164 ErrorLoc = FirstBinOp->getExprLoc();
13165 ErrorRange = FirstBinOp->getSourceRange();
13166 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13167 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13168 }
13169 }
13170 }
13171 }
13172 }
13173 } else {
13174 NoteLoc = ErrorLoc = Body->getBeginLoc();
13175 NoteRange = ErrorRange =
13176 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13177 ErrorFound = NotTwoSubstatements;
13178 }
13179 } else {
13180 NoteLoc = ErrorLoc = Body->getBeginLoc();
13181 NoteRange = ErrorRange =
13182 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13183 ErrorFound = NotACompoundStatement;
13184 }
13185 }
13186 if (ErrorFound != NoError) {
13187 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
13188 << ErrorRange;
13189 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13190 return StmtError();
13191 }
13192 if (SemaRef.CurContext->isDependentContext())
13193 UE = V = E = X = nullptr;
13194 } else if (AtomicKind == OMPC_compare) {
13195 if (IsCompareCapture) {
13196 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13197 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
13198 if (!Checker.checkStmt(Body, ErrorInfo)) {
13199 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
13200 << ErrorInfo.ErrorRange;
13201 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13202 << ErrorInfo.Error << ErrorInfo.NoteRange;
13203 return StmtError();
13204 }
13205 X = Checker.getX();
13206 E = Checker.getE();
13207 D = Checker.getD();
13208 CE = Checker.getCond();
13209 V = Checker.getV();
13210 R = Checker.getR();
13211 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13212 IsXLHSInRHSPart = Checker.isXBinopExpr();
13213 IsFailOnly = Checker.isFailOnly();
13214 IsPostfixUpdate = Checker.isPostfixUpdate();
13215 } else {
13216 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13217 OpenMPAtomicCompareChecker Checker(SemaRef);
13218 if (!Checker.checkStmt(Body, ErrorInfo)) {
13219 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
13220 << ErrorInfo.ErrorRange;
13221 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13222 << ErrorInfo.Error << ErrorInfo.NoteRange;
13223 return StmtError();
13224 }
13225 X = Checker.getX();
13226 E = Checker.getE();
13227 D = Checker.getD();
13228 CE = Checker.getCond();
13229 // The weak clause may only appear if the resulting atomic operation is
13230 // an atomic conditional update for which the comparison tests for
13231 // equality. It was not possible to do this check in
13232 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
13233 // could not be performed (Clauses are not available).
13234 auto *It = find_if(Clauses, [](OMPClause *C) {
13235 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13236 });
13237 if (It != Clauses.end()) {
13238 auto *Cond = dyn_cast<BinaryOperator>(CE);
13239 if (Cond->getOpcode() != BO_EQ) {
13240 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13241 ErrorInfo.ErrorLoc = Cond->getExprLoc();
13242 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
13243 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
13244
13245 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
13246 << ErrorInfo.ErrorRange;
13247 return StmtError();
13248 }
13249 }
13250 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13251 IsXLHSInRHSPart = Checker.isXBinopExpr();
13252 }
13253 }
13254
13255 SemaRef.setFunctionHasBranchProtectedScope();
13256
13257 return OMPAtomicDirective::Create(
13258 Context, StartLoc, EndLoc, Clauses, AStmt,
13259 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
13260}
13261
13263 Stmt *AStmt,
13264 SourceLocation StartLoc,
13265 SourceLocation EndLoc) {
13266 if (!AStmt)
13267 return StmtError();
13268
13269 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target, AStmt);
13270
13271 // OpenMP [2.16, Nesting of Regions]
13272 // If specified, a teams construct must be contained within a target
13273 // construct. That target construct must contain no statements or directives
13274 // outside of the teams construct.
13275 if (DSAStack->hasInnerTeamsRegion()) {
13276 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13277 bool OMPTeamsFound = true;
13278 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
13279 auto I = CS->body_begin();
13280 while (I != CS->body_end()) {
13281 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13282 bool IsTeams = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13283 if (!IsTeams || I != CS->body_begin()) {
13284 OMPTeamsFound = false;
13285 if (IsTeams && I != CS->body_begin()) {
13286 // This is the two teams case. Since the InnerTeamsRegionLoc will
13287 // point to this second one reset the iterator to the other teams.
13288 --I;
13289 }
13290 break;
13291 }
13292 ++I;
13293 }
13294 assert(I != CS->body_end() && "Not found statement");
13295 S = *I;
13296 } else {
13297 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13298 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13299 }
13300 if (!OMPTeamsFound) {
13301 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13302 Diag(DSAStack->getInnerTeamsRegionLoc(),
13303 diag::note_omp_nested_teams_construct_here);
13304 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
13306 return StmtError();
13307 }
13308 }
13309
13310 return OMPTargetDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13311 AStmt);
13312}
13313
13315 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13316 SourceLocation EndLoc) {
13317 if (!AStmt)
13318 return StmtError();
13319
13320 setBranchProtectedScope(SemaRef, OMPD_target_parallel, AStmt);
13321
13323 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
13324 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13325}
13326
13328 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13329 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13330 if (!AStmt)
13331 return StmtError();
13332
13333 CapturedStmt *CS =
13334 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for, AStmt);
13335
13336 OMPLoopBasedDirective::HelperExprs B;
13337 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13338 // define the nested loops number.
13339 unsigned NestedLoopCount =
13340 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13341 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13342 VarsWithImplicitDSA, B);
13343 if (NestedLoopCount == 0)
13344 return StmtError();
13345
13346 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13347 return StmtError();
13348
13350 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13351 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13352}
13353
13354/// Check for existence of a map clause in the list of clauses.
13356 const OpenMPClauseKind K) {
13357 return llvm::any_of(
13358 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13359}
13360
13361template <typename... Params>
13363 const Params... ClauseTypes) {
13364 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13365}
13366
13367/// Check if the variables in the mapping clause are externally visible.
13369 for (const OMPClause *C : Clauses) {
13370 if (auto *TC = dyn_cast<OMPToClause>(C))
13371 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13372 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13373 (VD->isExternallyVisible() &&
13374 VD->getVisibility() != HiddenVisibility);
13375 });
13376 else if (auto *FC = dyn_cast<OMPFromClause>(C))
13377 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13378 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13379 (VD->isExternallyVisible() &&
13380 VD->getVisibility() != HiddenVisibility);
13381 });
13382 }
13383
13384 return true;
13385}
13386
13389 Stmt *AStmt, SourceLocation StartLoc,
13390 SourceLocation EndLoc) {
13391 if (!AStmt)
13392 return StmtError();
13393
13394 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13395
13396 // OpenMP [2.12.2, target data Construct, Restrictions]
13397 // At least one map, use_device_addr or use_device_ptr clause must appear on
13398 // the directive.
13399 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13400 (getLangOpts().OpenMP < 50 ||
13401 !hasClauses(Clauses, OMPC_use_device_addr))) {
13402 StringRef Expected;
13403 if (getLangOpts().OpenMP < 50)
13404 Expected = "'map' or 'use_device_ptr'";
13405 else
13406 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13407 unsigned OMPVersion = getLangOpts().OpenMP;
13408 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13409 << Expected << getOpenMPDirectiveName(OMPD_target_data, OMPVersion);
13410 return StmtError();
13411 }
13412
13413 SemaRef.setFunctionHasBranchProtectedScope();
13414
13415 return OMPTargetDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13416 Clauses, AStmt);
13417}
13418
13420 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13421 SourceLocation EndLoc, Stmt *AStmt) {
13422 if (!AStmt)
13423 return StmtError();
13424
13425 setBranchProtectedScope(SemaRef, OMPD_target_enter_data, AStmt);
13426
13427 // OpenMP [2.10.2, Restrictions, p. 99]
13428 // At least one map clause must appear on the directive.
13429 if (!hasClauses(Clauses, OMPC_map)) {
13430 unsigned OMPVersion = getLangOpts().OpenMP;
13431 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13432 << "'map'"
13433 << getOpenMPDirectiveName(OMPD_target_enter_data, OMPVersion);
13434 return StmtError();
13435 }
13436
13437 return OMPTargetEnterDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13438 Clauses, AStmt);
13439}
13440
13442 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13443 SourceLocation EndLoc, Stmt *AStmt) {
13444 if (!AStmt)
13445 return StmtError();
13446
13447 setBranchProtectedScope(SemaRef, OMPD_target_exit_data, AStmt);
13448
13449 // OpenMP [2.10.3, Restrictions, p. 102]
13450 // At least one map clause must appear on the directive.
13451 if (!hasClauses(Clauses, OMPC_map)) {
13452 unsigned OMPVersion = getLangOpts().OpenMP;
13453 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13454 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data, OMPVersion);
13455 return StmtError();
13456 }
13457
13458 return OMPTargetExitDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13459 Clauses, AStmt);
13460}
13461
13463 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13464 SourceLocation EndLoc, Stmt *AStmt) {
13465 if (!AStmt)
13466 return StmtError();
13467
13468 setBranchProtectedScope(SemaRef, OMPD_target_update, AStmt);
13469
13470 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13471 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13472 return StmtError();
13473 }
13474
13475 if (!isClauseMappable(Clauses)) {
13476 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13477 return StmtError();
13478 }
13479
13480 return OMPTargetUpdateDirective::Create(getASTContext(), StartLoc, EndLoc,
13481 Clauses, AStmt);
13482}
13483
13484/// This checks whether a \p ClauseType clause \p C has at most \p Max
13485/// expression. If not, a diag of number \p Diag will be emitted.
13486template <typename ClauseType>
13487static bool checkNumExprsInClause(SemaBase &SemaRef,
13488 ArrayRef<OMPClause *> Clauses,
13489 unsigned MaxNum, unsigned Diag) {
13490 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13491 if (ClauseItr == Clauses.end())
13492 return true;
13493 const auto *C = cast<ClauseType>(*ClauseItr);
13494 auto VarList = C->getVarRefs();
13495 if (VarList.size() > MaxNum) {
13496 SemaRef.Diag(VarList[MaxNum]->getBeginLoc(), Diag)
13497 << getOpenMPClauseNameForDiag(C->getClauseKind());
13498 return false;
13499 }
13500 return true;
13501}
13502
13504 Stmt *AStmt,
13505 SourceLocation StartLoc,
13506 SourceLocation EndLoc) {
13507 if (!AStmt)
13508 return StmtError();
13509
13511 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
13513 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
13514 return StmtError();
13515
13516 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13517 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13518 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13519
13520 setBranchProtectedScope(SemaRef, OMPD_teams, AStmt);
13521
13522 DSAStack->setParentTeamsRegionLoc(StartLoc);
13523
13524 return OMPTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13525 AStmt);
13526}
13527
13529 SourceLocation StartLoc, SourceLocation EndLoc,
13530 OpenMPDirectiveKind CancelRegion) {
13531 if (DSAStack->isParentNowaitRegion()) {
13532 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13533 return StmtError();
13534 }
13535 if (DSAStack->isParentOrderedRegion()) {
13536 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13537 return StmtError();
13538 }
13540 EndLoc, CancelRegion);
13541}
13542
13544 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13545 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13546 if (DSAStack->isParentNowaitRegion()) {
13547 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13548 return StmtError();
13549 }
13550 if (DSAStack->isParentOrderedRegion()) {
13551 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13552 return StmtError();
13553 }
13554 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13555 return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13556 CancelRegion);
13557}
13558
13560 ArrayRef<OMPClause *> Clauses) {
13561 const OMPClause *ReductionClause = nullptr;
13562 const OMPClause *NogroupClause = nullptr;
13563 for (const OMPClause *C : Clauses) {
13564 if (C->getClauseKind() == OMPC_reduction) {
13565 ReductionClause = C;
13566 if (NogroupClause)
13567 break;
13568 continue;
13569 }
13570 if (C->getClauseKind() == OMPC_nogroup) {
13571 NogroupClause = C;
13572 if (ReductionClause)
13573 break;
13574 continue;
13575 }
13576 }
13577 if (ReductionClause && NogroupClause) {
13578 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13579 << SourceRange(NogroupClause->getBeginLoc(),
13580 NogroupClause->getEndLoc());
13581 return true;
13582 }
13583 return false;
13584}
13585
13587 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13588 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13589 if (!AStmt)
13590 return StmtError();
13591
13592 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13593 OMPLoopBasedDirective::HelperExprs B;
13594 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13595 // define the nested loops number.
13596 unsigned NestedLoopCount =
13597 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13598 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13599 *DSAStack, VarsWithImplicitDSA, B);
13600 if (NestedLoopCount == 0)
13601 return StmtError();
13602
13603 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13604 "omp for loop exprs were not built");
13605
13606 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13607 // The grainsize clause and num_tasks clause are mutually exclusive and may
13608 // not appear on the same taskloop directive.
13610 {OMPC_grainsize, OMPC_num_tasks}))
13611 return StmtError();
13612 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13613 // If a reduction clause is present on the taskloop directive, the nogroup
13614 // clause must not be specified.
13616 return StmtError();
13617
13618 SemaRef.setFunctionHasBranchProtectedScope();
13619 return OMPTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13620 NestedLoopCount, Clauses, AStmt, B,
13621 DSAStack->isCancelRegion());
13622}
13623
13625 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13626 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13627 if (!AStmt)
13628 return StmtError();
13629
13630 CapturedStmt *CS =
13631 setBranchProtectedScope(SemaRef, OMPD_taskloop_simd, AStmt);
13632
13633 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13634 OMPLoopBasedDirective::HelperExprs B;
13635 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13636 // define the nested loops number.
13637 unsigned NestedLoopCount =
13638 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13639 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13640 VarsWithImplicitDSA, B);
13641 if (NestedLoopCount == 0)
13642 return StmtError();
13643
13644 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13645 return StmtError();
13646
13647 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13648 // The grainsize clause and num_tasks clause are mutually exclusive and may
13649 // not appear on the same taskloop directive.
13651 {OMPC_grainsize, OMPC_num_tasks}))
13652 return StmtError();
13653 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13654 // If a reduction clause is present on the taskloop directive, the nogroup
13655 // clause must not be specified.
13657 return StmtError();
13659 return StmtError();
13660
13661 return OMPTaskLoopSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13662 NestedLoopCount, Clauses, AStmt, B);
13663}
13664
13666 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13667 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13668 if (!AStmt)
13669 return StmtError();
13670
13671 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13672 OMPLoopBasedDirective::HelperExprs B;
13673 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13674 // define the nested loops number.
13675 unsigned NestedLoopCount =
13676 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13677 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13678 *DSAStack, VarsWithImplicitDSA, B);
13679 if (NestedLoopCount == 0)
13680 return StmtError();
13681
13682 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13683 "omp for loop exprs were not built");
13684
13685 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13686 // The grainsize clause and num_tasks clause are mutually exclusive and may
13687 // not appear on the same taskloop directive.
13689 {OMPC_grainsize, OMPC_num_tasks}))
13690 return StmtError();
13691 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13692 // If a reduction clause is present on the taskloop directive, the nogroup
13693 // clause must not be specified.
13695 return StmtError();
13696
13697 SemaRef.setFunctionHasBranchProtectedScope();
13698 return OMPMasterTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13699 NestedLoopCount, Clauses, AStmt, B,
13700 DSAStack->isCancelRegion());
13701}
13702
13704 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13705 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13706 if (!AStmt)
13707 return StmtError();
13708
13709 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13710 OMPLoopBasedDirective::HelperExprs B;
13711 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13712 // define the nested loops number.
13713 unsigned NestedLoopCount =
13714 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13715 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13716 *DSAStack, VarsWithImplicitDSA, B);
13717 if (NestedLoopCount == 0)
13718 return StmtError();
13719
13720 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13721 "omp for loop exprs were not built");
13722
13723 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13724 // The grainsize clause and num_tasks clause are mutually exclusive and may
13725 // not appear on the same taskloop directive.
13727 {OMPC_grainsize, OMPC_num_tasks}))
13728 return StmtError();
13729 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13730 // If a reduction clause is present on the taskloop directive, the nogroup
13731 // clause must not be specified.
13733 return StmtError();
13734
13735 SemaRef.setFunctionHasBranchProtectedScope();
13736 return OMPMaskedTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13737 NestedLoopCount, Clauses, AStmt, B,
13738 DSAStack->isCancelRegion());
13739}
13740
13742 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13743 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13744 if (!AStmt)
13745 return StmtError();
13746
13747 CapturedStmt *CS =
13748 setBranchProtectedScope(SemaRef, OMPD_master_taskloop_simd, AStmt);
13749
13750 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13751 OMPLoopBasedDirective::HelperExprs B;
13752 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13753 // define the nested loops number.
13754 unsigned NestedLoopCount =
13755 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13756 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13757 VarsWithImplicitDSA, B);
13758 if (NestedLoopCount == 0)
13759 return StmtError();
13760
13761 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13762 return StmtError();
13763
13764 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13765 // The grainsize clause and num_tasks clause are mutually exclusive and may
13766 // not appear on the same taskloop directive.
13768 {OMPC_grainsize, OMPC_num_tasks}))
13769 return StmtError();
13770 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13771 // If a reduction clause is present on the taskloop directive, the nogroup
13772 // clause must not be specified.
13774 return StmtError();
13776 return StmtError();
13777
13779 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13780}
13781
13783 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13784 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13785 if (!AStmt)
13786 return StmtError();
13787
13788 CapturedStmt *CS =
13789 setBranchProtectedScope(SemaRef, OMPD_masked_taskloop_simd, AStmt);
13790
13791 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13792 OMPLoopBasedDirective::HelperExprs B;
13793 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13794 // define the nested loops number.
13795 unsigned NestedLoopCount =
13796 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13797 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13798 VarsWithImplicitDSA, B);
13799 if (NestedLoopCount == 0)
13800 return StmtError();
13801
13802 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13803 return StmtError();
13804
13805 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13806 // The grainsize clause and num_tasks clause are mutually exclusive and may
13807 // not appear on the same taskloop directive.
13809 {OMPC_grainsize, OMPC_num_tasks}))
13810 return StmtError();
13811 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13812 // If a reduction clause is present on the taskloop directive, the nogroup
13813 // clause must not be specified.
13815 return StmtError();
13817 return StmtError();
13818
13820 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13821}
13822
13824 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13825 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13826 if (!AStmt)
13827 return StmtError();
13828
13829 CapturedStmt *CS =
13830 setBranchProtectedScope(SemaRef, OMPD_parallel_master_taskloop, AStmt);
13831
13832 OMPLoopBasedDirective::HelperExprs B;
13833 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13834 // define the nested loops number.
13835 unsigned NestedLoopCount = checkOpenMPLoop(
13836 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13837 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13838 VarsWithImplicitDSA, B);
13839 if (NestedLoopCount == 0)
13840 return StmtError();
13841
13842 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13843 "omp for loop exprs were not built");
13844
13845 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13846 // The grainsize clause and num_tasks clause are mutually exclusive and may
13847 // not appear on the same taskloop directive.
13849 {OMPC_grainsize, OMPC_num_tasks}))
13850 return StmtError();
13851 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13852 // If a reduction clause is present on the taskloop directive, the nogroup
13853 // clause must not be specified.
13855 return StmtError();
13856
13858 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13859 DSAStack->isCancelRegion());
13860}
13861
13863 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13864 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13865 if (!AStmt)
13866 return StmtError();
13867
13868 CapturedStmt *CS =
13869 setBranchProtectedScope(SemaRef, OMPD_parallel_masked_taskloop, AStmt);
13870
13871 OMPLoopBasedDirective::HelperExprs B;
13872 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13873 // define the nested loops number.
13874 unsigned NestedLoopCount = checkOpenMPLoop(
13875 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13876 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13877 VarsWithImplicitDSA, B);
13878 if (NestedLoopCount == 0)
13879 return StmtError();
13880
13881 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13882 "omp for loop exprs were not built");
13883
13884 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13885 // The grainsize clause and num_tasks clause are mutually exclusive and may
13886 // not appear on the same taskloop directive.
13888 {OMPC_grainsize, OMPC_num_tasks}))
13889 return StmtError();
13890 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13891 // If a reduction clause is present on the taskloop directive, the nogroup
13892 // clause must not be specified.
13894 return StmtError();
13895
13897 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13898 DSAStack->isCancelRegion());
13899}
13900
13902 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13903 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13904 if (!AStmt)
13905 return StmtError();
13906
13908 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13909
13910 OMPLoopBasedDirective::HelperExprs B;
13911 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13912 // define the nested loops number.
13913 unsigned NestedLoopCount = checkOpenMPLoop(
13914 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13915 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13916 VarsWithImplicitDSA, B);
13917 if (NestedLoopCount == 0)
13918 return StmtError();
13919
13920 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13921 return StmtError();
13922
13923 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13924 // The grainsize clause and num_tasks clause are mutually exclusive and may
13925 // not appear on the same taskloop directive.
13927 {OMPC_grainsize, OMPC_num_tasks}))
13928 return StmtError();
13929 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13930 // If a reduction clause is present on the taskloop directive, the nogroup
13931 // clause must not be specified.
13933 return StmtError();
13935 return StmtError();
13936
13938 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13939}
13940
13942 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13943 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13944 if (!AStmt)
13945 return StmtError();
13946
13948 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13949
13950 OMPLoopBasedDirective::HelperExprs B;
13951 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13952 // define the nested loops number.
13953 unsigned NestedLoopCount = checkOpenMPLoop(
13954 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13955 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13956 VarsWithImplicitDSA, B);
13957 if (NestedLoopCount == 0)
13958 return StmtError();
13959
13960 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13961 return StmtError();
13962
13963 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13964 // The grainsize clause and num_tasks clause are mutually exclusive and may
13965 // not appear on the same taskloop directive.
13967 {OMPC_grainsize, OMPC_num_tasks}))
13968 return StmtError();
13969 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13970 // If a reduction clause is present on the taskloop directive, the nogroup
13971 // clause must not be specified.
13973 return StmtError();
13975 return StmtError();
13976
13978 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13979}
13980
13982 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13983 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13984 if (!AStmt)
13985 return StmtError();
13986
13987 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13988 OMPLoopBasedDirective::HelperExprs B;
13989 // In presence of clause 'collapse' with number of loops, it will
13990 // define the nested loops number.
13991 unsigned NestedLoopCount =
13992 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
13993 nullptr /*ordered not a clause on distribute*/, AStmt,
13994 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13995 if (NestedLoopCount == 0)
13996 return StmtError();
13997
13998 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13999 "omp for loop exprs were not built");
14000
14001 SemaRef.setFunctionHasBranchProtectedScope();
14002 auto *DistributeDirective = OMPDistributeDirective::Create(
14003 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14004 return DistributeDirective;
14005}
14006
14008 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14009 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14010 if (!AStmt)
14011 return StmtError();
14012
14013 CapturedStmt *CS =
14014 setBranchProtectedScope(SemaRef, OMPD_distribute_parallel_for, AStmt);
14015
14016 OMPLoopBasedDirective::HelperExprs B;
14017 // In presence of clause 'collapse' with number of loops, it will
14018 // define the nested loops number.
14019 unsigned NestedLoopCount = checkOpenMPLoop(
14020 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14021 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14022 VarsWithImplicitDSA, B);
14023 if (NestedLoopCount == 0)
14024 return StmtError();
14025
14026 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14027 "omp for loop exprs were not built");
14028
14030 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14031 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14032}
14033
14035 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14036 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14037 if (!AStmt)
14038 return StmtError();
14039
14041 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
14042
14043 OMPLoopBasedDirective::HelperExprs B;
14044 // In presence of clause 'collapse' with number of loops, it will
14045 // define the nested loops number.
14046 unsigned NestedLoopCount = checkOpenMPLoop(
14047 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14048 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14049 VarsWithImplicitDSA, B);
14050 if (NestedLoopCount == 0)
14051 return StmtError();
14052
14053 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14054 return StmtError();
14055
14057 return StmtError();
14058
14060 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14061}
14062
14064 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14065 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14066 if (!AStmt)
14067 return StmtError();
14068
14069 CapturedStmt *CS =
14070 setBranchProtectedScope(SemaRef, OMPD_distribute_simd, AStmt);
14071
14072 OMPLoopBasedDirective::HelperExprs B;
14073 // In presence of clause 'collapse' with number of loops, it will
14074 // define the nested loops number.
14075 unsigned NestedLoopCount =
14076 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
14077 nullptr /*ordered not a clause on distribute*/, CS,
14078 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14079 if (NestedLoopCount == 0)
14080 return StmtError();
14081
14082 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14083 return StmtError();
14084
14086 return StmtError();
14087
14088 return OMPDistributeSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
14089 NestedLoopCount, Clauses, AStmt, B);
14090}
14091
14093 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14094 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14095 if (!AStmt)
14096 return StmtError();
14097
14098 CapturedStmt *CS =
14099 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for_simd, AStmt);
14100
14101 OMPLoopBasedDirective::HelperExprs B;
14102 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14103 // define the nested loops number.
14104 unsigned NestedLoopCount = checkOpenMPLoop(
14105 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
14106 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
14107 VarsWithImplicitDSA, B);
14108 if (NestedLoopCount == 0)
14109 return StmtError();
14110
14111 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14112 return StmtError();
14113
14115 return StmtError();
14116
14118 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14119}
14120
14122 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14123 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14124 if (!AStmt)
14125 return StmtError();
14126
14127 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target_simd, AStmt);
14128
14129 OMPLoopBasedDirective::HelperExprs B;
14130 // In presence of clause 'collapse' with number of loops, it will define the
14131 // nested loops number.
14132 unsigned NestedLoopCount =
14133 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
14134 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
14135 VarsWithImplicitDSA, B);
14136 if (NestedLoopCount == 0)
14137 return StmtError();
14138
14139 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14140 return StmtError();
14141
14143 return StmtError();
14144
14145 return OMPTargetSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
14146 NestedLoopCount, Clauses, AStmt, B);
14147}
14148
14150 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14151 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14152 if (!AStmt)
14153 return StmtError();
14154
14155 CapturedStmt *CS =
14156 setBranchProtectedScope(SemaRef, OMPD_teams_distribute, AStmt);
14157
14158 OMPLoopBasedDirective::HelperExprs B;
14159 // In presence of clause 'collapse' with number of loops, it will
14160 // define the nested loops number.
14161 unsigned NestedLoopCount =
14162 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
14163 nullptr /*ordered not a clause on distribute*/, CS,
14164 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14165 if (NestedLoopCount == 0)
14166 return StmtError();
14167
14168 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14169 "omp teams distribute loop exprs were not built");
14170
14171 DSAStack->setParentTeamsRegionLoc(StartLoc);
14172
14174 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14175}
14176
14178 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14179 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14180 if (!AStmt)
14181 return StmtError();
14182
14183 CapturedStmt *CS =
14184 setBranchProtectedScope(SemaRef, OMPD_teams_distribute_simd, AStmt);
14185
14186 OMPLoopBasedDirective::HelperExprs B;
14187 // In presence of clause 'collapse' with number of loops, it will
14188 // define the nested loops number.
14189 unsigned NestedLoopCount = checkOpenMPLoop(
14190 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14191 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14192 VarsWithImplicitDSA, B);
14193 if (NestedLoopCount == 0)
14194 return StmtError();
14195
14196 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14197 return StmtError();
14198
14200 return StmtError();
14201
14202 DSAStack->setParentTeamsRegionLoc(StartLoc);
14203
14205 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14206}
14207
14209 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14210 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14211 if (!AStmt)
14212 return StmtError();
14213
14215 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
14216
14217 OMPLoopBasedDirective::HelperExprs B;
14218 // In presence of clause 'collapse' with number of loops, it will
14219 // define the nested loops number.
14220 unsigned NestedLoopCount = checkOpenMPLoop(
14221 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14222 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14223 VarsWithImplicitDSA, B);
14224 if (NestedLoopCount == 0)
14225 return StmtError();
14226
14227 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14228 return StmtError();
14229
14231 return StmtError();
14232
14233 DSAStack->setParentTeamsRegionLoc(StartLoc);
14234
14236 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14237}
14238
14240 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14241 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14242 if (!AStmt)
14243 return StmtError();
14244
14246 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
14247
14248 OMPLoopBasedDirective::HelperExprs B;
14249 // In presence of clause 'collapse' with number of loops, it will
14250 // define the nested loops number.
14251 unsigned NestedLoopCount = checkOpenMPLoop(
14252 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14253 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14254 VarsWithImplicitDSA, B);
14255
14256 if (NestedLoopCount == 0)
14257 return StmtError();
14258
14259 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14260 "omp for loop exprs were not built");
14261
14262 DSAStack->setParentTeamsRegionLoc(StartLoc);
14263
14265 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14266 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14267}
14268
14270 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14271 SourceLocation EndLoc) {
14272 if (!AStmt)
14273 return StmtError();
14274
14275 setBranchProtectedScope(SemaRef, OMPD_target_teams, AStmt);
14276
14277 const OMPClause *BareClause = nullptr;
14278 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) &&
14279 hasClauses(Clauses, OMPC_thread_limit);
14280 bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) {
14281 BareClause = C;
14282 return C->getClauseKind() == OMPC_ompx_bare;
14283 });
14284
14285 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14286 Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
14287 return StmtError();
14288 }
14289
14290 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
14291 unsigned DiagNo = HasBareClause
14292 ? diag::err_ompx_more_than_three_expr_not_allowed
14293 : diag::err_omp_multi_expr_not_allowed;
14294 if (!checkNumExprsInClause<OMPNumTeamsClause>(*this, Clauses,
14295 ClauseMaxNumExprs, DiagNo) ||
14297 ClauseMaxNumExprs, DiagNo))
14298 return StmtError();
14299
14300 return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc,
14301 Clauses, AStmt);
14302}
14303
14305 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14306 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14307 if (!AStmt)
14308 return StmtError();
14309
14311 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14313 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14314 return StmtError();
14315
14316 CapturedStmt *CS =
14317 setBranchProtectedScope(SemaRef, OMPD_target_teams_distribute, AStmt);
14318
14319 OMPLoopBasedDirective::HelperExprs B;
14320 // In presence of clause 'collapse' with number of loops, it will
14321 // define the nested loops number.
14322 unsigned NestedLoopCount = checkOpenMPLoop(
14323 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14324 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14325 VarsWithImplicitDSA, B);
14326 if (NestedLoopCount == 0)
14327 return StmtError();
14328
14329 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14330 "omp target teams distribute loop exprs were not built");
14331
14333 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14334}
14335
14337 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14338 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14339 if (!AStmt)
14340 return StmtError();
14341
14343 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14345 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14346 return StmtError();
14347
14349 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14350
14351 OMPLoopBasedDirective::HelperExprs B;
14352 // In presence of clause 'collapse' with number of loops, it will
14353 // define the nested loops number.
14354 unsigned NestedLoopCount = checkOpenMPLoop(
14355 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14356 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14357 VarsWithImplicitDSA, B);
14358 if (NestedLoopCount == 0)
14359 return StmtError();
14360
14361 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14362 return StmtError();
14363
14365 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14366 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14367}
14368
14370 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14371 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14372 if (!AStmt)
14373 return StmtError();
14374
14376 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14378 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14379 return StmtError();
14380
14382 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14383
14384 OMPLoopBasedDirective::HelperExprs B;
14385 // In presence of clause 'collapse' with number of loops, it will
14386 // define the nested loops number.
14387 unsigned NestedLoopCount =
14388 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14389 getCollapseNumberExpr(Clauses),
14390 nullptr /*ordered not a clause on distribute*/, CS,
14391 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14392 if (NestedLoopCount == 0)
14393 return StmtError();
14394
14395 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14396 return StmtError();
14397
14399 return StmtError();
14400
14402 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14403}
14404
14406 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14407 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14408 if (!AStmt)
14409 return StmtError();
14410
14412 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14414 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14415 return StmtError();
14416
14418 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14419
14420 OMPLoopBasedDirective::HelperExprs B;
14421 // In presence of clause 'collapse' with number of loops, it will
14422 // define the nested loops number.
14423 unsigned NestedLoopCount = checkOpenMPLoop(
14424 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14425 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14426 VarsWithImplicitDSA, B);
14427 if (NestedLoopCount == 0)
14428 return StmtError();
14429
14430 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14431 return StmtError();
14432
14434 return StmtError();
14435
14437 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14438}
14439
14440/// Updates OriginalInits by checking Transform against loop transformation
14441/// directives and appending their pre-inits if a match is found.
14443 SmallVectorImpl<Stmt *> &PreInits) {
14444 Stmt *Dir = Transform->getDirective();
14445 switch (Dir->getStmtClass()) {
14446#define STMT(CLASS, PARENT)
14447#define ABSTRACT_STMT(CLASS)
14448#define COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT) \
14449 case Stmt::CLASS##Class: \
14450 appendFlattenedStmtList(PreInits, \
14451 static_cast<const CLASS *>(Dir)->getPreInits()); \
14452 break;
14453#define OMPCANONICALLOOPNESTTRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14454 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14455#define OMPCANONICALLOOPSEQUENCETRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14456 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14457#include "clang/AST/StmtNodes.inc"
14458#undef COMMON_OMP_LOOP_TRANSFORMATION
14459 default:
14460 llvm_unreachable("Not a loop transformation");
14461 }
14462}
14463
14464bool SemaOpenMP::checkTransformableLoopNest(
14465 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14467 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *>> &OriginalInits) {
14468 OriginalInits.emplace_back();
14469 bool Result = OMPLoopBasedDirective::doForAllLoops(
14470 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14471 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14472 Stmt *CurStmt) {
14473 VarsWithInheritedDSAType TmpDSA;
14474 unsigned SingleNumLoops =
14475 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14476 TmpDSA, LoopHelpers[Cnt]);
14477 if (SingleNumLoops == 0)
14478 return true;
14479 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14480 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14481 OriginalInits.back().push_back(For->getInit());
14482 Body = For->getBody();
14483 } else {
14484 assert(isa<CXXForRangeStmt>(CurStmt) &&
14485 "Expected canonical for or range-based for loops.");
14486 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14487 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14488 Body = CXXFor->getBody();
14489 }
14490 OriginalInits.emplace_back();
14491 return false;
14492 },
14493 [&OriginalInits](OMPLoopTransformationDirective *Transform) {
14494 updatePreInits(Transform, OriginalInits.back());
14495 });
14496 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14497 OriginalInits.pop_back();
14498 return Result;
14499}
14500
14501/// Counts the total number of OpenMP canonical nested loops, including the
14502/// outermost loop (the original loop). PRECONDITION of this visitor is that it
14503/// must be invoked from the original loop to be analyzed. The traversal stops
14504/// for Decl's and Expr's given that they may contain inner loops that must not
14505/// be counted.
14506///
14507/// Example AST structure for the code:
14508///
14509/// int main() {
14510/// #pragma omp fuse
14511/// {
14512/// for (int i = 0; i < 100; i++) { <-- Outer loop
14513/// []() {
14514/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (1)
14515/// };
14516/// for(int j = 0; j < 5; ++j) {} <-- Inner loop
14517/// }
14518/// for (int r = 0; i < 100; i++) { <-- Outer loop
14519/// struct LocalClass {
14520/// void bar() {
14521/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (2)
14522/// }
14523/// };
14524/// for(int k = 0; k < 10; ++k) {} <-- Inner loop
14525/// {x = 5; for(k = 0; k < 10; ++k) x += k; x}; <-- NOT A LOOP (3)
14526/// }
14527/// }
14528/// }
14529/// (1) because in a different function (here: a lambda)
14530/// (2) because in a different function (here: class method)
14531/// (3) because considered to be intervening-code of non-perfectly nested loop
14532/// Result: Loop 'i' contains 2 loops, Loop 'r' also contains 2 loops.
14534private:
14535 unsigned NestedLoopCount = 0;
14536
14537public:
14538 explicit NestedLoopCounterVisitor() = default;
14539
14540 unsigned getNestedLoopCount() const { return NestedLoopCount; }
14541
14542 bool VisitForStmt(ForStmt *FS) override {
14543 ++NestedLoopCount;
14544 return true;
14545 }
14546
14548 ++NestedLoopCount;
14549 return true;
14550 }
14551
14552 bool TraverseStmt(Stmt *S) override {
14553 if (!S)
14554 return true;
14555
14556 // Skip traversal of all expressions, including special cases like
14557 // LambdaExpr, StmtExpr, BlockExpr, and RequiresExpr. These expressions
14558 // may contain inner statements (and even loops), but they are not part
14559 // of the syntactic body of the surrounding loop structure.
14560 // Therefore must not be counted.
14561 if (isa<Expr>(S))
14562 return true;
14563
14564 // Only recurse into CompoundStmt (block {}) and loop bodies.
14567 }
14568
14569 // Stop traversal of the rest of statements, that break perfect
14570 // loop nesting, such as control flow (IfStmt, SwitchStmt...).
14571 return true;
14572 }
14573
14574 bool TraverseDecl(Decl *D) override {
14575 // Stop in the case of finding a declaration, it is not important
14576 // in order to find nested loops (Possible CXXRecordDecl, RecordDecl,
14577 // FunctionDecl...).
14578 return true;
14579 }
14580};
14581
14582bool SemaOpenMP::analyzeLoopSequence(Stmt *LoopSeqStmt,
14583 LoopSequenceAnalysis &SeqAnalysis,
14584 ASTContext &Context,
14585 OpenMPDirectiveKind Kind) {
14587 // Helper Lambda to handle storing initialization and body statements for
14588 // both ForStmt and CXXForRangeStmt.
14589 auto StoreLoopStatements = [](LoopAnalysis &Analysis, Stmt *LoopStmt) {
14590 if (auto *For = dyn_cast<ForStmt>(LoopStmt)) {
14591 Analysis.OriginalInits.push_back(For->getInit());
14592 Analysis.TheForStmt = For;
14593 } else {
14594 auto *CXXFor = cast<CXXForRangeStmt>(LoopStmt);
14595 Analysis.OriginalInits.push_back(CXXFor->getBeginStmt());
14596 Analysis.TheForStmt = CXXFor;
14597 }
14598 };
14599
14600 // Helper lambda functions to encapsulate the processing of different
14601 // derivations of the canonical loop sequence grammar
14602 // Modularized code for handling loop generation and transformations.
14603 auto AnalyzeLoopGeneration = [&](Stmt *Child) {
14604 auto *LoopTransform = cast<OMPLoopTransformationDirective>(Child);
14605 Stmt *TransformedStmt = LoopTransform->getTransformedStmt();
14606 unsigned NumGeneratedTopLevelLoops =
14607 LoopTransform->getNumGeneratedTopLevelLoops();
14608 // Handle the case where transformed statement is not available due to
14609 // dependent contexts
14610 if (!TransformedStmt) {
14611 if (NumGeneratedTopLevelLoops > 0) {
14612 SeqAnalysis.LoopSeqSize += NumGeneratedTopLevelLoops;
14613 return true;
14614 }
14615 // Unroll full (0 loops produced)
14616 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14617 << 0 << getOpenMPDirectiveName(Kind);
14618 return false;
14619 }
14620 // Handle loop transformations with multiple loop nests
14621 // Unroll full
14622 if (!NumGeneratedTopLevelLoops) {
14623 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14624 << 0 << getOpenMPDirectiveName(Kind);
14625 return false;
14626 }
14627 // Loop transformatons such as split or loopranged fuse
14628 if (NumGeneratedTopLevelLoops > 1) {
14629 // Get the preinits related to this loop sequence generating
14630 // loop transformation (i.e loopranged fuse, split...)
14631 // These preinits differ slightly from regular inits/pre-inits related
14632 // to single loop generating loop transformations (interchange, unroll)
14633 // given that they are not bounded to a particular loop nest
14634 // so they need to be treated independently
14635 updatePreInits(LoopTransform, SeqAnalysis.LoopSequencePreInits);
14636 return analyzeLoopSequence(TransformedStmt, SeqAnalysis, Context, Kind);
14637 }
14638 // Vast majority: (Tile, Unroll, Stripe, Reverse, Interchange, Fuse all)
14639 // Process the transformed loop statement
14640 LoopAnalysis &NewTransformedSingleLoop =
14641 SeqAnalysis.Loops.emplace_back(Child);
14642 unsigned IsCanonical = checkOpenMPLoop(
14643 Kind, nullptr, nullptr, TransformedStmt, SemaRef, *DSAStack, TmpDSA,
14644 NewTransformedSingleLoop.HelperExprs);
14645
14646 if (!IsCanonical)
14647 return false;
14648
14649 StoreLoopStatements(NewTransformedSingleLoop, TransformedStmt);
14650 updatePreInits(LoopTransform, NewTransformedSingleLoop.TransformsPreInits);
14651
14652 SeqAnalysis.LoopSeqSize++;
14653 return true;
14654 };
14655
14656 // Modularized code for handling regular canonical loops.
14657 auto AnalyzeRegularLoop = [&](Stmt *Child) {
14658 LoopAnalysis &NewRegularLoop = SeqAnalysis.Loops.emplace_back(Child);
14659 unsigned IsCanonical =
14660 checkOpenMPLoop(Kind, nullptr, nullptr, Child, SemaRef, *DSAStack,
14661 TmpDSA, NewRegularLoop.HelperExprs);
14662
14663 if (!IsCanonical)
14664 return false;
14665
14666 StoreLoopStatements(NewRegularLoop, Child);
14667 NestedLoopCounterVisitor NLCV;
14668 NLCV.TraverseStmt(Child);
14669 return true;
14670 };
14671
14672 // High level grammar validation.
14673 for (Stmt *Child : LoopSeqStmt->children()) {
14674 if (!Child)
14675 continue;
14676 // Skip over non-loop-sequence statements.
14677 if (!LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14678 Child = Child->IgnoreContainers();
14679 // Ignore empty compound statement.
14680 if (!Child)
14681 continue;
14682 // In the case of a nested loop sequence ignoring containers would not
14683 // be enough, a recurisve transversal of the loop sequence is required.
14684 if (isa<CompoundStmt>(Child)) {
14685 if (!analyzeLoopSequence(Child, SeqAnalysis, Context, Kind))
14686 return false;
14687 // Already been treated, skip this children
14688 continue;
14689 }
14690 }
14691 // Regular loop sequence handling.
14692 if (LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14693 if (LoopAnalysis::isLoopTransformation(Child)) {
14694 if (!AnalyzeLoopGeneration(Child))
14695 return false;
14696 // AnalyzeLoopGeneration updates SeqAnalysis.LoopSeqSize accordingly.
14697 } else {
14698 if (!AnalyzeRegularLoop(Child))
14699 return false;
14700 SeqAnalysis.LoopSeqSize++;
14701 }
14702 } else {
14703 // Report error for invalid statement inside canonical loop sequence.
14704 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14705 << 0 << getOpenMPDirectiveName(Kind);
14706 return false;
14707 }
14708 }
14709 return true;
14710}
14711
14712bool SemaOpenMP::checkTransformableLoopSequence(
14713 OpenMPDirectiveKind Kind, Stmt *AStmt, LoopSequenceAnalysis &SeqAnalysis,
14714 ASTContext &Context) {
14715 // Following OpenMP 6.0 API Specification, a Canonical Loop Sequence follows
14716 // the grammar:
14717 //
14718 // canonical-loop-sequence:
14719 // {
14720 // loop-sequence+
14721 // }
14722 // where loop-sequence can be any of the following:
14723 // 1. canonical-loop-sequence
14724 // 2. loop-nest
14725 // 3. loop-sequence-generating-construct (i.e OMPLoopTransformationDirective)
14726 //
14727 // To recognise and traverse this structure the helper function
14728 // analyzeLoopSequence serves as the recurisve entry point
14729 // and tries to match the input AST to the canonical loop sequence grammar
14730 // structure. This function will perform both a semantic and syntactical
14731 // analysis of the given statement according to OpenMP 6.0 definition of
14732 // the aforementioned canonical loop sequence.
14733
14734 // We expect an outer compound statement.
14735 if (!isa<CompoundStmt>(AStmt)) {
14736 Diag(AStmt->getBeginLoc(), diag::err_omp_not_a_loop_sequence)
14737 << getOpenMPDirectiveName(Kind);
14738 return false;
14739 }
14740
14741 // Recursive entry point to process the main loop sequence
14742 if (!analyzeLoopSequence(AStmt, SeqAnalysis, Context, Kind))
14743 return false;
14744
14745 // Diagnose an empty loop sequence.
14746 if (!SeqAnalysis.LoopSeqSize) {
14747 Diag(AStmt->getBeginLoc(), diag::err_omp_empty_loop_sequence)
14748 << getOpenMPDirectiveName(Kind);
14749 return false;
14750 }
14751 return true;
14752}
14753
14754/// Add preinit statements that need to be propagated from the selected loop.
14755static void addLoopPreInits(ASTContext &Context,
14756 OMPLoopBasedDirective::HelperExprs &LoopHelper,
14757 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
14758 SmallVectorImpl<Stmt *> &PreInits) {
14759
14760 // For range-based for-statements, ensure that their syntactic sugar is
14761 // executed by adding them as pre-init statements.
14762 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14763 Stmt *RangeInit = CXXRangeFor->getInit();
14764 if (RangeInit)
14765 PreInits.push_back(RangeInit);
14766
14767 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14768 PreInits.push_back(new (Context) DeclStmt(RangeStmt->getDeclGroup(),
14769 RangeStmt->getBeginLoc(),
14770 RangeStmt->getEndLoc()));
14771
14772 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14773 PreInits.push_back(new (Context) DeclStmt(RangeEnd->getDeclGroup(),
14774 RangeEnd->getBeginLoc(),
14775 RangeEnd->getEndLoc()));
14776 }
14777
14778 llvm::append_range(PreInits, OriginalInit);
14779
14780 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
14781 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
14782 PreInits.push_back(new (Context) DeclStmt(
14783 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14784 }
14785
14786 // Gather declarations for the data members used as counters.
14787 for (Expr *CounterRef : LoopHelper.Counters) {
14788 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14789 if (isa<OMPCapturedExprDecl>(CounterDecl))
14790 PreInits.push_back(new (Context) DeclStmt(
14791 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
14792 }
14793}
14794
14795/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
14796/// loop of a construct.
14797static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) {
14798 size_t NumLoops = LoopStmts.size();
14799 OMPLoopBasedDirective::doForAllLoops(
14800 AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
14801 [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
14802 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
14803 LoopStmts[Cnt] = CurStmt;
14804 return false;
14805 });
14806 assert(!is_contained(LoopStmts, nullptr) &&
14807 "Expecting a loop statement for each affected loop");
14808}
14809
14810/// Build and return a DeclRefExpr for the floor induction variable using the
14811/// SemaRef and the provided parameters.
14812static Expr *makeFloorIVRef(Sema &SemaRef, ArrayRef<VarDecl *> FloorIndVars,
14813 int I, QualType IVTy, DeclRefExpr *OrigCntVar) {
14814 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14815 OrigCntVar->getExprLoc());
14816}
14817
14819 Stmt *AStmt,
14820 SourceLocation StartLoc,
14821 SourceLocation EndLoc) {
14822 ASTContext &Context = getASTContext();
14823 Scope *CurScope = SemaRef.getCurScope();
14824
14825 const auto *SizesClause =
14826 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14827 if (!SizesClause ||
14828 llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; }))
14829 return StmtError();
14830 unsigned NumLoops = SizesClause->getNumSizes();
14831
14832 // Empty statement should only be possible if there already was an error.
14833 if (!AStmt)
14834 return StmtError();
14835
14836 // Verify and diagnose loop nest.
14838 Stmt *Body = nullptr;
14839 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
14840 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14841 OriginalInits))
14842 return StmtError();
14843
14844 // Delay tiling to when template is completely instantiated.
14845 if (SemaRef.CurContext->isDependentContext())
14846 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14847 NumLoops, AStmt, nullptr, nullptr);
14848
14849 assert(LoopHelpers.size() == NumLoops &&
14850 "Expecting loop iteration space dimensionality to match number of "
14851 "affected loops");
14852 assert(OriginalInits.size() == NumLoops &&
14853 "Expecting loop iteration space dimensionality to match number of "
14854 "affected loops");
14855
14856 // Collect all affected loop statements.
14857 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14858 collectLoopStmts(AStmt, LoopStmts);
14859
14860 SmallVector<Stmt *, 4> PreInits;
14861 CaptureVars CopyTransformer(SemaRef);
14862
14863 // Create iteration variables for the generated loops.
14864 SmallVector<VarDecl *, 4> FloorIndVars;
14865 SmallVector<VarDecl *, 4> TileIndVars;
14866 FloorIndVars.resize(NumLoops);
14867 TileIndVars.resize(NumLoops);
14868 for (unsigned I = 0; I < NumLoops; ++I) {
14869 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14870
14871 assert(LoopHelper.Counters.size() == 1 &&
14872 "Expect single-dimensional loop iteration space");
14873 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14874 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14875 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14876 QualType CntTy = IterVarRef->getType();
14877
14878 // Iteration variable for the floor (i.e. outer) loop.
14879 {
14880 std::string FloorCntName =
14881 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14882 VarDecl *FloorCntDecl =
14883 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14884 FloorIndVars[I] = FloorCntDecl;
14885 }
14886
14887 // Iteration variable for the tile (i.e. inner) loop.
14888 {
14889 std::string TileCntName =
14890 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14891
14892 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14893 // used by the expressions to derive the original iteration variable's
14894 // value from the logical iteration number.
14895 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14896 TileCntDecl->setDeclName(
14897 &SemaRef.PP.getIdentifierTable().get(TileCntName));
14898 TileIndVars[I] = TileCntDecl;
14899 }
14900
14901 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
14902 PreInits);
14903 }
14904
14905 // Once the original iteration values are set, append the innermost body.
14906 Stmt *Inner = Body;
14907
14908 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
14909 SizesClause, CurScope](int I) -> Expr * {
14910 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14911
14912 if (DimTileSizeExpr->containsErrors())
14913 return nullptr;
14914
14915 if (isa<ConstantExpr>(DimTileSizeExpr))
14916 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14917
14918 // When the tile size is not a constant but a variable, it is possible to
14919 // pass non-positive numbers. For instance:
14920 // \code{c}
14921 // int a = 0;
14922 // #pragma omp tile sizes(a)
14923 // for (int i = 0; i < 42; ++i)
14924 // body(i);
14925 // \endcode
14926 // Although there is no meaningful interpretation of the tile size, the body
14927 // should still be executed 42 times to avoid surprises. To preserve the
14928 // invariant that every loop iteration is executed exactly once and not
14929 // cause an infinite loop, apply a minimum tile size of one.
14930 // Build expr:
14931 // \code{c}
14932 // (TS <= 0) ? 1 : TS
14933 // \endcode
14934 QualType DimTy = DimTileSizeExpr->getType();
14935 uint64_t DimWidth = Context.getTypeSize(DimTy);
14937 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14938 IntegerLiteral *One =
14939 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
14940 Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
14941 CurScope, {}, BO_LE,
14942 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
14943 Expr *MinOne = new (Context) ConditionalOperator(
14944 Cond, {}, One, {},
14945 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14947 return MinOne;
14948 };
14949
14950 // Create tile loops from the inside to the outside.
14951 for (int I = NumLoops - 1; I >= 0; --I) {
14952 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14953 Expr *NumIterations = LoopHelper.NumIterations;
14954 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14955 QualType IVTy = NumIterations->getType();
14956 Stmt *LoopStmt = LoopStmts[I];
14957
14958 // Commonly used variables. One of the constraints of an AST is that every
14959 // node object must appear at most once, hence we define a lambda that
14960 // creates a new AST node at every use.
14961 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
14962 OrigCntVar]() {
14963 return buildDeclRefExpr(SemaRef, TileIndVars[I], IVTy,
14964 OrigCntVar->getExprLoc());
14965 };
14966
14967 // For init-statement: auto .tile.iv = .floor.iv
14968 SemaRef.AddInitializerToDecl(
14969 TileIndVars[I],
14970 SemaRef
14971 .DefaultLvalueConversion(
14972 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
14973 .get(),
14974 /*DirectInit=*/false);
14975 Decl *CounterDecl = TileIndVars[I];
14976 StmtResult InitStmt = new (Context)
14977 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14978 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14979 if (!InitStmt.isUsable())
14980 return StmtError();
14981
14982 // For cond-expression:
14983 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
14984 Expr *DimTileSize = MakeDimTileSize(I);
14985 if (!DimTileSize)
14986 return StmtError();
14987 ExprResult EndOfTile = SemaRef.BuildBinOp(
14988 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14989 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14990 DimTileSize);
14991 if (!EndOfTile.isUsable())
14992 return StmtError();
14993 ExprResult IsPartialTile =
14994 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14995 NumIterations, EndOfTile.get());
14996 if (!IsPartialTile.isUsable())
14997 return StmtError();
14998 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
14999 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15000 IsPartialTile.get(), NumIterations, EndOfTile.get());
15001 if (!MinTileAndIterSpace.isUsable())
15002 return StmtError();
15003 ExprResult CondExpr =
15004 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15005 MakeTileIVRef(), MinTileAndIterSpace.get());
15006 if (!CondExpr.isUsable())
15007 return StmtError();
15008
15009 // For incr-statement: ++.tile.iv
15010 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15011 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
15012 if (!IncrStmt.isUsable())
15013 return StmtError();
15014
15015 // Statements to set the original iteration variable's value from the
15016 // logical iteration number.
15017 // Generated for loop is:
15018 // \code
15019 // Original_for_init;
15020 // for (auto .tile.iv = .floor.iv;
15021 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
15022 // ++.tile.iv) {
15023 // Original_Body;
15024 // Original_counter_update;
15025 // }
15026 // \endcode
15027 // FIXME: If the innermost body is an loop itself, inserting these
15028 // statements stops it being recognized as a perfectly nested loop (e.g.
15029 // for applying tiling again). If this is the case, sink the expressions
15030 // further into the inner loop.
15031 SmallVector<Stmt *, 4> BodyParts;
15032 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15033 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15034 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15035 BodyParts.push_back(Inner);
15036 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15037 Inner->getBeginLoc(), Inner->getEndLoc());
15038 Inner = new (Context)
15039 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15040 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15041 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15042 }
15043
15044 // Create floor loops from the inside to the outside.
15045 for (int I = NumLoops - 1; I >= 0; --I) {
15046 auto &LoopHelper = LoopHelpers[I];
15047 Expr *NumIterations = LoopHelper.NumIterations;
15048 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15049 QualType IVTy = NumIterations->getType();
15050
15051 // For init-statement: auto .floor.iv = 0
15052 SemaRef.AddInitializerToDecl(
15053 FloorIndVars[I],
15054 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15055 /*DirectInit=*/false);
15056 Decl *CounterDecl = FloorIndVars[I];
15057 StmtResult InitStmt = new (Context)
15058 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15059 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15060 if (!InitStmt.isUsable())
15061 return StmtError();
15062
15063 // For cond-expression: .floor.iv < NumIterations
15064 ExprResult CondExpr = SemaRef.BuildBinOp(
15065 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15066 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15067 NumIterations);
15068 if (!CondExpr.isUsable())
15069 return StmtError();
15070
15071 // For incr-statement: .floor.iv += DimTileSize
15072 Expr *DimTileSize = MakeDimTileSize(I);
15073 if (!DimTileSize)
15074 return StmtError();
15075 ExprResult IncrStmt = SemaRef.BuildBinOp(
15076 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15077 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15078 DimTileSize);
15079 if (!IncrStmt.isUsable())
15080 return StmtError();
15081
15082 Inner = new (Context)
15083 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15084 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15085 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15086 }
15087
15088 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
15089 AStmt, Inner,
15090 buildPreInits(Context, PreInits));
15091}
15092
15094 Stmt *AStmt,
15095 SourceLocation StartLoc,
15096 SourceLocation EndLoc) {
15097 ASTContext &Context = getASTContext();
15098 Scope *CurScope = SemaRef.getCurScope();
15099
15100 const auto *SizesClause =
15101 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
15102 if (!SizesClause ||
15103 llvm::any_of(SizesClause->getSizesRefs(), [](const Expr *SizeExpr) {
15104 return !SizeExpr || SizeExpr->containsErrors();
15105 }))
15106 return StmtError();
15107 unsigned NumLoops = SizesClause->getNumSizes();
15108
15109 // Empty statement should only be possible if there already was an error.
15110 if (!AStmt)
15111 return StmtError();
15112
15113 // Verify and diagnose loop nest.
15115 Stmt *Body = nullptr;
15116 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
15117 if (!checkTransformableLoopNest(OMPD_stripe, AStmt, NumLoops, LoopHelpers,
15118 Body, OriginalInits))
15119 return StmtError();
15120
15121 // Delay striping to when template is completely instantiated.
15122 if (SemaRef.CurContext->isDependentContext())
15123 return OMPStripeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15124 NumLoops, AStmt, nullptr, nullptr);
15125
15126 assert(LoopHelpers.size() == NumLoops &&
15127 "Expecting loop iteration space dimensionality to match number of "
15128 "affected loops");
15129 assert(OriginalInits.size() == NumLoops &&
15130 "Expecting loop iteration space dimensionality to match number of "
15131 "affected loops");
15132
15133 // Collect all affected loop statements.
15134 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15135 collectLoopStmts(AStmt, LoopStmts);
15136
15137 SmallVector<Stmt *, 4> PreInits;
15138 CaptureVars CopyTransformer(SemaRef);
15139
15140 // Create iteration variables for the generated loops.
15141 SmallVector<VarDecl *, 4> FloorIndVars;
15142 SmallVector<VarDecl *, 4> StripeIndVars;
15143 FloorIndVars.resize(NumLoops);
15144 StripeIndVars.resize(NumLoops);
15145 for (unsigned I : llvm::seq<unsigned>(NumLoops)) {
15146 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15147
15148 assert(LoopHelper.Counters.size() == 1 &&
15149 "Expect single-dimensional loop iteration space");
15150 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15151 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15152 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15153 QualType CntTy = IterVarRef->getType();
15154
15155 // Iteration variable for the stripe (i.e. outer) loop.
15156 {
15157 std::string FloorCntName =
15158 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15159 VarDecl *FloorCntDecl =
15160 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
15161 FloorIndVars[I] = FloorCntDecl;
15162 }
15163
15164 // Iteration variable for the stripe (i.e. inner) loop.
15165 {
15166 std::string StripeCntName =
15167 (Twine(".stripe_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15168
15169 // Reuse the iteration variable created by checkOpenMPLoop. It is also
15170 // used by the expressions to derive the original iteration variable's
15171 // value from the logical iteration number.
15172 auto *StripeCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15173 StripeCntDecl->setDeclName(
15174 &SemaRef.PP.getIdentifierTable().get(StripeCntName));
15175 StripeIndVars[I] = StripeCntDecl;
15176 }
15177
15178 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
15179 PreInits);
15180 }
15181
15182 // Once the original iteration values are set, append the innermost body.
15183 Stmt *Inner = Body;
15184
15185 auto MakeDimStripeSize = [&](int I) -> Expr * {
15186 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
15187 if (isa<ConstantExpr>(DimStripeSizeExpr))
15188 return AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr));
15189
15190 // When the stripe size is not a constant but a variable, it is possible to
15191 // pass non-positive numbers. For instance:
15192 // \code{c}
15193 // int a = 0;
15194 // #pragma omp stripe sizes(a)
15195 // for (int i = 0; i < 42; ++i)
15196 // body(i);
15197 // \endcode
15198 // Although there is no meaningful interpretation of the stripe size, the
15199 // body should still be executed 42 times to avoid surprises. To preserve
15200 // the invariant that every loop iteration is executed exactly once and not
15201 // cause an infinite loop, apply a minimum stripe size of one.
15202 // Build expr:
15203 // \code{c}
15204 // (TS <= 0) ? 1 : TS
15205 // \endcode
15206 QualType DimTy = DimStripeSizeExpr->getType();
15207 uint64_t DimWidth = Context.getTypeSize(DimTy);
15209 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
15210 IntegerLiteral *One =
15211 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
15212 Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
15213 CurScope, {}, BO_LE,
15214 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), Zero));
15215 Expr *MinOne = new (Context) ConditionalOperator(
15216 Cond, {}, One, {},
15217 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), DimTy,
15219 return MinOne;
15220 };
15221
15222 // Create stripe loops from the inside to the outside.
15223 for (int I = NumLoops - 1; I >= 0; --I) {
15224 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15225 Expr *NumIterations = LoopHelper.NumIterations;
15226 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15227 QualType IVTy = NumIterations->getType();
15228 Stmt *LoopStmt = LoopStmts[I];
15229
15230 // For init-statement: auto .stripe.iv = .floor.iv
15231 SemaRef.AddInitializerToDecl(
15232 StripeIndVars[I],
15233 SemaRef
15234 .DefaultLvalueConversion(
15235 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
15236 .get(),
15237 /*DirectInit=*/false);
15238 Decl *CounterDecl = StripeIndVars[I];
15239 StmtResult InitStmt = new (Context)
15240 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15241 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15242 if (!InitStmt.isUsable())
15243 return StmtError();
15244
15245 // For cond-expression:
15246 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations)
15247 ExprResult EndOfStripe = SemaRef.BuildBinOp(
15248 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15249 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15250 MakeDimStripeSize(I));
15251 if (!EndOfStripe.isUsable())
15252 return StmtError();
15253 ExprResult IsPartialStripe =
15254 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15255 NumIterations, EndOfStripe.get());
15256 if (!IsPartialStripe.isUsable())
15257 return StmtError();
15258 ExprResult MinStripeAndIterSpace = SemaRef.ActOnConditionalOp(
15259 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15260 IsPartialStripe.get(), NumIterations, EndOfStripe.get());
15261 if (!MinStripeAndIterSpace.isUsable())
15262 return StmtError();
15263 ExprResult CondExpr = SemaRef.BuildBinOp(
15264 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15265 makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar),
15266 MinStripeAndIterSpace.get());
15267 if (!CondExpr.isUsable())
15268 return StmtError();
15269
15270 // For incr-statement: ++.stripe.iv
15271 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15272 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc,
15273 makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar));
15274 if (!IncrStmt.isUsable())
15275 return StmtError();
15276
15277 // Statements to set the original iteration variable's value from the
15278 // logical iteration number.
15279 // Generated for loop is:
15280 // \code
15281 // Original_for_init;
15282 // for (auto .stripe.iv = .floor.iv;
15283 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations);
15284 // ++.stripe.iv) {
15285 // Original_Body;
15286 // Original_counter_update;
15287 // }
15288 // \endcode
15289 // FIXME: If the innermost body is a loop itself, inserting these
15290 // statements stops it being recognized as a perfectly nested loop (e.g.
15291 // for applying another loop transformation). If this is the case, sink the
15292 // expressions further into the inner loop.
15293 SmallVector<Stmt *, 4> BodyParts;
15294 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15295 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15296 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15297 BodyParts.push_back(Inner);
15298 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15299 Inner->getBeginLoc(), Inner->getEndLoc());
15300 Inner = new (Context)
15301 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15302 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15303 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15304 }
15305
15306 // Create grid loops from the inside to the outside.
15307 for (int I = NumLoops - 1; I >= 0; --I) {
15308 auto &LoopHelper = LoopHelpers[I];
15309 Expr *NumIterations = LoopHelper.NumIterations;
15310 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15311 QualType IVTy = NumIterations->getType();
15312
15313 // For init-statement: auto .grid.iv = 0
15314 SemaRef.AddInitializerToDecl(
15315 FloorIndVars[I],
15316 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15317 /*DirectInit=*/false);
15318 Decl *CounterDecl = FloorIndVars[I];
15319 StmtResult InitStmt = new (Context)
15320 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15321 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15322 if (!InitStmt.isUsable())
15323 return StmtError();
15324
15325 // For cond-expression: .floor.iv < NumIterations
15326 ExprResult CondExpr = SemaRef.BuildBinOp(
15327 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15328 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15329 NumIterations);
15330 if (!CondExpr.isUsable())
15331 return StmtError();
15332
15333 // For incr-statement: .floor.iv += DimStripeSize
15334 ExprResult IncrStmt = SemaRef.BuildBinOp(
15335 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15336 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15337 MakeDimStripeSize(I));
15338 if (!IncrStmt.isUsable())
15339 return StmtError();
15340
15341 Inner = new (Context)
15342 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15343 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15344 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15345 }
15346
15347 return OMPStripeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15348 NumLoops, AStmt, Inner,
15349 buildPreInits(Context, PreInits));
15350}
15351
15353 Stmt *AStmt,
15354 SourceLocation StartLoc,
15355 SourceLocation EndLoc) {
15356 ASTContext &Context = getASTContext();
15357 Scope *CurScope = SemaRef.getCurScope();
15358 // Empty statement should only be possible if there already was an error.
15359 if (!AStmt)
15360 return StmtError();
15361
15363 {OMPC_partial, OMPC_full}))
15364 return StmtError();
15365
15366 const OMPFullClause *FullClause =
15367 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15368 const OMPPartialClause *PartialClause =
15369 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15370 assert(!(FullClause && PartialClause) &&
15371 "mutual exclusivity must have been checked before");
15372
15373 constexpr unsigned NumLoops = 1;
15374 Stmt *Body = nullptr;
15376 NumLoops);
15377 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
15378 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15379 Body, OriginalInits))
15380 return StmtError();
15381
15382 unsigned NumGeneratedTopLevelLoops = PartialClause ? 1 : 0;
15383
15384 // Delay unrolling to when template is completely instantiated.
15385 if (SemaRef.CurContext->isDependentContext())
15386 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15387 NumGeneratedTopLevelLoops, nullptr,
15388 nullptr);
15389
15390 assert(LoopHelpers.size() == NumLoops &&
15391 "Expecting a single-dimensional loop iteration space");
15392 assert(OriginalInits.size() == NumLoops &&
15393 "Expecting a single-dimensional loop iteration space");
15394 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15395
15396 if (FullClause) {
15398 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
15399 /*SuppressExprDiags=*/true)
15400 .isUsable()) {
15401 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
15402 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
15403 << "#pragma omp unroll full";
15404 return StmtError();
15405 }
15406 }
15407
15408 // The generated loop may only be passed to other loop-associated directive
15409 // when a partial clause is specified. Without the requirement it is
15410 // sufficient to generate loop unroll metadata at code-generation.
15411 if (NumGeneratedTopLevelLoops == 0)
15412 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15413 NumGeneratedTopLevelLoops, nullptr,
15414 nullptr);
15415
15416 // Otherwise, we need to provide a de-sugared/transformed AST that can be
15417 // associated with another loop directive.
15418 //
15419 // The canonical loop analysis return by checkTransformableLoopNest assumes
15420 // the following structure to be the same loop without transformations or
15421 // directives applied: \code OriginalInits; LoopHelper.PreInits;
15422 // LoopHelper.Counters;
15423 // for (; IV < LoopHelper.NumIterations; ++IV) {
15424 // LoopHelper.Updates;
15425 // Body;
15426 // }
15427 // \endcode
15428 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
15429 // and referenced by LoopHelper.IterationVarRef.
15430 //
15431 // The unrolling directive transforms this into the following loop:
15432 // \code
15433 // OriginalInits; \
15434 // LoopHelper.PreInits; > NewPreInits
15435 // LoopHelper.Counters; /
15436 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
15437 // #pragma clang loop unroll_count(Factor)
15438 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
15439 // {
15440 // LoopHelper.Updates;
15441 // Body;
15442 // }
15443 // }
15444 // \endcode
15445 // where UIV is a new logical iteration counter. IV must be the same VarDecl
15446 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
15447 // references it. If the partially unrolled loop is associated with another
15448 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
15449 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
15450 // OpenMP canonical loop. The inner loop is not an associable canonical loop
15451 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
15452 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
15453 // property of the OMPLoopBasedDirective instead of statements in
15454 // CompoundStatement. This is to allow the loop to become a non-outermost loop
15455 // of a canonical loop nest where these PreInits are emitted before the
15456 // outermost directive.
15457
15458 // Find the loop statement.
15459 Stmt *LoopStmt = nullptr;
15460 collectLoopStmts(AStmt, {LoopStmt});
15461
15462 // Determine the PreInit declarations.
15463 SmallVector<Stmt *, 4> PreInits;
15464 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15465
15466 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15467 QualType IVTy = IterationVarRef->getType();
15468 assert(LoopHelper.Counters.size() == 1 &&
15469 "Expecting a single-dimensional loop iteration space");
15470 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15471
15472 // Determine the unroll factor.
15473 uint64_t Factor;
15474 SourceLocation FactorLoc;
15475 if (Expr *FactorVal = PartialClause->getFactor();
15476 FactorVal && !FactorVal->containsErrors()) {
15477 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15478 FactorLoc = FactorVal->getExprLoc();
15479 } else {
15480 // TODO: Use a better profitability model.
15481 Factor = 2;
15482 }
15483 assert(Factor > 0 && "Expected positive unroll factor");
15484 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
15486 getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor),
15487 IVTy, FactorLoc);
15488 };
15489
15490 // Iteration variable SourceLocations.
15491 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15492 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15493 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15494
15495 // Internal variable names.
15496 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15497 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
15498 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
15499
15500 // Create the iteration variable for the unrolled loop.
15501 VarDecl *OuterIVDecl =
15502 buildVarDecl(SemaRef, {}, IVTy, OuterIVName, nullptr, OrigVar);
15503 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
15504 return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc);
15505 };
15506
15507 // Iteration variable for the inner loop: Reuse the iteration variable created
15508 // by checkOpenMPLoop.
15509 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15510 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(InnerIVName));
15511 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
15512 return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc);
15513 };
15514
15515 // Make a copy of the NumIterations expression for each use: By the AST
15516 // constraints, every expression object in a DeclContext must be unique.
15517 CaptureVars CopyTransformer(SemaRef);
15518 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15519 return AssertSuccess(
15520 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15521 };
15522
15523 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15524 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(MakeOuterRef());
15525 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(),
15526 /*DirectInit=*/false);
15527 StmtResult InnerInit = new (Context)
15528 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15529 if (!InnerInit.isUsable())
15530 return StmtError();
15531
15532 // Inner For cond-expression:
15533 // \code
15534 // .unroll_inner.iv < .unrolled.iv + Factor &&
15535 // .unroll_inner.iv < NumIterations
15536 // \endcode
15537 // This conjunction of two conditions allows ScalarEvolution to derive the
15538 // maximum trip count of the inner loop.
15539 ExprResult EndOfTile =
15540 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15541 MakeOuterRef(), MakeFactorExpr());
15542 if (!EndOfTile.isUsable())
15543 return StmtError();
15544 ExprResult InnerCond1 =
15545 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15546 MakeInnerRef(), EndOfTile.get());
15547 if (!InnerCond1.isUsable())
15548 return StmtError();
15549 ExprResult InnerCond2 =
15550 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15551 MakeInnerRef(), MakeNumIterations());
15552 if (!InnerCond2.isUsable())
15553 return StmtError();
15554 ExprResult InnerCond =
15555 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15556 InnerCond1.get(), InnerCond2.get());
15557 if (!InnerCond.isUsable())
15558 return StmtError();
15559
15560 // Inner For incr-statement: ++.unroll_inner.iv
15561 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
15562 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
15563 if (!InnerIncr.isUsable())
15564 return StmtError();
15565
15566 // Inner For statement.
15567 SmallVector<Stmt *> InnerBodyStmts;
15568 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15569 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15570 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15571 InnerBodyStmts.push_back(Body);
15572 CompoundStmt *InnerBody =
15574 Body->getBeginLoc(), Body->getEndLoc());
15575 ForStmt *InnerFor = new (Context)
15576 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15577 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15578 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15579
15580 // Unroll metadata for the inner loop.
15581 // This needs to take into account the remainder portion of the unrolled loop,
15582 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15583 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15584 // the maximum trip count, which will also generate a remainder loop. Just
15585 // `unroll(enable)` (which could have been useful if the user has not
15586 // specified a concrete factor; even though the outer loop cannot be
15587 // influenced anymore, would avoid more code bloat than necessary) will refuse
15588 // the loop because "Won't unroll; remainder loop could not be generated when
15589 // assuming runtime trip count". Even if it did work, it must not choose a
15590 // larger unroll factor than the maximum loop length, or it would always just
15591 // execute the remainder loop.
15592 LoopHintAttr *UnrollHintAttr =
15593 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15594 LoopHintAttr::Numeric, MakeFactorExpr());
15595 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
15596 getASTContext(), StartLoc, {UnrollHintAttr}, InnerFor);
15597
15598 // Outer For init-statement: auto .unrolled.iv = 0
15599 SemaRef.AddInitializerToDecl(
15600 OuterIVDecl,
15601 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15602 /*DirectInit=*/false);
15603 StmtResult OuterInit = new (Context)
15604 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15605 if (!OuterInit.isUsable())
15606 return StmtError();
15607
15608 // Outer For cond-expression: .unrolled.iv < NumIterations
15609 ExprResult OuterConde =
15610 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15611 MakeOuterRef(), MakeNumIterations());
15612 if (!OuterConde.isUsable())
15613 return StmtError();
15614
15615 // Outer For incr-statement: .unrolled.iv += Factor
15616 ExprResult OuterIncr =
15617 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15618 MakeOuterRef(), MakeFactorExpr());
15619 if (!OuterIncr.isUsable())
15620 return StmtError();
15621
15622 // Outer For statement.
15623 ForStmt *OuterFor = new (Context)
15624 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15625 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15626 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15627
15628 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15629 NumGeneratedTopLevelLoops, OuterFor,
15630 buildPreInits(Context, PreInits));
15631}
15632
15634 SourceLocation StartLoc,
15635 SourceLocation EndLoc) {
15636 ASTContext &Context = getASTContext();
15637 Scope *CurScope = SemaRef.getCurScope();
15638
15639 // Empty statement should only be possible if there already was an error.
15640 if (!AStmt)
15641 return StmtError();
15642
15643 constexpr unsigned NumLoops = 1;
15644 Stmt *Body = nullptr;
15646 NumLoops);
15647 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
15648 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
15649 Body, OriginalInits))
15650 return StmtError();
15651
15652 // Delay applying the transformation to when template is completely
15653 // instantiated.
15654 if (SemaRef.CurContext->isDependentContext())
15655 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
15656 NumLoops, nullptr, nullptr);
15657
15658 assert(LoopHelpers.size() == NumLoops &&
15659 "Expecting a single-dimensional loop iteration space");
15660 assert(OriginalInits.size() == NumLoops &&
15661 "Expecting a single-dimensional loop iteration space");
15662 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15663
15664 // Find the loop statement.
15665 Stmt *LoopStmt = nullptr;
15666 collectLoopStmts(AStmt, {LoopStmt});
15667
15668 // Determine the PreInit declarations.
15669 SmallVector<Stmt *> PreInits;
15670 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15671
15672 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15673 QualType IVTy = IterationVarRef->getType();
15674 uint64_t IVWidth = Context.getTypeSize(IVTy);
15675 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15676
15677 // Iteration variable SourceLocations.
15678 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15679 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15680 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15681
15682 // Locations pointing to the transformation.
15683 SourceLocation TransformLoc = StartLoc;
15684 SourceLocation TransformLocBegin = StartLoc;
15685 SourceLocation TransformLocEnd = EndLoc;
15686
15687 // Internal variable names.
15688 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15689 SmallString<64> ForwardIVName(".forward.iv.");
15690 ForwardIVName += OrigVarName;
15691 SmallString<64> ReversedIVName(".reversed.iv.");
15692 ReversedIVName += OrigVarName;
15693
15694 // LoopHelper.Updates will read the logical iteration number from
15695 // LoopHelper.IterationVarRef, compute the value of the user loop counter of
15696 // that logical iteration from it, then assign it to the user loop counter
15697 // variable. We cannot directly use LoopHelper.IterationVarRef as the
15698 // induction variable of the generated loop because it may cause an underflow:
15699 // \code{.c}
15700 // for (unsigned i = 0; i < n; ++i)
15701 // body(i);
15702 // \endcode
15703 //
15704 // Naive reversal:
15705 // \code{.c}
15706 // for (unsigned i = n-1; i >= 0; --i)
15707 // body(i);
15708 // \endcode
15709 //
15710 // Instead, we introduce a new iteration variable representing the logical
15711 // iteration counter of the original loop, convert it to the logical iteration
15712 // number of the reversed loop, then let LoopHelper.Updates compute the user's
15713 // loop iteration variable from it.
15714 // \code{.cpp}
15715 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
15716 // auto .reversed.iv = n - .forward.iv - 1;
15717 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates
15718 // body(i); // Body
15719 // }
15720 // \endcode
15721
15722 // Subexpressions with more than one use. One of the constraints of an AST is
15723 // that every node object must appear at most once, hence we define a lambda
15724 // that creates a new AST node at every use.
15725 CaptureVars CopyTransformer(SemaRef);
15726 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15727 return AssertSuccess(
15728 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15729 };
15730
15731 // Create the iteration variable for the forward loop (from 0 to n-1).
15732 VarDecl *ForwardIVDecl =
15733 buildVarDecl(SemaRef, {}, IVTy, ForwardIVName, nullptr, OrigVar);
15734 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
15735 OrigVarLoc]() {
15736 return buildDeclRefExpr(SemaRef, ForwardIVDecl, IVTy, OrigVarLoc);
15737 };
15738
15739 // Iteration variable for the reversed induction variable (from n-1 downto 0):
15740 // Reuse the iteration variable created by checkOpenMPLoop.
15741 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15742 ReversedIVDecl->setDeclName(
15743 &SemaRef.PP.getIdentifierTable().get(ReversedIVName));
15744
15745 // For init-statement:
15746 // \code{.cpp}
15747 // auto .forward.iv = 0;
15748 // \endcode
15749 auto *Zero = IntegerLiteral::Create(Context, llvm::APInt::getZero(IVWidth),
15750 ForwardIVDecl->getType(), OrigVarLoc);
15751 SemaRef.AddInitializerToDecl(ForwardIVDecl, Zero, /*DirectInit=*/false);
15752 StmtResult Init = new (Context)
15753 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15754 if (!Init.isUsable())
15755 return StmtError();
15756
15757 // Forward iv cond-expression:
15758 // \code{.cpp}
15759 // .forward.iv < MakeNumIterations()
15760 // \endcode
15762 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15763 MakeForwardRef(), MakeNumIterations());
15764 if (!Cond.isUsable())
15765 return StmtError();
15766
15767 // Forward incr-statement:
15768 // \code{.c}
15769 // ++.forward.iv
15770 // \endcode
15771 ExprResult Incr = SemaRef.BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
15772 UO_PreInc, MakeForwardRef());
15773 if (!Incr.isUsable())
15774 return StmtError();
15775
15776 // Reverse the forward-iv:
15777 // \code{.cpp}
15778 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
15779 // \endcode
15780 auto *One = IntegerLiteral::Create(Context, llvm::APInt(IVWidth, 1), IVTy,
15781 TransformLoc);
15782 ExprResult Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub,
15783 MakeNumIterations(), One);
15784 if (!Minus.isUsable())
15785 return StmtError();
15786 Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.get(),
15787 MakeForwardRef());
15788 if (!Minus.isUsable())
15789 return StmtError();
15790 StmtResult InitReversed = new (Context) DeclStmt(
15791 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
15792 if (!InitReversed.isUsable())
15793 return StmtError();
15794 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.get(),
15795 /*DirectInit=*/false);
15796
15797 // The new loop body.
15798 SmallVector<Stmt *, 4> BodyStmts;
15799 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
15800 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
15801 BodyStmts.push_back(InitReversed.get());
15802 llvm::append_range(BodyStmts, LoopHelper.Updates);
15803 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15804 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15805 BodyStmts.push_back(Body);
15806 auto *ReversedBody =
15807 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
15808 Body->getBeginLoc(), Body->getEndLoc());
15809
15810 // Finally create the reversed For-statement.
15811 auto *ReversedFor = new (Context)
15812 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
15813 ReversedBody, LoopHelper.Init->getBeginLoc(),
15814 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15815 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt, NumLoops,
15816 ReversedFor,
15817 buildPreInits(Context, PreInits));
15818}
15819
15821 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15822 SourceLocation EndLoc) {
15823 ASTContext &Context = getASTContext();
15824 DeclContext *CurContext = SemaRef.CurContext;
15825 Scope *CurScope = SemaRef.getCurScope();
15826
15827 // Empty statement should only be possible if there already was an error.
15828 if (!AStmt)
15829 return StmtError();
15830
15831 // interchange without permutation clause swaps two loops.
15832 const OMPPermutationClause *PermutationClause =
15833 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
15834 size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2;
15835
15836 // Verify and diagnose loop nest.
15838 Stmt *Body = nullptr;
15839 SmallVector<SmallVector<Stmt *>, 2> OriginalInits;
15840 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
15841 LoopHelpers, Body, OriginalInits))
15842 return StmtError();
15843
15844 // Delay interchange to when template is completely instantiated.
15845 if (CurContext->isDependentContext())
15846 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15847 NumLoops, AStmt, nullptr, nullptr);
15848
15849 // An invalid expression in the permutation clause is set to nullptr in
15850 // ActOnOpenMPPermutationClause.
15851 if (PermutationClause &&
15852 llvm::is_contained(PermutationClause->getArgsRefs(), nullptr))
15853 return StmtError();
15854
15855 assert(LoopHelpers.size() == NumLoops &&
15856 "Expecting loop iteration space dimensionaly to match number of "
15857 "affected loops");
15858 assert(OriginalInits.size() == NumLoops &&
15859 "Expecting loop iteration space dimensionaly to match number of "
15860 "affected loops");
15861
15862 // Decode the permutation clause.
15863 SmallVector<uint64_t, 2> Permutation;
15864 if (!PermutationClause) {
15865 Permutation = {1, 0};
15866 } else {
15867 ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs();
15868 llvm::BitVector Flags(PermArgs.size());
15869 for (Expr *PermArg : PermArgs) {
15870 std::optional<llvm::APSInt> PermCstExpr =
15871 PermArg->getIntegerConstantExpr(Context);
15872 if (!PermCstExpr)
15873 continue;
15874 uint64_t PermInt = PermCstExpr->getZExtValue();
15875 assert(1 <= PermInt && PermInt <= NumLoops &&
15876 "Must be a permutation; diagnostic emitted in "
15877 "ActOnOpenMPPermutationClause");
15878 if (Flags[PermInt - 1]) {
15879 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
15880 Diag(PermArg->getExprLoc(),
15881 diag::err_omp_interchange_permutation_value_repeated)
15882 << PermInt << ExprRange;
15883 continue;
15884 }
15885 Flags[PermInt - 1] = true;
15886
15887 Permutation.push_back(PermInt - 1);
15888 }
15889
15890 if (Permutation.size() != NumLoops)
15891 return StmtError();
15892 }
15893
15894 // Nothing to transform with trivial permutation.
15895 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](auto P) {
15896 auto [Idx, Arg] = P;
15897 return Idx == Arg;
15898 }))
15899 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15900 NumLoops, AStmt, AStmt, nullptr);
15901
15902 // Find the affected loops.
15903 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15904 collectLoopStmts(AStmt, LoopStmts);
15905
15906 // Collect pre-init statements on the order before the permuation.
15907 SmallVector<Stmt *> PreInits;
15908 for (auto I : llvm::seq<int>(NumLoops)) {
15909 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15910
15911 assert(LoopHelper.Counters.size() == 1 &&
15912 "Single-dimensional loop iteration space expected");
15913
15914 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
15915 PreInits);
15916 }
15917
15918 SmallVector<VarDecl *> PermutedIndVars(NumLoops);
15919 CaptureVars CopyTransformer(SemaRef);
15920
15921 // Create the permuted loops from the inside to the outside of the
15922 // interchanged loop nest. Body of the innermost new loop is the original
15923 // innermost body.
15924 Stmt *Inner = Body;
15925 for (auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
15926 // Get the original loop that belongs to this new position.
15927 uint64_t SourceIdx = Permutation[TargetIdx];
15928 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
15929 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15930 assert(SourceHelper.Counters.size() == 1 &&
15931 "Single-dimensional loop iteration space expected");
15932 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.Counters.front());
15933
15934 // Normalized loop counter variable: From 0 to n-1, always an integer type.
15935 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(SourceHelper.IterationVarRef);
15936 QualType IVTy = IterVarRef->getType();
15937 assert(IVTy->isIntegerType() &&
15938 "Expected the logical iteration counter to be an integer");
15939
15940 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15941 SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
15942
15943 // Make a copy of the NumIterations expression for each use: By the AST
15944 // constraints, every expression object in a DeclContext must be unique.
15945 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
15946 return AssertSuccess(
15947 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
15948 };
15949
15950 // Iteration variable for the permuted loop. Reuse the one from
15951 // checkOpenMPLoop which will also be used to update the original loop
15952 // variable.
15953 SmallString<64> PermutedCntName(".permuted_");
15954 PermutedCntName.append({llvm::utostr(TargetIdx), ".iv.", OrigVarName});
15955 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15956 PermutedCntDecl->setDeclName(
15957 &SemaRef.PP.getIdentifierTable().get(PermutedCntName));
15958 PermutedIndVars[TargetIdx] = PermutedCntDecl;
15959 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
15960 return buildDeclRefExpr(SemaRef, PermutedCntDecl, IVTy, OrigVarLoc);
15961 };
15962
15963 // For init-statement:
15964 // \code
15965 // auto .permuted_{target}.iv = 0
15966 // \endcode
15967 ExprResult Zero = SemaRef.ActOnIntegerConstant(OrigVarLoc, 0);
15968 if (!Zero.isUsable())
15969 return StmtError();
15970 SemaRef.AddInitializerToDecl(PermutedCntDecl, Zero.get(),
15971 /*DirectInit=*/false);
15972 StmtResult InitStmt = new (Context)
15973 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
15974 OrigCntVar->getEndLoc());
15975 if (!InitStmt.isUsable())
15976 return StmtError();
15977
15978 // For cond-expression:
15979 // \code
15980 // .permuted_{target}.iv < MakeNumIterations()
15981 // \endcode
15982 ExprResult CondExpr =
15983 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
15984 MakePermutedRef(), MakeNumIterations());
15985 if (!CondExpr.isUsable())
15986 return StmtError();
15987
15988 // For incr-statement:
15989 // \code
15990 // ++.tile.iv
15991 // \endcode
15992 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15993 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
15994 if (!IncrStmt.isUsable())
15995 return StmtError();
15996
15997 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
15998 SourceHelper.Updates.end());
15999 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
16000 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
16001 BodyParts.push_back(Inner);
16002 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
16003 Inner->getBeginLoc(), Inner->getEndLoc());
16004 Inner = new (Context) ForStmt(
16005 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
16006 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
16007 SourceHelper.Inc->getEndLoc());
16008 }
16009
16010 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
16011 NumLoops, AStmt, Inner,
16012 buildPreInits(Context, PreInits));
16013}
16014
16016 Stmt *AStmt,
16017 SourceLocation StartLoc,
16018 SourceLocation EndLoc) {
16019
16020 ASTContext &Context = getASTContext();
16021 DeclContext *CurrContext = SemaRef.CurContext;
16022 Scope *CurScope = SemaRef.getCurScope();
16023 CaptureVars CopyTransformer(SemaRef);
16024
16025 // Ensure the structured block is not empty
16026 if (!AStmt)
16027 return StmtError();
16028
16029 // Defer transformation in dependent contexts
16030 // The NumLoopNests argument is set to a placeholder 1 (even though
16031 // using looprange fuse could yield up to 3 top level loop nests)
16032 // because a dependent context could prevent determining its true value
16033 if (CurrContext->isDependentContext())
16034 return OMPFuseDirective::Create(Context, StartLoc, EndLoc, Clauses,
16035 /* NumLoops */ 1, AStmt, nullptr, nullptr);
16036
16037 // Validate that the potential loop sequence is transformable for fusion
16038 // Also collect the HelperExprs, Loop Stmts, Inits, and Number of loops
16039 LoopSequenceAnalysis SeqAnalysis;
16040 if (!checkTransformableLoopSequence(OMPD_fuse, AStmt, SeqAnalysis, Context))
16041 return StmtError();
16042
16043 // SeqAnalysis.LoopSeqSize exists mostly to handle dependent contexts,
16044 // otherwise it must be the same as SeqAnalysis.Loops.size().
16045 assert(SeqAnalysis.LoopSeqSize == SeqAnalysis.Loops.size() &&
16046 "Inconsistent size of the loop sequence and the number of loops "
16047 "found in the sequence");
16048
16049 // Handle clauses, which can be any of the following: [looprange, apply]
16050 const auto *LRC =
16051 OMPExecutableDirective::getSingleClause<OMPLoopRangeClause>(Clauses);
16052
16053 // The clause arguments are invalidated if any error arises
16054 // such as non-constant or non-positive arguments
16055 if (LRC && (!LRC->getFirst() || !LRC->getCount()))
16056 return StmtError();
16057
16058 // Delayed semantic check of LoopRange constraint
16059 // Evaluates the loop range arguments and returns the first and count values
16060 auto EvaluateLoopRangeArguments = [&Context](Expr *First, Expr *Count,
16061 uint64_t &FirstVal,
16062 uint64_t &CountVal) {
16063 llvm::APSInt FirstInt = First->EvaluateKnownConstInt(Context);
16064 llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Context);
16065 FirstVal = FirstInt.getZExtValue();
16066 CountVal = CountInt.getZExtValue();
16067 };
16068
16069 // OpenMP [6.0, Restrictions]
16070 // first + count - 1 must not evaluate to a value greater than the
16071 // loop sequence length of the associated canonical loop sequence.
16072 auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal,
16073 unsigned NumLoops) -> bool {
16074 return FirstVal + CountVal - 1 <= NumLoops;
16075 };
16076 uint64_t FirstVal = 1, CountVal = 0, LastVal = SeqAnalysis.LoopSeqSize;
16077
16078 // Validates the loop range after evaluating the semantic information
16079 // and ensures that the range is valid for the given loop sequence size.
16080 // Expressions are evaluated at compile time to obtain constant values.
16081 if (LRC) {
16082 EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal,
16083 CountVal);
16084 if (CountVal == 1)
16085 SemaRef.Diag(LRC->getCountLoc(), diag::warn_omp_redundant_fusion)
16086 << getOpenMPDirectiveName(OMPD_fuse);
16087
16088 if (!ValidLoopRange(FirstVal, CountVal, SeqAnalysis.LoopSeqSize)) {
16089 SemaRef.Diag(LRC->getFirstLoc(), diag::err_omp_invalid_looprange)
16090 << getOpenMPDirectiveName(OMPD_fuse) << FirstVal
16091 << (FirstVal + CountVal - 1) << SeqAnalysis.LoopSeqSize;
16092 return StmtError();
16093 }
16094
16095 LastVal = FirstVal + CountVal - 1;
16096 }
16097
16098 // Complete fusion generates a single canonical loop nest
16099 // However looprange clause may generate several loop nests
16100 unsigned NumGeneratedTopLevelLoops =
16101 LRC ? SeqAnalysis.LoopSeqSize - CountVal + 1 : 1;
16102
16103 // Emit a warning for redundant loop fusion when the sequence contains only
16104 // one loop.
16105 if (SeqAnalysis.LoopSeqSize == 1)
16106 SemaRef.Diag(AStmt->getBeginLoc(), diag::warn_omp_redundant_fusion)
16107 << getOpenMPDirectiveName(OMPD_fuse);
16108
16109 // Select the type with the largest bit width among all induction variables
16110 QualType IVType =
16111 SeqAnalysis.Loops[FirstVal - 1].HelperExprs.IterationVarRef->getType();
16112 for (unsigned I : llvm::seq<unsigned>(FirstVal, LastVal)) {
16113 QualType CurrentIVType =
16114 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef->getType();
16115 if (Context.getTypeSize(CurrentIVType) > Context.getTypeSize(IVType)) {
16116 IVType = CurrentIVType;
16117 }
16118 }
16119 uint64_t IVBitWidth = Context.getIntWidth(IVType);
16120
16121 // Create pre-init declarations for all loops lower bounds, upper bounds,
16122 // strides and num-iterations for every top level loop in the fusion
16123 SmallVector<VarDecl *, 4> LBVarDecls;
16124 SmallVector<VarDecl *, 4> STVarDecls;
16125 SmallVector<VarDecl *, 4> NIVarDecls;
16126 SmallVector<VarDecl *, 4> UBVarDecls;
16127 SmallVector<VarDecl *, 4> IVVarDecls;
16128
16129 // Helper lambda to create variables for bounds, strides, and other
16130 // expressions. Generates both the variable declaration and the corresponding
16131 // initialization statement.
16132 auto CreateHelperVarAndStmt =
16133 [&, &SemaRef = SemaRef](Expr *ExprToCopy, const std::string &BaseName,
16134 unsigned I, bool NeedsNewVD = false) {
16135 Expr *TransformedExpr =
16136 AssertSuccess(CopyTransformer.TransformExpr(ExprToCopy));
16137 if (!TransformedExpr)
16138 return std::pair<VarDecl *, StmtResult>(nullptr, StmtError());
16139
16140 auto Name = (Twine(".omp.") + BaseName + std::to_string(I)).str();
16141
16142 VarDecl *VD;
16143 if (NeedsNewVD) {
16144 VD = buildVarDecl(SemaRef, SourceLocation(), IVType, Name);
16145 SemaRef.AddInitializerToDecl(VD, TransformedExpr, false);
16146 } else {
16147 // Create a unique variable name
16148 DeclRefExpr *DRE = cast<DeclRefExpr>(TransformedExpr);
16149 VD = cast<VarDecl>(DRE->getDecl());
16150 VD->setDeclName(&SemaRef.PP.getIdentifierTable().get(Name));
16151 }
16152 // Create the corresponding declaration statement
16153 StmtResult DeclStmt = new (Context) class DeclStmt(
16155 return std::make_pair(VD, DeclStmt);
16156 };
16157
16158 // PreInits hold a sequence of variable declarations that must be executed
16159 // before the fused loop begins. These include bounds, strides, and other
16160 // helper variables required for the transformation. Other loop transforms
16161 // also contain their own preinits
16162 SmallVector<Stmt *> PreInits;
16163
16164 // Update the general preinits using the preinits generated by loop sequence
16165 // generating loop transformations. These preinits differ slightly from
16166 // single-loop transformation preinits, as they can be detached from a
16167 // specific loop inside multiple generated loop nests. This happens
16168 // because certain helper variables, like '.omp.fuse.max', are introduced to
16169 // handle fused iteration spaces and may not be directly tied to a single
16170 // original loop. The preinit structure must ensure that hidden variables
16171 // like '.omp.fuse.max' are still properly handled.
16172 // Transformations that apply this concept: Loopranged Fuse, Split
16173 llvm::append_range(PreInits, SeqAnalysis.LoopSequencePreInits);
16174
16175 // Process each single loop to generate and collect declarations
16176 // and statements for all helper expressions related to
16177 // particular single loop nests
16178
16179 // Also In the case of the fused loops, we keep track of their original
16180 // inits by appending them to their preinits statement, and in the case of
16181 // transformations, also append their preinits (which contain the original
16182 // loop initialization statement or other statements)
16183
16184 // Firstly we need to set TransformIndex to match the begining of the
16185 // looprange section
16186 unsigned int TransformIndex = 0;
16187 for (unsigned I : llvm::seq<unsigned>(FirstVal - 1)) {
16188 if (SeqAnalysis.Loops[I].isLoopTransformation())
16189 ++TransformIndex;
16190 }
16191
16192 for (unsigned int I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16193 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16194 addLoopPreInits(Context, SeqAnalysis.Loops[I].HelperExprs,
16195 SeqAnalysis.Loops[I].TheForStmt,
16196 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16197 } else if (SeqAnalysis.Loops[I].isLoopTransformation()) {
16198 // For transformed loops, insert both pre-inits and original inits.
16199 // Order matters: pre-inits may define variables used in the original
16200 // inits such as upper bounds...
16201 SmallVector<Stmt *> &TransformPreInit =
16202 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16203 llvm::append_range(PreInits, TransformPreInit);
16204
16205 addLoopPreInits(Context, SeqAnalysis.Loops[I].HelperExprs,
16206 SeqAnalysis.Loops[I].TheForStmt,
16207 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16208 }
16209 auto [UBVD, UBDStmt] =
16210 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.UB, "ub", J);
16211 auto [LBVD, LBDStmt] =
16212 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.LB, "lb", J);
16213 auto [STVD, STDStmt] =
16214 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.ST, "st", J);
16215 auto [NIVD, NIDStmt] = CreateHelperVarAndStmt(
16216 SeqAnalysis.Loops[I].HelperExprs.NumIterations, "ni", J, true);
16217 auto [IVVD, IVDStmt] = CreateHelperVarAndStmt(
16218 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef, "iv", J);
16219
16220 assert(LBVD && STVD && NIVD && IVVD &&
16221 "OpenMP Fuse Helper variables creation failed");
16222
16223 UBVarDecls.push_back(UBVD);
16224 LBVarDecls.push_back(LBVD);
16225 STVarDecls.push_back(STVD);
16226 NIVarDecls.push_back(NIVD);
16227 IVVarDecls.push_back(IVVD);
16228
16229 PreInits.push_back(LBDStmt.get());
16230 PreInits.push_back(STDStmt.get());
16231 PreInits.push_back(NIDStmt.get());
16232 PreInits.push_back(IVDStmt.get());
16233 }
16234
16235 auto MakeVarDeclRef = [&SemaRef = this->SemaRef](VarDecl *VD) {
16236 return buildDeclRefExpr(SemaRef, VD, VD->getType(), VD->getLocation(),
16237 false);
16238 };
16239
16240 // Following up the creation of the final fused loop will be performed
16241 // which has the following shape (considering the selected loops):
16242 //
16243 // for (fuse.index = 0; fuse.index < max(ni0, ni1..., nik); ++fuse.index) {
16244 // if (fuse.index < ni0){
16245 // iv0 = lb0 + st0 * fuse.index;
16246 // original.index0 = iv0
16247 // body(0);
16248 // }
16249 // if (fuse.index < ni1){
16250 // iv1 = lb1 + st1 * fuse.index;
16251 // original.index1 = iv1
16252 // body(1);
16253 // }
16254 //
16255 // ...
16256 //
16257 // if (fuse.index < nik){
16258 // ivk = lbk + stk * fuse.index;
16259 // original.indexk = ivk
16260 // body(k); Expr *InitVal = IntegerLiteral::Create(Context,
16261 // llvm::APInt(IVWidth, 0),
16262 // }
16263
16264 // 1. Create the initialized fuse index
16265 StringRef IndexName = ".omp.fuse.index";
16266 Expr *InitVal = IntegerLiteral::Create(Context, llvm::APInt(IVBitWidth, 0),
16267 IVType, SourceLocation());
16268 VarDecl *IndexDecl =
16269 buildVarDecl(SemaRef, {}, IVType, IndexName, nullptr, nullptr);
16270 SemaRef.AddInitializerToDecl(IndexDecl, InitVal, false);
16271 StmtResult InitStmt = new (Context)
16273
16274 if (!InitStmt.isUsable())
16275 return StmtError();
16276
16277 auto MakeIVRef = [&SemaRef = this->SemaRef, IndexDecl, IVType,
16278 Loc = InitVal->getExprLoc()]() {
16279 return buildDeclRefExpr(SemaRef, IndexDecl, IVType, Loc, false);
16280 };
16281
16282 // 2. Iteratively compute the max number of logical iterations Max(NI_1, NI_2,
16283 // ..., NI_k)
16284 //
16285 // This loop accumulates the maximum value across multiple expressions,
16286 // ensuring each step constructs a unique AST node for correctness. By using
16287 // intermediate temporary variables and conditional operators, we maintain
16288 // distinct nodes and avoid duplicating subtrees, For instance, max(a,b,c):
16289 // omp.temp0 = max(a, b)
16290 // omp.temp1 = max(omp.temp0, c)
16291 // omp.fuse.max = max(omp.temp1, omp.temp0)
16292
16293 ExprResult MaxExpr;
16294 // I is the range of loops in the sequence that we fuse.
16295 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16296 DeclRefExpr *NIRef = MakeVarDeclRef(NIVarDecls[J]);
16297 QualType NITy = NIRef->getType();
16298
16299 if (MaxExpr.isUnset()) {
16300 // Initialize MaxExpr with the first NI expression
16301 MaxExpr = NIRef;
16302 } else {
16303 // Create a new acummulator variable t_i = MaxExpr
16304 std::string TempName = (Twine(".omp.temp.") + Twine(J)).str();
16305 VarDecl *TempDecl =
16306 buildVarDecl(SemaRef, {}, NITy, TempName, nullptr, nullptr);
16307 TempDecl->setInit(MaxExpr.get());
16308 DeclRefExpr *TempRef =
16309 buildDeclRefExpr(SemaRef, TempDecl, NITy, SourceLocation(), false);
16310 DeclRefExpr *TempRef2 =
16311 buildDeclRefExpr(SemaRef, TempDecl, NITy, SourceLocation(), false);
16312 // Add a DeclStmt to PreInits to ensure the variable is declared.
16313 StmtResult TempStmt = new (Context)
16315
16316 if (!TempStmt.isUsable())
16317 return StmtError();
16318 PreInits.push_back(TempStmt.get());
16319
16320 // Build MaxExpr <-(MaxExpr > NIRef ? MaxExpr : NIRef)
16322 SemaRef.BuildBinOp(nullptr, SourceLocation(), BO_GT, TempRef, NIRef);
16323 // Handle any errors in Comparison creation
16324 if (!Comparison.isUsable())
16325 return StmtError();
16326
16327 DeclRefExpr *NIRef2 = MakeVarDeclRef(NIVarDecls[J]);
16328 // Update MaxExpr using a conditional expression to hold the max value
16329 MaxExpr = new (Context) ConditionalOperator(
16330 Comparison.get(), SourceLocation(), TempRef2, SourceLocation(),
16331 NIRef2->getExprStmt(), NITy, VK_LValue, OK_Ordinary);
16332
16333 if (!MaxExpr.isUsable())
16334 return StmtError();
16335 }
16336 }
16337 if (!MaxExpr.isUsable())
16338 return StmtError();
16339
16340 // 3. Declare the max variable
16341 const std::string MaxName = Twine(".omp.fuse.max").str();
16342 VarDecl *MaxDecl =
16343 buildVarDecl(SemaRef, {}, IVType, MaxName, nullptr, nullptr);
16344 MaxDecl->setInit(MaxExpr.get());
16345 DeclRefExpr *MaxRef = buildDeclRefExpr(SemaRef, MaxDecl, IVType, {}, false);
16346 StmtResult MaxStmt = new (Context)
16348
16349 if (MaxStmt.isInvalid())
16350 return StmtError();
16351 PreInits.push_back(MaxStmt.get());
16352
16353 // 4. Create condition Expr: index < n_max
16354 ExprResult CondExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_LT,
16355 MakeIVRef(), MaxRef);
16356 if (!CondExpr.isUsable())
16357 return StmtError();
16358
16359 // 5. Increment Expr: ++index
16360 ExprResult IncrExpr =
16361 SemaRef.BuildUnaryOp(CurScope, SourceLocation(), UO_PreInc, MakeIVRef());
16362 if (!IncrExpr.isUsable())
16363 return StmtError();
16364
16365 // 6. Build the Fused Loop Body
16366 // The final fused loop iterates over the maximum logical range. Inside the
16367 // loop, each original loop's index is calculated dynamically, and its body
16368 // is executed conditionally.
16369 //
16370 // Each sub-loop's body is guarded by a conditional statement to ensure
16371 // it executes only within its logical iteration range:
16372 //
16373 // if (fuse.index < ni_k){
16374 // iv_k = lb_k + st_k * fuse.index;
16375 // original.index = iv_k
16376 // body(k);
16377 // }
16378
16379 CompoundStmt *FusedBody = nullptr;
16380 SmallVector<Stmt *, 4> FusedBodyStmts;
16381 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16382 // Assingment of the original sub-loop index to compute the logical index
16383 // IV_k = LB_k + omp.fuse.index * ST_k
16384 ExprResult IdxExpr =
16385 SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Mul,
16386 MakeVarDeclRef(STVarDecls[J]), MakeIVRef());
16387 if (!IdxExpr.isUsable())
16388 return StmtError();
16389 IdxExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Add,
16390 MakeVarDeclRef(LBVarDecls[J]), IdxExpr.get());
16391
16392 if (!IdxExpr.isUsable())
16393 return StmtError();
16394 IdxExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Assign,
16395 MakeVarDeclRef(IVVarDecls[J]), IdxExpr.get());
16396 if (!IdxExpr.isUsable())
16397 return StmtError();
16398
16399 // Update the original i_k = IV_k
16400 SmallVector<Stmt *, 4> BodyStmts;
16401 BodyStmts.push_back(IdxExpr.get());
16402 llvm::append_range(BodyStmts, SeqAnalysis.Loops[I].HelperExprs.Updates);
16403
16404 // If the loop is a CXXForRangeStmt then the iterator variable is needed
16405 if (auto *SourceCXXFor =
16406 dyn_cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt))
16407 BodyStmts.push_back(SourceCXXFor->getLoopVarStmt());
16408
16409 Stmt *Body =
16410 (isa<ForStmt>(SeqAnalysis.Loops[I].TheForStmt))
16411 ? cast<ForStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody()
16412 : cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody();
16413 BodyStmts.push_back(Body);
16414
16415 CompoundStmt *CombinedBody =
16416 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
16419 SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_LT, MakeIVRef(),
16420 MakeVarDeclRef(NIVarDecls[J]));
16421
16422 if (!Condition.isUsable())
16423 return StmtError();
16424
16425 IfStmt *IfStatement = IfStmt::Create(
16426 Context, SourceLocation(), IfStatementKind::Ordinary, nullptr, nullptr,
16427 Condition.get(), SourceLocation(), SourceLocation(), CombinedBody,
16428 SourceLocation(), nullptr);
16429
16430 FusedBodyStmts.push_back(IfStatement);
16431 }
16432 FusedBody = CompoundStmt::Create(Context, FusedBodyStmts, FPOptionsOverride(),
16434
16435 // 7. Construct the final fused loop
16436 ForStmt *FusedForStmt = new (Context)
16437 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr, IncrExpr.get(),
16438 FusedBody, InitStmt.get()->getBeginLoc(), SourceLocation(),
16439 IncrExpr.get()->getEndLoc());
16440
16441 // In the case of looprange, the result of fuse won't simply
16442 // be a single loop (ForStmt), but rather a loop sequence
16443 // (CompoundStmt) of 3 parts: the pre-fusion loops, the fused loop
16444 // and the post-fusion loops, preserving its original order.
16445 //
16446 // Note: If looprange clause produces a single fused loop nest then
16447 // this compound statement wrapper is unnecessary (Therefore this
16448 // treatment is skipped)
16449
16450 Stmt *FusionStmt = FusedForStmt;
16451 if (LRC && CountVal != SeqAnalysis.LoopSeqSize) {
16452 SmallVector<Stmt *, 4> FinalLoops;
16453
16454 // Reset the transform index
16455 TransformIndex = 0;
16456
16457 // Collect all non-fused loops before and after the fused region.
16458 // Pre-fusion and post-fusion loops are inserted in order exploiting their
16459 // symmetry, along with their corresponding transformation pre-inits if
16460 // needed. The fused loop is added between the two regions.
16461 for (unsigned I : llvm::seq<unsigned>(SeqAnalysis.LoopSeqSize)) {
16462 if (I >= FirstVal - 1 && I < FirstVal + CountVal - 1) {
16463 // Update the Transformation counter to skip already treated
16464 // loop transformations
16465 if (!SeqAnalysis.Loops[I].isLoopTransformation())
16466 ++TransformIndex;
16467 continue;
16468 }
16469
16470 // No need to handle:
16471 // Regular loops: they are kept intact as-is.
16472 // Loop-sequence-generating transformations: already handled earlier.
16473 // Only TransformSingleLoop requires inserting pre-inits here
16474 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16475 const auto &TransformPreInit =
16476 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16477 if (!TransformPreInit.empty())
16478 llvm::append_range(PreInits, TransformPreInit);
16479 }
16480
16481 FinalLoops.push_back(SeqAnalysis.Loops[I].TheForStmt);
16482 }
16483
16484 FinalLoops.insert(FinalLoops.begin() + (FirstVal - 1), FusedForStmt);
16485 FusionStmt = CompoundStmt::Create(Context, FinalLoops, FPOptionsOverride(),
16487 }
16488 return OMPFuseDirective::Create(Context, StartLoc, EndLoc, Clauses,
16489 NumGeneratedTopLevelLoops, AStmt, FusionStmt,
16490 buildPreInits(Context, PreInits));
16491}
16492
16494 Expr *Expr,
16495 SourceLocation StartLoc,
16496 SourceLocation LParenLoc,
16497 SourceLocation EndLoc) {
16498 OMPClause *Res = nullptr;
16499 switch (Kind) {
16500 case OMPC_final:
16501 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
16502 break;
16503 case OMPC_safelen:
16504 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
16505 break;
16506 case OMPC_simdlen:
16507 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
16508 break;
16509 case OMPC_allocator:
16510 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
16511 break;
16512 case OMPC_collapse:
16513 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
16514 break;
16515 case OMPC_ordered:
16516 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
16517 break;
16518 case OMPC_nowait:
16519 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc, LParenLoc, Expr);
16520 break;
16521 case OMPC_priority:
16522 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
16523 break;
16524 case OMPC_hint:
16525 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
16526 break;
16527 case OMPC_depobj:
16528 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
16529 break;
16530 case OMPC_detach:
16531 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
16532 break;
16533 case OMPC_novariants:
16534 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
16535 break;
16536 case OMPC_nocontext:
16537 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
16538 break;
16539 case OMPC_filter:
16540 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
16541 break;
16542 case OMPC_partial:
16543 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
16544 break;
16545 case OMPC_message:
16546 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
16547 break;
16548 case OMPC_align:
16549 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
16550 break;
16551 case OMPC_ompx_dyn_cgroup_mem:
16552 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
16553 break;
16554 case OMPC_holds:
16555 Res = ActOnOpenMPHoldsClause(Expr, StartLoc, LParenLoc, EndLoc);
16556 break;
16557 case OMPC_dyn_groupprivate:
16558 case OMPC_grainsize:
16559 case OMPC_num_tasks:
16560 case OMPC_num_threads:
16561 case OMPC_device:
16562 case OMPC_if:
16563 case OMPC_default:
16564 case OMPC_proc_bind:
16565 case OMPC_schedule:
16566 case OMPC_private:
16567 case OMPC_firstprivate:
16568 case OMPC_lastprivate:
16569 case OMPC_shared:
16570 case OMPC_reduction:
16571 case OMPC_task_reduction:
16572 case OMPC_in_reduction:
16573 case OMPC_linear:
16574 case OMPC_aligned:
16575 case OMPC_copyin:
16576 case OMPC_copyprivate:
16577 case OMPC_untied:
16578 case OMPC_mergeable:
16579 case OMPC_threadprivate:
16580 case OMPC_groupprivate:
16581 case OMPC_sizes:
16582 case OMPC_allocate:
16583 case OMPC_flush:
16584 case OMPC_read:
16585 case OMPC_write:
16586 case OMPC_update:
16587 case OMPC_capture:
16588 case OMPC_compare:
16589 case OMPC_seq_cst:
16590 case OMPC_acq_rel:
16591 case OMPC_acquire:
16592 case OMPC_release:
16593 case OMPC_relaxed:
16594 case OMPC_depend:
16595 case OMPC_threads:
16596 case OMPC_simd:
16597 case OMPC_map:
16598 case OMPC_nogroup:
16599 case OMPC_dist_schedule:
16600 case OMPC_defaultmap:
16601 case OMPC_unknown:
16602 case OMPC_uniform:
16603 case OMPC_to:
16604 case OMPC_from:
16605 case OMPC_use_device_ptr:
16606 case OMPC_use_device_addr:
16607 case OMPC_is_device_ptr:
16608 case OMPC_unified_address:
16609 case OMPC_unified_shared_memory:
16610 case OMPC_reverse_offload:
16611 case OMPC_dynamic_allocators:
16612 case OMPC_atomic_default_mem_order:
16613 case OMPC_self_maps:
16614 case OMPC_device_type:
16615 case OMPC_match:
16616 case OMPC_nontemporal:
16617 case OMPC_order:
16618 case OMPC_at:
16619 case OMPC_severity:
16620 case OMPC_destroy:
16621 case OMPC_inclusive:
16622 case OMPC_exclusive:
16623 case OMPC_uses_allocators:
16624 case OMPC_affinity:
16625 case OMPC_when:
16626 case OMPC_bind:
16627 case OMPC_num_teams:
16628 case OMPC_thread_limit:
16629 default:
16630 llvm_unreachable("Clause is not allowed.");
16631 }
16632 return Res;
16633}
16634
16635// An OpenMP directive such as 'target parallel' has two captured regions:
16636// for the 'target' and 'parallel' respectively. This function returns
16637// the region in which to capture expressions associated with a clause.
16638// A return value of OMPD_unknown signifies that the expression should not
16639// be captured.
16641 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
16642 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
16643 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
16644 "Invalid directive with CKind-clause");
16645
16646 // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
16647 if (NameModifier != OMPD_unknown &&
16648 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
16649 return OMPD_unknown;
16650
16651 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(DKind);
16652
16653 // [5.2:341:24-30]
16654 // If the clauses have expressions on them, such as for various clauses where
16655 // the argument of the clause is an expression, or lower-bound, length, or
16656 // stride expressions inside array sections (or subscript and stride
16657 // expressions in subscript-triplet for Fortran), or linear-step or alignment
16658 // expressions, the expressions are evaluated immediately before the construct
16659 // to which the clause has been split or duplicated per the above rules
16660 // (therefore inside of the outer leaf constructs). However, the expressions
16661 // inside the num_teams and thread_limit clauses are always evaluated before
16662 // the outermost leaf construct.
16663
16664 // Process special cases first.
16665 switch (CKind) {
16666 case OMPC_if:
16667 switch (DKind) {
16668 case OMPD_teams_loop:
16669 case OMPD_target_teams_loop:
16670 // For [target] teams loop, assume capture region is 'teams' so it's
16671 // available for codegen later to use if/when necessary.
16672 return OMPD_teams;
16673 case OMPD_target_update:
16674 case OMPD_target_enter_data:
16675 case OMPD_target_exit_data:
16676 return OMPD_task;
16677 default:
16678 break;
16679 }
16680 break;
16681 case OMPC_num_teams:
16682 case OMPC_thread_limit:
16683 case OMPC_ompx_dyn_cgroup_mem:
16684 case OMPC_dyn_groupprivate:
16685 // TODO: This may need to consider teams too.
16686 if (Leafs[0] == OMPD_target)
16687 return OMPD_target;
16688 break;
16689 case OMPC_device:
16690 if (Leafs[0] == OMPD_target ||
16691 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
16692 OMPD_target_enter_data, OMPD_target_exit_data},
16693 DKind))
16694 return OMPD_task;
16695 break;
16696 case OMPC_novariants:
16697 case OMPC_nocontext:
16698 if (DKind == OMPD_dispatch)
16699 return OMPD_task;
16700 break;
16701 case OMPC_when:
16702 if (DKind == OMPD_metadirective)
16703 return OMPD_metadirective;
16704 break;
16705 case OMPC_filter:
16706 return OMPD_unknown;
16707 default:
16708 break;
16709 }
16710
16711 // If none of the special cases above applied, and DKind is a capturing
16712 // directive, find the innermost enclosing leaf construct that allows the
16713 // clause, and returns the corresponding capture region.
16714
16715 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
16716 // Find the index in "Leafs" of the last leaf that allows the given
16717 // clause. The search will only include indexes [0, EndIdx).
16718 // EndIdx may be set to the index of the NameModifier, if present.
16719 int InnermostIdx = [&]() {
16720 for (int I = EndIdx - 1; I >= 0; --I) {
16721 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
16722 return I;
16723 }
16724 return -1;
16725 }();
16726
16727 // Find the nearest enclosing capture region.
16729 for (int I = InnermostIdx - 1; I >= 0; --I) {
16730 if (!isOpenMPCapturingDirective(Leafs[I]))
16731 continue;
16732 Regions.clear();
16733 getOpenMPCaptureRegions(Regions, Leafs[I]);
16734 if (Regions[0] != OMPD_unknown)
16735 return Regions.back();
16736 }
16737 return OMPD_unknown;
16738 };
16739
16740 if (isOpenMPCapturingDirective(DKind)) {
16741 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
16742 for (int I = 0, E = Leafs.size(); I != E; ++I) {
16743 if (Leafs[I] == Dir)
16744 return I + 1;
16745 }
16746 return 0;
16747 };
16748
16749 int End = NameModifier == OMPD_unknown ? Leafs.size()
16750 : GetLeafIndex(NameModifier);
16751 return GetEnclosingRegion(End, CKind);
16752 }
16753
16754 return OMPD_unknown;
16755}
16756
16758 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
16759 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
16760 SourceLocation ColonLoc, 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 = Val.get();
16772
16773 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16774 CaptureRegion = getOpenMPCaptureRegionForClause(
16775 DKind, OMPC_if, getLangOpts().OpenMP, NameModifier);
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())
16786 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16787 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16788}
16789
16791 SourceLocation StartLoc,
16792 SourceLocation LParenLoc,
16793 SourceLocation EndLoc) {
16794 Expr *ValExpr = Condition;
16795 Stmt *HelperValStmt = nullptr;
16796 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16797 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16798 !Condition->isInstantiationDependent() &&
16799 !Condition->containsUnexpandedParameterPack()) {
16800 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
16801 if (Val.isInvalid())
16802 return nullptr;
16803
16804 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
16805
16806 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16807 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final,
16808 getLangOpts().OpenMP);
16809 if (CaptureRegion != OMPD_unknown &&
16810 !SemaRef.CurContext->isDependentContext()) {
16811 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16812 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16813 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16814 HelperValStmt = buildPreInits(getASTContext(), Captures);
16815 }
16816 }
16817
16818 return new (getASTContext()) OMPFinalClause(
16819 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16820}
16821
16824 Expr *Op) {
16825 if (!Op)
16826 return ExprError();
16827
16828 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
16829 public:
16830 IntConvertDiagnoser()
16831 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {}
16832 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
16833 QualType T) override {
16834 return S.Diag(Loc, diag::err_omp_not_integral) << T;
16835 }
16836 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
16837 QualType T) override {
16838 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
16839 }
16840 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
16841 QualType T,
16842 QualType ConvTy) override {
16843 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
16844 }
16845 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
16846 QualType ConvTy) override {
16847 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16848 << ConvTy->isEnumeralType() << ConvTy;
16849 }
16850 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
16851 QualType T) override {
16852 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
16853 }
16854 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
16855 QualType ConvTy) override {
16856 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16857 << ConvTy->isEnumeralType() << ConvTy;
16858 }
16859 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
16860 QualType) override {
16861 llvm_unreachable("conversion functions are permitted");
16862 }
16863 } ConvertDiagnoser;
16864 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16865}
16866
16867static bool
16869 bool StrictlyPositive, bool BuildCapture = false,
16870 OpenMPDirectiveKind DKind = OMPD_unknown,
16871 OpenMPDirectiveKind *CaptureRegion = nullptr,
16872 Stmt **HelperValStmt = nullptr) {
16873 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
16874 !ValExpr->isInstantiationDependent()) {
16875 SourceLocation Loc = ValExpr->getExprLoc();
16877 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
16878 if (Value.isInvalid())
16879 return false;
16880
16881 ValExpr = Value.get();
16882 // The expression must evaluate to a non-negative integer value.
16883 if (std::optional<llvm::APSInt> Result =
16884 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
16885 if (Result->isSigned() &&
16886 !((!StrictlyPositive && Result->isNonNegative()) ||
16887 (StrictlyPositive && Result->isStrictlyPositive()))) {
16888 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
16889 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
16890 << ValExpr->getSourceRange();
16891 return false;
16892 }
16893 }
16894 if (!BuildCapture)
16895 return true;
16896 *CaptureRegion =
16897 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
16898 if (*CaptureRegion != OMPD_unknown &&
16899 !SemaRef.CurContext->isDependentContext()) {
16900 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16901 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16902 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16903 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
16904 }
16905 }
16906 return true;
16907}
16908
16909static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First,
16910 unsigned Last,
16911 ArrayRef<unsigned> Exclude = {}) {
16912 SmallString<256> Buffer;
16913 llvm::raw_svector_ostream Out(Buffer);
16914 unsigned Skipped = Exclude.size();
16915 for (unsigned I = First; I < Last; ++I) {
16916 if (llvm::is_contained(Exclude, I)) {
16917 --Skipped;
16918 continue;
16919 }
16920 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
16921 if (I + Skipped + 2 == Last)
16922 Out << " or ";
16923 else if (I + Skipped + 1 != Last)
16924 Out << ", ";
16925 }
16926 return std::string(Out.str());
16927}
16928
16930 OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads,
16931 SourceLocation StartLoc, SourceLocation LParenLoc,
16932 SourceLocation ModifierLoc, SourceLocation EndLoc) {
16933 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 60) &&
16934 "Unexpected num_threads modifier in OpenMP < 60.");
16935
16936 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTHREADS_unknown) {
16937 std::string Values = getListOfPossibleValues(OMPC_num_threads, /*First=*/0,
16939 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
16940 << Values << getOpenMPClauseNameForDiag(OMPC_num_threads);
16941 return nullptr;
16942 }
16943
16944 Expr *ValExpr = NumThreads;
16945 Stmt *HelperValStmt = nullptr;
16946
16947 // OpenMP [2.5, Restrictions]
16948 // The num_threads expression must evaluate to a positive integer value.
16949 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads,
16950 /*StrictlyPositive=*/true))
16951 return nullptr;
16952
16953 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16955 DKind, OMPC_num_threads, getLangOpts().OpenMP);
16956 if (CaptureRegion != OMPD_unknown &&
16957 !SemaRef.CurContext->isDependentContext()) {
16958 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16959 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16960 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16961 HelperValStmt = buildPreInits(getASTContext(), Captures);
16962 }
16963
16964 return new (getASTContext())
16965 OMPNumThreadsClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
16966 StartLoc, LParenLoc, ModifierLoc, EndLoc);
16967}
16968
16970 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
16971 bool SuppressExprDiags) {
16972 if (!E)
16973 return ExprError();
16974 if (E->isValueDependent() || E->isTypeDependent() ||
16976 return E;
16977
16978 llvm::APSInt Result;
16979 ExprResult ICE;
16980 if (SuppressExprDiags) {
16981 // Use a custom diagnoser that suppresses 'note' diagnostics about the
16982 // expression.
16983 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
16984 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
16986 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
16987 llvm_unreachable("Diagnostic suppressed");
16988 }
16989 } Diagnoser;
16990 ICE = SemaRef.VerifyIntegerConstantExpression(E, &Result, Diagnoser,
16992 } else {
16993 ICE =
16994 SemaRef.VerifyIntegerConstantExpression(E, &Result,
16995 /*FIXME*/ AllowFoldKind::Allow);
16996 }
16997 if (ICE.isInvalid())
16998 return ExprError();
16999
17000 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
17001 (!StrictlyPositive && !Result.isNonNegative())) {
17002 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
17003 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
17004 << E->getSourceRange();
17005 return ExprError();
17006 }
17007 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
17008 CKind == OMPC_allocate) &&
17009 !Result.isPowerOf2()) {
17010 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
17011 << E->getSourceRange();
17012 return ExprError();
17013 }
17014
17015 if (!Result.isRepresentableByInt64()) {
17016 Diag(E->getExprLoc(), diag::err_omp_large_expression_in_clause)
17018 return ExprError();
17019 }
17020
17021 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
17022 DSAStack->setAssociatedLoops(Result.getExtValue());
17023 else if (CKind == OMPC_ordered)
17024 DSAStack->setAssociatedLoops(Result.getExtValue());
17025 return ICE;
17026}
17027
17028void SemaOpenMP::setOpenMPDeviceNum(int Num) { DeviceNum = Num; }
17029
17030void SemaOpenMP::setOpenMPDeviceNumID(StringRef ID) { DeviceNumID = ID; }
17031
17032int SemaOpenMP::getOpenMPDeviceNum() const { return DeviceNum; }
17033
17035 llvm::APSInt Result;
17036 Expr::EvalResult EvalResult;
17037 // Evaluate the expression to an integer value
17038 if (!DeviceNumExpr->isValueDependent() &&
17039 DeviceNumExpr->EvaluateAsInt(EvalResult, SemaRef.Context)) {
17040 // The device expression must evaluate to a non-negative integer value.
17041 Result = EvalResult.Val.getInt();
17042 if (Result.isNonNegative()) {
17043 setOpenMPDeviceNum(Result.getZExtValue());
17044 } else {
17045 Diag(DeviceNumExpr->getExprLoc(),
17046 diag::err_omp_negative_expression_in_clause)
17047 << "device_num" << 0 << DeviceNumExpr->getSourceRange();
17048 }
17049 } else if (auto *DeclRef = dyn_cast<DeclRefExpr>(DeviceNumExpr)) {
17050 // Check if the expression is an identifier
17051 IdentifierInfo *IdInfo = DeclRef->getDecl()->getIdentifier();
17052 if (IdInfo) {
17053 setOpenMPDeviceNumID(IdInfo->getName());
17054 }
17055 } else {
17056 Diag(DeviceNumExpr->getExprLoc(), diag::err_expected_expression);
17057 }
17058}
17059
17061 SourceLocation StartLoc,
17062 SourceLocation LParenLoc,
17063 SourceLocation EndLoc) {
17064 // OpenMP [2.8.1, simd construct, Description]
17065 // The parameter of the safelen clause must be a constant
17066 // positive integer expression.
17067 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
17068 if (Safelen.isInvalid())
17069 return nullptr;
17070 return new (getASTContext())
17071 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
17072}
17073
17075 SourceLocation StartLoc,
17076 SourceLocation LParenLoc,
17077 SourceLocation EndLoc) {
17078 // OpenMP [2.8.1, simd construct, Description]
17079 // The parameter of the simdlen clause must be a constant
17080 // positive integer expression.
17081 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
17082 if (Simdlen.isInvalid())
17083 return nullptr;
17084 return new (getASTContext())
17085 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
17086}
17087
17088/// Tries to find omp_allocator_handle_t type.
17090 DSAStackTy *Stack) {
17091 if (!Stack->getOMPAllocatorHandleT().isNull())
17092 return true;
17093
17094 // Set the allocator handle type.
17095 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
17096 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
17097 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
17098 S.Diag(Loc, diag::err_omp_implied_type_not_found)
17099 << "omp_allocator_handle_t";
17100 return false;
17101 }
17102 QualType AllocatorHandleEnumTy = PT.get();
17103 AllocatorHandleEnumTy.addConst();
17104 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
17105
17106 // Fill the predefined allocator map.
17107 bool ErrorFound = false;
17108 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
17109 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
17110 StringRef Allocator =
17111 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
17112 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
17113 auto *VD = dyn_cast_or_null<ValueDecl>(
17114 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
17115 if (!VD) {
17116 ErrorFound = true;
17117 break;
17118 }
17119 QualType AllocatorType =
17121 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
17122 if (!Res.isUsable()) {
17123 ErrorFound = true;
17124 break;
17125 }
17126 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
17128 /*AllowExplicit=*/true);
17129 if (!Res.isUsable()) {
17130 ErrorFound = true;
17131 break;
17132 }
17133 Stack->setAllocator(AllocatorKind, Res.get());
17134 }
17135 if (ErrorFound) {
17136 S.Diag(Loc, diag::err_omp_implied_type_not_found)
17137 << "omp_allocator_handle_t";
17138 return false;
17139 }
17140
17141 return true;
17142}
17143
17145 SourceLocation StartLoc,
17146 SourceLocation LParenLoc,
17147 SourceLocation EndLoc) {
17148 // OpenMP [2.11.3, allocate Directive, Description]
17149 // allocator is an expression of omp_allocator_handle_t type.
17151 return nullptr;
17152
17153 ExprResult Allocator = SemaRef.DefaultLvalueConversion(A);
17154 if (Allocator.isInvalid())
17155 return nullptr;
17156 Allocator = SemaRef.PerformImplicitConversion(
17157 Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
17159 /*AllowExplicit=*/true);
17160 if (Allocator.isInvalid())
17161 return nullptr;
17162 return new (getASTContext())
17163 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
17164}
17165
17167 SourceLocation StartLoc,
17168 SourceLocation LParenLoc,
17169 SourceLocation EndLoc) {
17170 // OpenMP [2.7.1, loop construct, Description]
17171 // OpenMP [2.8.1, simd construct, Description]
17172 // OpenMP [2.9.6, distribute construct, Description]
17173 // The parameter of the collapse clause must be a constant
17174 // positive integer expression.
17175 ExprResult NumForLoopsResult =
17176 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
17177 if (NumForLoopsResult.isInvalid())
17178 return nullptr;
17179 return new (getASTContext())
17180 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
17181}
17182
17184 SourceLocation EndLoc,
17185 SourceLocation LParenLoc,
17186 Expr *NumForLoops) {
17187 // OpenMP [2.7.1, loop construct, Description]
17188 // OpenMP [2.8.1, simd construct, Description]
17189 // OpenMP [2.9.6, distribute construct, Description]
17190 // The parameter of the ordered clause must be a constant
17191 // positive integer expression if any.
17192 if (NumForLoops && LParenLoc.isValid()) {
17193 ExprResult NumForLoopsResult =
17194 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
17195 if (NumForLoopsResult.isInvalid())
17196 return nullptr;
17197 NumForLoops = NumForLoopsResult.get();
17198 } else {
17199 NumForLoops = nullptr;
17200 }
17201 auto *Clause =
17203 NumForLoops ? DSAStack->getAssociatedLoops() : 0,
17204 StartLoc, LParenLoc, EndLoc);
17205 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
17206 return Clause;
17207}
17208
17210 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
17211 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17212 OMPClause *Res = nullptr;
17213 switch (Kind) {
17214 case OMPC_proc_bind:
17215 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
17216 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17217 break;
17218 case OMPC_atomic_default_mem_order:
17220 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
17221 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17222 break;
17223 case OMPC_fail:
17224 Res = ActOnOpenMPFailClause(static_cast<OpenMPClauseKind>(Argument),
17225 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17226 break;
17227 case OMPC_update:
17228 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
17229 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17230 break;
17231 case OMPC_bind:
17232 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
17233 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17234 break;
17235 case OMPC_at:
17236 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
17237 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17238 break;
17239 case OMPC_severity:
17241 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
17242 LParenLoc, EndLoc);
17243 break;
17244 case OMPC_threadset:
17245 Res = ActOnOpenMPThreadsetClause(static_cast<OpenMPThreadsetKind>(Argument),
17246 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17247 break;
17248 case OMPC_if:
17249 case OMPC_final:
17250 case OMPC_num_threads:
17251 case OMPC_safelen:
17252 case OMPC_simdlen:
17253 case OMPC_sizes:
17254 case OMPC_allocator:
17255 case OMPC_collapse:
17256 case OMPC_schedule:
17257 case OMPC_private:
17258 case OMPC_firstprivate:
17259 case OMPC_lastprivate:
17260 case OMPC_shared:
17261 case OMPC_reduction:
17262 case OMPC_task_reduction:
17263 case OMPC_in_reduction:
17264 case OMPC_linear:
17265 case OMPC_aligned:
17266 case OMPC_copyin:
17267 case OMPC_copyprivate:
17268 case OMPC_ordered:
17269 case OMPC_nowait:
17270 case OMPC_untied:
17271 case OMPC_mergeable:
17272 case OMPC_threadprivate:
17273 case OMPC_groupprivate:
17274 case OMPC_allocate:
17275 case OMPC_flush:
17276 case OMPC_depobj:
17277 case OMPC_read:
17278 case OMPC_write:
17279 case OMPC_capture:
17280 case OMPC_compare:
17281 case OMPC_seq_cst:
17282 case OMPC_acq_rel:
17283 case OMPC_acquire:
17284 case OMPC_release:
17285 case OMPC_relaxed:
17286 case OMPC_depend:
17287 case OMPC_device:
17288 case OMPC_threads:
17289 case OMPC_simd:
17290 case OMPC_map:
17291 case OMPC_num_teams:
17292 case OMPC_thread_limit:
17293 case OMPC_priority:
17294 case OMPC_grainsize:
17295 case OMPC_nogroup:
17296 case OMPC_num_tasks:
17297 case OMPC_hint:
17298 case OMPC_dist_schedule:
17299 case OMPC_default:
17300 case OMPC_defaultmap:
17301 case OMPC_unknown:
17302 case OMPC_uniform:
17303 case OMPC_to:
17304 case OMPC_from:
17305 case OMPC_use_device_ptr:
17306 case OMPC_use_device_addr:
17307 case OMPC_is_device_ptr:
17308 case OMPC_has_device_addr:
17309 case OMPC_unified_address:
17310 case OMPC_unified_shared_memory:
17311 case OMPC_reverse_offload:
17312 case OMPC_dynamic_allocators:
17313 case OMPC_self_maps:
17314 case OMPC_device_type:
17315 case OMPC_match:
17316 case OMPC_nontemporal:
17317 case OMPC_destroy:
17318 case OMPC_novariants:
17319 case OMPC_nocontext:
17320 case OMPC_detach:
17321 case OMPC_inclusive:
17322 case OMPC_exclusive:
17323 case OMPC_uses_allocators:
17324 case OMPC_affinity:
17325 case OMPC_when:
17326 case OMPC_message:
17327 default:
17328 llvm_unreachable("Clause is not allowed.");
17329 }
17330 return Res;
17331}
17332
17334 llvm::omp::DefaultKind M, SourceLocation MLoc,
17336 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17337 if (M == OMP_DEFAULT_unknown) {
17338 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17339 << getListOfPossibleValues(OMPC_default, /*First=*/0,
17340 /*Last=*/unsigned(OMP_DEFAULT_unknown))
17341 << getOpenMPClauseNameForDiag(OMPC_default);
17342 return nullptr;
17343 }
17344 if (VCKind == OMPC_DEFAULT_VC_unknown) {
17345 Diag(VCKindLoc, diag::err_omp_default_vc)
17346 << getOpenMPSimpleClauseTypeName(OMPC_default, unsigned(M));
17347 return nullptr;
17348 }
17349
17350 bool IsTargetDefault =
17351 getLangOpts().OpenMP >= 60 &&
17352 isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective());
17353
17354 // OpenMP 6.0, page 224, lines 3-4 default Clause, Semantics
17355 // If data-sharing-attribute is shared then the clause has no effect
17356 // on a target construct;
17357 if (IsTargetDefault && M == OMP_DEFAULT_shared)
17358 return nullptr;
17359
17360 auto SetDefaultClauseAttrs = [&](llvm::omp::DefaultKind M,
17363 OpenMPDefaultmapClauseKind DefMapKind;
17364 // default data-sharing-attribute
17365 switch (M) {
17366 case OMP_DEFAULT_none:
17367 if (IsTargetDefault)
17368 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_none;
17369 else
17370 DSAStack->setDefaultDSANone(MLoc);
17371 break;
17372 case OMP_DEFAULT_firstprivate:
17373 if (IsTargetDefault)
17374 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_firstprivate;
17375 else
17376 DSAStack->setDefaultDSAFirstPrivate(MLoc);
17377 break;
17378 case OMP_DEFAULT_private:
17379 if (IsTargetDefault)
17380 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_private;
17381 else
17382 DSAStack->setDefaultDSAPrivate(MLoc);
17383 break;
17384 case OMP_DEFAULT_shared:
17385 assert(!IsTargetDefault && "DSA shared invalid with target directive");
17386 DSAStack->setDefaultDSAShared(MLoc);
17387 break;
17388 default:
17389 llvm_unreachable("unexpected DSA in OpenMP default clause");
17390 }
17391 // default variable-category
17392 switch (VCKind) {
17393 case OMPC_DEFAULT_VC_aggregate:
17394 if (IsTargetDefault)
17395 DefMapKind = OMPC_DEFAULTMAP_aggregate;
17396 else
17397 DSAStack->setDefaultDSAVCAggregate(VCKindLoc);
17398 break;
17399 case OMPC_DEFAULT_VC_pointer:
17400 if (IsTargetDefault)
17401 DefMapKind = OMPC_DEFAULTMAP_pointer;
17402 else
17403 DSAStack->setDefaultDSAVCPointer(VCKindLoc);
17404 break;
17405 case OMPC_DEFAULT_VC_scalar:
17406 if (IsTargetDefault)
17407 DefMapKind = OMPC_DEFAULTMAP_scalar;
17408 else
17409 DSAStack->setDefaultDSAVCScalar(VCKindLoc);
17410 break;
17411 case OMPC_DEFAULT_VC_all:
17412 if (IsTargetDefault)
17413 DefMapKind = OMPC_DEFAULTMAP_all;
17414 else
17415 DSAStack->setDefaultDSAVCAll(VCKindLoc);
17416 break;
17417 default:
17418 llvm_unreachable("unexpected variable category in OpenMP default clause");
17419 }
17420 // OpenMP 6.0, page 224, lines 4-5 default Clause, Semantics
17421 // otherwise, its effect on a target construct is equivalent to
17422 // specifying the defaultmap clause with the same data-sharing-attribute
17423 // and variable-category.
17424 //
17425 // If earlier than OpenMP 6.0, or not a target directive, the default DSA
17426 // is/was set as before.
17427 if (IsTargetDefault) {
17428 if (DefMapKind == OMPC_DEFAULTMAP_all) {
17429 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_aggregate, MLoc);
17430 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_scalar, MLoc);
17431 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_pointer, MLoc);
17432 } else {
17433 DSAStack->setDefaultDMAAttr(DefMapMod, DefMapKind, MLoc);
17434 }
17435 }
17436 };
17437
17438 SetDefaultClauseAttrs(M, VCKind);
17439 return new (getASTContext())
17440 OMPDefaultClause(M, MLoc, VCKind, VCKindLoc, StartLoc, LParenLoc, EndLoc);
17441}
17442
17444 SourceLocation KindLoc,
17445 SourceLocation StartLoc,
17446 SourceLocation LParenLoc,
17447 SourceLocation EndLoc) {
17448 if (Kind == OMPC_THREADSET_unknown) {
17449 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17450 << getListOfPossibleValues(OMPC_threadset, /*First=*/0,
17451 /*Last=*/unsigned(OMPC_THREADSET_unknown))
17452 << getOpenMPClauseName(OMPC_threadset);
17453 return nullptr;
17454 }
17455
17456 return new (getASTContext())
17457 OMPThreadsetClause(Kind, KindLoc, StartLoc, LParenLoc, EndLoc);
17458}
17459
17461 SourceLocation KindKwLoc,
17462 SourceLocation StartLoc,
17463 SourceLocation LParenLoc,
17464 SourceLocation EndLoc) {
17465 if (Kind == OMP_PROC_BIND_unknown) {
17466 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17467 << getListOfPossibleValues(OMPC_proc_bind,
17468 /*First=*/unsigned(OMP_PROC_BIND_master),
17469 /*Last=*/
17470 unsigned(getLangOpts().OpenMP > 50
17471 ? OMP_PROC_BIND_primary
17472 : OMP_PROC_BIND_spread) +
17473 1)
17474 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
17475 return nullptr;
17476 }
17477 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
17478 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17479 << getListOfPossibleValues(OMPC_proc_bind,
17480 /*First=*/unsigned(OMP_PROC_BIND_master),
17481 /*Last=*/
17482 unsigned(OMP_PROC_BIND_spread) + 1)
17483 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
17484 return new (getASTContext())
17485 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17486}
17487
17490 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17492 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17494 OMPC_atomic_default_mem_order, /*First=*/0,
17496 << getOpenMPClauseNameForDiag(OMPC_atomic_default_mem_order);
17497 return nullptr;
17498 }
17500 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17501}
17502
17504 SourceLocation KindKwLoc,
17505 SourceLocation StartLoc,
17506 SourceLocation LParenLoc,
17507 SourceLocation EndLoc) {
17508 if (Kind == OMPC_AT_unknown) {
17509 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17510 << getListOfPossibleValues(OMPC_at, /*First=*/0,
17511 /*Last=*/OMPC_AT_unknown)
17512 << getOpenMPClauseNameForDiag(OMPC_at);
17513 return nullptr;
17514 }
17515 return new (getASTContext())
17516 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17517}
17518
17520 SourceLocation KindKwLoc,
17521 SourceLocation StartLoc,
17522 SourceLocation LParenLoc,
17523 SourceLocation EndLoc) {
17524 if (Kind == OMPC_SEVERITY_unknown) {
17525 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17526 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
17527 /*Last=*/OMPC_SEVERITY_unknown)
17528 << getOpenMPClauseNameForDiag(OMPC_severity);
17529 return nullptr;
17530 }
17531 return new (getASTContext())
17532 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17533}
17534
17536 SourceLocation StartLoc,
17537 SourceLocation LParenLoc,
17538 SourceLocation EndLoc) {
17539 assert(ME && "NULL expr in Message clause");
17540 QualType Type = ME->getType();
17541 if ((!Type->isPointerType() && !Type->isArrayType()) ||
17543 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
17544 << getOpenMPClauseNameForDiag(OMPC_message) << 0;
17545 return nullptr;
17546 }
17547
17548 Stmt *HelperValStmt = nullptr;
17549
17550 // Depending on whether this clause appears in an executable context or not,
17551 // we may or may not build a capture.
17552 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17553 OpenMPDirectiveKind CaptureRegion =
17554 DKind == OMPD_unknown ? OMPD_unknown
17556 DKind, OMPC_message, getLangOpts().OpenMP);
17557 if (CaptureRegion != OMPD_unknown &&
17558 !SemaRef.CurContext->isDependentContext()) {
17559 ME = SemaRef.MakeFullExpr(ME).get();
17560 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17561 ME = tryBuildCapture(SemaRef, ME, Captures).get();
17562 HelperValStmt = buildPreInits(getASTContext(), Captures);
17563 }
17564
17565 // Convert array type to pointer type if needed.
17566 ME = SemaRef.DefaultFunctionArrayLvalueConversion(ME).get();
17567
17568 return new (getASTContext()) OMPMessageClause(
17569 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17570}
17571
17574 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
17575 SourceLocation KindLoc, SourceLocation EndLoc) {
17576 if (Kind != OMPC_ORDER_concurrent ||
17577 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
17578 // Kind should be concurrent,
17579 // Modifiers introduced in OpenMP 5.1
17580 static_assert(OMPC_ORDER_unknown > 0,
17581 "OMPC_ORDER_unknown not greater than 0");
17582
17583 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17584 << getListOfPossibleValues(OMPC_order,
17585 /*First=*/0,
17586 /*Last=*/OMPC_ORDER_unknown)
17587 << getOpenMPClauseNameForDiag(OMPC_order);
17588 return nullptr;
17589 }
17590 if (getLangOpts().OpenMP >= 51 && Modifier == OMPC_ORDER_MODIFIER_unknown &&
17591 MLoc.isValid()) {
17592 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17593 << getListOfPossibleValues(OMPC_order,
17594 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
17595 /*Last=*/OMPC_ORDER_MODIFIER_last)
17596 << getOpenMPClauseNameForDiag(OMPC_order);
17597 } else if (getLangOpts().OpenMP >= 50) {
17598 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
17599 if (DSAStack->getCurScope()) {
17600 // mark the current scope with 'order' flag
17601 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
17602 DSAStack->getCurScope()->setFlags(existingFlags |
17604 }
17605 }
17606 return new (getASTContext()) OMPOrderClause(
17607 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
17608}
17609
17611 SourceLocation KindKwLoc,
17612 SourceLocation StartLoc,
17613 SourceLocation LParenLoc,
17614 SourceLocation EndLoc) {
17615 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
17616 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
17617 SmallVector<unsigned> Except = {
17618 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
17619 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
17620 if (getLangOpts().OpenMP < 51)
17621 Except.push_back(OMPC_DEPEND_inoutset);
17622 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17623 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
17624 /*Last=*/OMPC_DEPEND_unknown, Except)
17625 << getOpenMPClauseNameForDiag(OMPC_update);
17626 return nullptr;
17627 }
17628 return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc,
17629 KindKwLoc, Kind, EndLoc);
17630}
17631
17633 SourceLocation StartLoc,
17634 SourceLocation LParenLoc,
17635 SourceLocation EndLoc) {
17636 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
17637
17638 for (Expr *&SizeExpr : SanitizedSizeExprs) {
17639 // Skip if already sanitized, e.g. during a partial template instantiation.
17640 if (!SizeExpr)
17641 continue;
17642
17643 bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes,
17644 /*StrictlyPositive=*/true);
17645
17646 // isNonNegativeIntegerValue returns true for non-integral types (but still
17647 // emits error diagnostic), so check for the expected type explicitly.
17648 QualType SizeTy = SizeExpr->getType();
17649 if (!SizeTy->isIntegerType())
17650 IsValid = false;
17651
17652 // Handling in templates is tricky. There are four possibilities to
17653 // consider:
17654 //
17655 // 1a. The expression is valid and we are in a instantiated template or not
17656 // in a template:
17657 // Pass valid expression to be further analysed later in Sema.
17658 // 1b. The expression is valid and we are in a template (including partial
17659 // instantiation):
17660 // isNonNegativeIntegerValue skipped any checks so there is no
17661 // guarantee it will be correct after instantiation.
17662 // ActOnOpenMPSizesClause will be called again at instantiation when
17663 // it is not in a dependent context anymore. This may cause warnings
17664 // to be emitted multiple times.
17665 // 2a. The expression is invalid and we are in an instantiated template or
17666 // not in a template:
17667 // Invalidate the expression with a clearly wrong value (nullptr) so
17668 // later in Sema we do not have to do the same validity analysis again
17669 // or crash from unexpected data. Error diagnostics have already been
17670 // emitted.
17671 // 2b. The expression is invalid and we are in a template (including partial
17672 // instantiation):
17673 // Pass the invalid expression as-is, template instantiation may
17674 // replace unexpected types/values with valid ones. The directives
17675 // with this clause must not try to use these expressions in dependent
17676 // contexts, but delay analysis until full instantiation.
17677 if (!SizeExpr->isInstantiationDependent() && !IsValid)
17678 SizeExpr = nullptr;
17679 }
17680
17681 return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17682 SanitizedSizeExprs);
17683}
17684
17686 SourceLocation StartLoc,
17687 SourceLocation LParenLoc,
17688 SourceLocation EndLoc) {
17689 size_t NumLoops = PermExprs.size();
17690 SmallVector<Expr *> SanitizedPermExprs;
17691 llvm::append_range(SanitizedPermExprs, PermExprs);
17692
17693 for (Expr *&PermExpr : SanitizedPermExprs) {
17694 // Skip if template-dependent or already sanitized, e.g. during a partial
17695 // template instantiation.
17696 if (!PermExpr || PermExpr->isInstantiationDependent())
17697 continue;
17698
17699 llvm::APSInt PermVal;
17700 ExprResult PermEvalExpr = SemaRef.VerifyIntegerConstantExpression(
17701 PermExpr, &PermVal, AllowFoldKind::Allow);
17702 bool IsValid = PermEvalExpr.isUsable();
17703 if (IsValid)
17704 PermExpr = PermEvalExpr.get();
17705
17706 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
17707 SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
17708 PermEvalExpr.get()->getEndLoc());
17709 Diag(PermEvalExpr.get()->getExprLoc(),
17710 diag::err_omp_interchange_permutation_value_range)
17711 << NumLoops << ExprRange;
17712 IsValid = false;
17713 }
17714
17715 if (!PermExpr->isInstantiationDependent() && !IsValid)
17716 PermExpr = nullptr;
17717 }
17718
17719 return OMPPermutationClause::Create(getASTContext(), StartLoc, LParenLoc,
17720 EndLoc, SanitizedPermExprs);
17721}
17722
17724 SourceLocation EndLoc) {
17725 return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc);
17726}
17727
17729 SourceLocation StartLoc,
17730 SourceLocation LParenLoc,
17731 SourceLocation EndLoc) {
17732 if (FactorExpr) {
17733 // If an argument is specified, it must be a constant (or an unevaluated
17734 // template expression).
17736 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
17737 if (FactorResult.isInvalid())
17738 return nullptr;
17739 FactorExpr = FactorResult.get();
17740 }
17741
17742 return OMPPartialClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17743 FactorExpr);
17744}
17745
17747 Expr *First, Expr *Count, SourceLocation StartLoc, SourceLocation LParenLoc,
17748 SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc) {
17749
17750 // OpenMP [6.0, Restrictions]
17751 // First and Count must be integer expressions with positive value
17752 ExprResult FirstVal =
17754 if (FirstVal.isInvalid())
17755 First = nullptr;
17756
17757 ExprResult CountVal =
17758 VerifyPositiveIntegerConstantInClause(Count, OMPC_looprange);
17759 if (CountVal.isInvalid())
17760 Count = nullptr;
17761
17762 // OpenMP [6.0, Restrictions]
17763 // first + count - 1 must not evaluate to a value greater than the
17764 // loop sequence length of the associated canonical loop sequence.
17765 // This check must be performed afterwards due to the delayed
17766 // parsing and computation of the associated loop sequence
17767 return OMPLoopRangeClause::Create(getASTContext(), StartLoc, LParenLoc,
17768 FirstLoc, CountLoc, EndLoc, First, Count);
17769}
17770
17772 SourceLocation LParenLoc,
17773 SourceLocation EndLoc) {
17774 ExprResult AlignVal;
17775 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
17776 if (AlignVal.isInvalid())
17777 return nullptr;
17778 return OMPAlignClause::Create(getASTContext(), AlignVal.get(), StartLoc,
17779 LParenLoc, EndLoc);
17780}
17781
17784 SourceLocation StartLoc, SourceLocation LParenLoc,
17785 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
17786 SourceLocation EndLoc) {
17787 OMPClause *Res = nullptr;
17788 switch (Kind) {
17789 case OMPC_schedule: {
17790 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
17791 assert(Argument.size() == NumberOfElements &&
17792 ArgumentLoc.size() == NumberOfElements);
17794 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
17795 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
17796 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
17797 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
17798 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
17799 break;
17800 }
17801 case OMPC_if:
17802 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17803 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
17804 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
17805 DelimLoc, EndLoc);
17806 break;
17807 case OMPC_dist_schedule:
17809 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
17810 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
17811 break;
17812 case OMPC_default:
17813 enum { DefaultModifier, DefaultVarCategory };
17815 static_cast<llvm::omp::DefaultKind>(Argument[DefaultModifier]),
17816 ArgumentLoc[DefaultModifier],
17818 Argument[DefaultVarCategory]),
17819 ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc);
17820 break;
17821 case OMPC_defaultmap:
17822 enum { Modifier, DefaultmapKind };
17824 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
17825 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
17826 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
17827 EndLoc);
17828 break;
17829 case OMPC_order:
17830 enum { OrderModifier, OrderKind };
17832 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
17833 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
17834 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
17835 break;
17836 case OMPC_device:
17837 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17839 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
17840 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17841 break;
17842 case OMPC_grainsize:
17843 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17844 "Modifier for grainsize clause and its location are expected.");
17846 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
17847 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17848 break;
17849 case OMPC_num_tasks:
17850 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17851 "Modifier for num_tasks clause and its location are expected.");
17853 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
17854 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17855 break;
17856 case OMPC_dyn_groupprivate: {
17857 enum { Modifier1, Modifier2, NumberOfElements };
17858 assert(Argument.size() == NumberOfElements &&
17859 ArgumentLoc.size() == NumberOfElements &&
17860 "Modifiers for dyn_groupprivate clause and their locations are "
17861 "expected.");
17863 static_cast<OpenMPDynGroupprivateClauseModifier>(Argument[Modifier1]),
17865 Argument[Modifier2]),
17866 Expr, StartLoc, LParenLoc, ArgumentLoc[Modifier1],
17867 ArgumentLoc[Modifier2], EndLoc);
17868 break;
17869 }
17870 case OMPC_num_threads:
17871 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17872 "Modifier for num_threads clause and its location are expected.");
17874 static_cast<OpenMPNumThreadsClauseModifier>(Argument.back()), Expr,
17875 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17876 break;
17877 case OMPC_final:
17878 case OMPC_safelen:
17879 case OMPC_simdlen:
17880 case OMPC_sizes:
17881 case OMPC_allocator:
17882 case OMPC_collapse:
17883 case OMPC_proc_bind:
17884 case OMPC_private:
17885 case OMPC_firstprivate:
17886 case OMPC_lastprivate:
17887 case OMPC_shared:
17888 case OMPC_reduction:
17889 case OMPC_task_reduction:
17890 case OMPC_in_reduction:
17891 case OMPC_linear:
17892 case OMPC_aligned:
17893 case OMPC_copyin:
17894 case OMPC_copyprivate:
17895 case OMPC_ordered:
17896 case OMPC_nowait:
17897 case OMPC_untied:
17898 case OMPC_mergeable:
17899 case OMPC_threadprivate:
17900 case OMPC_groupprivate:
17901 case OMPC_allocate:
17902 case OMPC_flush:
17903 case OMPC_depobj:
17904 case OMPC_read:
17905 case OMPC_write:
17906 case OMPC_update:
17907 case OMPC_capture:
17908 case OMPC_compare:
17909 case OMPC_seq_cst:
17910 case OMPC_acq_rel:
17911 case OMPC_acquire:
17912 case OMPC_release:
17913 case OMPC_relaxed:
17914 case OMPC_depend:
17915 case OMPC_threads:
17916 case OMPC_simd:
17917 case OMPC_map:
17918 case OMPC_num_teams:
17919 case OMPC_thread_limit:
17920 case OMPC_priority:
17921 case OMPC_nogroup:
17922 case OMPC_hint:
17923 case OMPC_unknown:
17924 case OMPC_uniform:
17925 case OMPC_to:
17926 case OMPC_from:
17927 case OMPC_use_device_ptr:
17928 case OMPC_use_device_addr:
17929 case OMPC_is_device_ptr:
17930 case OMPC_has_device_addr:
17931 case OMPC_unified_address:
17932 case OMPC_unified_shared_memory:
17933 case OMPC_reverse_offload:
17934 case OMPC_dynamic_allocators:
17935 case OMPC_atomic_default_mem_order:
17936 case OMPC_self_maps:
17937 case OMPC_device_type:
17938 case OMPC_match:
17939 case OMPC_nontemporal:
17940 case OMPC_at:
17941 case OMPC_severity:
17942 case OMPC_message:
17943 case OMPC_destroy:
17944 case OMPC_novariants:
17945 case OMPC_nocontext:
17946 case OMPC_detach:
17947 case OMPC_inclusive:
17948 case OMPC_exclusive:
17949 case OMPC_uses_allocators:
17950 case OMPC_affinity:
17951 case OMPC_when:
17952 case OMPC_bind:
17953 default:
17954 llvm_unreachable("Clause is not allowed.");
17955 }
17956 return Res;
17957}
17958
17961 SourceLocation M1Loc, SourceLocation M2Loc) {
17962 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
17963 SmallVector<unsigned, 2> Excluded;
17965 Excluded.push_back(M2);
17966 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
17967 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
17968 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
17969 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
17970 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
17971 << getListOfPossibleValues(OMPC_schedule,
17972 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
17974 Excluded)
17975 << getOpenMPClauseNameForDiag(OMPC_schedule);
17976 return true;
17977 }
17978 return false;
17979}
17980
17983 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
17984 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
17985 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
17986 if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) ||
17987 checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc))
17988 return nullptr;
17989 // OpenMP, 2.7.1, Loop Construct, Restrictions
17990 // Either the monotonic modifier or the nonmonotonic modifier can be specified
17991 // but not both.
17992 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
17993 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
17994 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
17995 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
17996 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
17997 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
17998 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
17999 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
18000 return nullptr;
18001 }
18002 if (Kind == OMPC_SCHEDULE_unknown) {
18003 std::string Values;
18004 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
18005 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
18006 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
18008 Exclude);
18009 } else {
18010 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
18011 /*Last=*/OMPC_SCHEDULE_unknown);
18012 }
18013 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
18014 << Values << getOpenMPClauseNameForDiag(OMPC_schedule);
18015 return nullptr;
18016 }
18017 // OpenMP, 2.7.1, Loop Construct, Restrictions
18018 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
18019 // schedule(guided).
18020 // OpenMP 5.0 does not have this restriction.
18021 if (getLangOpts().OpenMP < 50 &&
18022 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
18023 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
18024 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
18025 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
18026 diag::err_omp_schedule_nonmonotonic_static);
18027 return nullptr;
18028 }
18029 Expr *ValExpr = ChunkSize;
18030 Stmt *HelperValStmt = nullptr;
18031 if (ChunkSize) {
18032 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
18033 !ChunkSize->isInstantiationDependent() &&
18034 !ChunkSize->containsUnexpandedParameterPack()) {
18035 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
18036 ExprResult Val =
18037 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
18038 if (Val.isInvalid())
18039 return nullptr;
18040
18041 ValExpr = Val.get();
18042
18043 // OpenMP [2.7.1, Restrictions]
18044 // chunk_size must be a loop invariant integer expression with a positive
18045 // value.
18046 if (std::optional<llvm::APSInt> Result =
18048 if (Result->isSigned() && !Result->isStrictlyPositive()) {
18049 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
18050 << "schedule" << 1 << ChunkSize->getSourceRange();
18051 return nullptr;
18052 }
18054 DSAStack->getCurrentDirective(), OMPC_schedule,
18055 getLangOpts().OpenMP) != OMPD_unknown &&
18056 !SemaRef.CurContext->isDependentContext()) {
18057 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18058 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18059 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18060 HelperValStmt = buildPreInits(getASTContext(), Captures);
18061 }
18062 }
18063 }
18064
18065 return new (getASTContext())
18066 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
18067 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
18068}
18069
18071 SourceLocation StartLoc,
18072 SourceLocation EndLoc) {
18073 OMPClause *Res = nullptr;
18074 switch (Kind) {
18075 case OMPC_ordered:
18076 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
18077 break;
18078 case OMPC_nowait:
18079 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc,
18080 /*LParenLoc=*/SourceLocation(),
18081 /*Condition=*/nullptr);
18082 break;
18083 case OMPC_untied:
18084 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
18085 break;
18086 case OMPC_mergeable:
18087 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
18088 break;
18089 case OMPC_read:
18090 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
18091 break;
18092 case OMPC_write:
18093 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
18094 break;
18095 case OMPC_update:
18096 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
18097 break;
18098 case OMPC_capture:
18099 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
18100 break;
18101 case OMPC_compare:
18102 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
18103 break;
18104 case OMPC_fail:
18105 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
18106 break;
18107 case OMPC_seq_cst:
18108 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
18109 break;
18110 case OMPC_acq_rel:
18111 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
18112 break;
18113 case OMPC_acquire:
18114 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
18115 break;
18116 case OMPC_release:
18117 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
18118 break;
18119 case OMPC_relaxed:
18120 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
18121 break;
18122 case OMPC_weak:
18123 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
18124 break;
18125 case OMPC_threads:
18126 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
18127 break;
18128 case OMPC_simd:
18129 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
18130 break;
18131 case OMPC_nogroup:
18132 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
18133 break;
18134 case OMPC_unified_address:
18135 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
18136 break;
18137 case OMPC_unified_shared_memory:
18138 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
18139 break;
18140 case OMPC_reverse_offload:
18141 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
18142 break;
18143 case OMPC_dynamic_allocators:
18144 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
18145 break;
18146 case OMPC_self_maps:
18147 Res = ActOnOpenMPSelfMapsClause(StartLoc, EndLoc);
18148 break;
18149 case OMPC_destroy:
18150 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
18151 /*LParenLoc=*/SourceLocation(),
18152 /*VarLoc=*/SourceLocation(), EndLoc);
18153 break;
18154 case OMPC_full:
18155 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
18156 break;
18157 case OMPC_partial:
18158 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
18159 break;
18160 case OMPC_ompx_bare:
18161 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
18162 break;
18163 case OMPC_if:
18164 case OMPC_final:
18165 case OMPC_num_threads:
18166 case OMPC_safelen:
18167 case OMPC_simdlen:
18168 case OMPC_sizes:
18169 case OMPC_allocator:
18170 case OMPC_collapse:
18171 case OMPC_schedule:
18172 case OMPC_private:
18173 case OMPC_firstprivate:
18174 case OMPC_lastprivate:
18175 case OMPC_shared:
18176 case OMPC_reduction:
18177 case OMPC_task_reduction:
18178 case OMPC_in_reduction:
18179 case OMPC_linear:
18180 case OMPC_aligned:
18181 case OMPC_copyin:
18182 case OMPC_copyprivate:
18183 case OMPC_default:
18184 case OMPC_proc_bind:
18185 case OMPC_threadprivate:
18186 case OMPC_groupprivate:
18187 case OMPC_allocate:
18188 case OMPC_flush:
18189 case OMPC_depobj:
18190 case OMPC_depend:
18191 case OMPC_device:
18192 case OMPC_map:
18193 case OMPC_num_teams:
18194 case OMPC_thread_limit:
18195 case OMPC_priority:
18196 case OMPC_grainsize:
18197 case OMPC_num_tasks:
18198 case OMPC_hint:
18199 case OMPC_dist_schedule:
18200 case OMPC_defaultmap:
18201 case OMPC_unknown:
18202 case OMPC_uniform:
18203 case OMPC_to:
18204 case OMPC_from:
18205 case OMPC_use_device_ptr:
18206 case OMPC_use_device_addr:
18207 case OMPC_is_device_ptr:
18208 case OMPC_has_device_addr:
18209 case OMPC_atomic_default_mem_order:
18210 case OMPC_device_type:
18211 case OMPC_match:
18212 case OMPC_nontemporal:
18213 case OMPC_order:
18214 case OMPC_at:
18215 case OMPC_severity:
18216 case OMPC_message:
18217 case OMPC_novariants:
18218 case OMPC_nocontext:
18219 case OMPC_detach:
18220 case OMPC_inclusive:
18221 case OMPC_exclusive:
18222 case OMPC_uses_allocators:
18223 case OMPC_affinity:
18224 case OMPC_when:
18225 case OMPC_ompx_dyn_cgroup_mem:
18226 case OMPC_dyn_groupprivate:
18227 default:
18228 llvm_unreachable("Clause is not allowed.");
18229 }
18230 return Res;
18231}
18232
18234 SourceLocation EndLoc,
18235 SourceLocation LParenLoc,
18236 Expr *Condition) {
18237 Expr *ValExpr = Condition;
18238 if (Condition && LParenLoc.isValid()) {
18239 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18240 !Condition->isInstantiationDependent() &&
18241 !Condition->containsUnexpandedParameterPack()) {
18242 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
18243 if (Val.isInvalid())
18244 return nullptr;
18245
18246 ValExpr = Val.get();
18247 }
18248 }
18249 DSAStack->setNowaitRegion();
18250 return new (getASTContext())
18251 OMPNowaitClause(ValExpr, StartLoc, LParenLoc, EndLoc);
18252}
18253
18255 SourceLocation EndLoc) {
18256 DSAStack->setUntiedRegion();
18257 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
18258}
18259
18261 SourceLocation EndLoc) {
18262 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
18263}
18264
18266 SourceLocation EndLoc) {
18267 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
18268}
18269
18271 SourceLocation EndLoc) {
18272 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
18273}
18274
18276 SourceLocation EndLoc) {
18277 return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc);
18278}
18279
18281 SourceLocation EndLoc) {
18282 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
18283}
18284
18286 SourceLocation EndLoc) {
18287 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
18288}
18289
18291 SourceLocation EndLoc) {
18292 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
18293}
18294
18296 SourceLocation KindLoc,
18297 SourceLocation StartLoc,
18298 SourceLocation LParenLoc,
18299 SourceLocation EndLoc) {
18300
18302 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
18303 return nullptr;
18304 }
18305 return new (getASTContext())
18306 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
18307}
18308
18310 SourceLocation EndLoc) {
18311 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
18312}
18313
18315 SourceLocation EndLoc) {
18316 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
18317}
18318
18320 SourceLocation EndLoc) {
18321 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
18322}
18323
18325 SourceLocation EndLoc) {
18326 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
18327}
18328
18330 SourceLocation EndLoc) {
18331 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
18332}
18333
18335 SourceLocation EndLoc) {
18336 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
18337}
18338
18340 SourceLocation EndLoc) {
18341 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
18342}
18343
18345 SourceLocation EndLoc) {
18346 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
18347}
18348
18350 SourceLocation EndLoc) {
18351 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
18352}
18353
18355 SourceLocation EndLoc) {
18356 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
18357}
18358
18359OMPClause *
18364
18366 SourceLocation EndLoc) {
18367 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
18368}
18369
18370OMPClause *
18372 SourceLocation EndLoc) {
18373 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
18374}
18375
18377 SourceLocation EndLoc) {
18378 return new (getASTContext()) OMPSelfMapsClause(StartLoc, EndLoc);
18379}
18380
18383 SourceLocation StartLoc,
18384 SourceLocation EndLoc) {
18385
18386 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18387 // At least one action-clause must appear on a directive.
18388 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
18389 unsigned OMPVersion = getLangOpts().OpenMP;
18390 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
18391 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
18392 << Expected << getOpenMPDirectiveName(OMPD_interop, OMPVersion);
18393 return StmtError();
18394 }
18395
18396 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18397 // A depend clause can only appear on the directive if a targetsync
18398 // interop-type is present or the interop-var was initialized with
18399 // the targetsync interop-type.
18400
18401 // If there is any 'init' clause diagnose if there is no 'init' clause with
18402 // interop-type of 'targetsync'. Cases involving other directives cannot be
18403 // diagnosed.
18404 const OMPDependClause *DependClause = nullptr;
18405 bool HasInitClause = false;
18406 bool IsTargetSync = false;
18407 for (const OMPClause *C : Clauses) {
18408 if (IsTargetSync)
18409 break;
18410 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
18411 HasInitClause = true;
18412 if (InitClause->getIsTargetSync())
18413 IsTargetSync = true;
18414 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
18415 DependClause = DC;
18416 }
18417 }
18418 if (DependClause && HasInitClause && !IsTargetSync) {
18419 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
18420 return StmtError();
18421 }
18422
18423 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18424 // Each interop-var may be specified for at most one action-clause of each
18425 // interop construct.
18427 for (OMPClause *C : Clauses) {
18428 OpenMPClauseKind ClauseKind = C->getClauseKind();
18429 std::pair<ValueDecl *, bool> DeclResult;
18430 SourceLocation ELoc;
18431 SourceRange ERange;
18432
18433 if (ClauseKind == OMPC_init) {
18434 auto *E = cast<OMPInitClause>(C)->getInteropVar();
18435 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18436 } else if (ClauseKind == OMPC_use) {
18437 auto *E = cast<OMPUseClause>(C)->getInteropVar();
18438 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18439 } else if (ClauseKind == OMPC_destroy) {
18440 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
18441 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18442 }
18443
18444 if (DeclResult.first) {
18445 if (!InteropVars.insert(DeclResult.first).second) {
18446 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
18447 << DeclResult.first;
18448 return StmtError();
18449 }
18450 }
18451 }
18452
18453 return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc,
18454 Clauses);
18455}
18456
18457static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
18458 SourceLocation VarLoc,
18459 OpenMPClauseKind Kind) {
18460 SourceLocation ELoc;
18461 SourceRange ERange;
18462 Expr *RefExpr = InteropVarExpr;
18463 auto Res = getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
18464 /*AllowArraySection=*/false,
18465 /*AllowAssumedSizeArray=*/false,
18466 /*DiagType=*/"omp_interop_t");
18467
18468 if (Res.second) {
18469 // It will be analyzed later.
18470 return true;
18471 }
18472
18473 if (!Res.first)
18474 return false;
18475
18476 // Interop variable should be of type omp_interop_t.
18477 bool HasError = false;
18478 QualType InteropType;
18479 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
18480 VarLoc, Sema::LookupOrdinaryName);
18481 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
18482 NamedDecl *ND = Result.getFoundDecl();
18483 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
18484 InteropType = QualType(TD->getTypeForDecl(), 0);
18485 } else {
18486 HasError = true;
18487 }
18488 } else {
18489 HasError = true;
18490 }
18491
18492 if (HasError) {
18493 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
18494 << "omp_interop_t";
18495 return false;
18496 }
18497
18498 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
18499 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
18500 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
18501 return false;
18502 }
18503
18504 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18505 // The interop-var passed to init or destroy must be non-const.
18506 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
18507 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
18508 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
18509 << /*non-const*/ 1;
18510 return false;
18511 }
18512 return true;
18513}
18514
18516 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
18517 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
18518
18519 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init))
18520 return nullptr;
18521
18522 // Check prefer_type values. These foreign-runtime-id values are either
18523 // string literals or constant integral expressions.
18524 for (const Expr *E : InteropInfo.PreferTypes) {
18525 if (E->isValueDependent() || E->isTypeDependent() ||
18527 continue;
18529 continue;
18530 if (isa<StringLiteral>(E))
18531 continue;
18532 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
18533 return nullptr;
18534 }
18535
18536 return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo,
18537 StartLoc, LParenLoc, VarLoc, EndLoc);
18538}
18539
18541 SourceLocation StartLoc,
18542 SourceLocation LParenLoc,
18543 SourceLocation VarLoc,
18544 SourceLocation EndLoc) {
18545
18546 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use))
18547 return nullptr;
18548
18549 return new (getASTContext())
18550 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18551}
18552
18554 SourceLocation StartLoc,
18555 SourceLocation LParenLoc,
18556 SourceLocation VarLoc,
18557 SourceLocation EndLoc) {
18558 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
18559 DSAStack->getCurrentDirective() == OMPD_depobj) {
18560 unsigned OMPVersion = getLangOpts().OpenMP;
18561 Diag(StartLoc, diag::err_omp_expected_clause_argument)
18562 << getOpenMPClauseNameForDiag(OMPC_destroy)
18563 << getOpenMPDirectiveName(OMPD_depobj, OMPVersion);
18564 return nullptr;
18565 }
18566 if (InteropVar &&
18567 !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy))
18568 return nullptr;
18569
18570 return new (getASTContext())
18571 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18572}
18573
18575 SourceLocation StartLoc,
18576 SourceLocation LParenLoc,
18577 SourceLocation EndLoc) {
18578 Expr *ValExpr = Condition;
18579 Stmt *HelperValStmt = nullptr;
18580 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18581 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18582 !Condition->isInstantiationDependent() &&
18583 !Condition->containsUnexpandedParameterPack()) {
18584 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
18585 if (Val.isInvalid())
18586 return nullptr;
18587
18588 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
18589
18590 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18591 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
18592 getLangOpts().OpenMP);
18593 if (CaptureRegion != OMPD_unknown &&
18594 !SemaRef.CurContext->isDependentContext()) {
18595 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18596 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18597 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18598 HelperValStmt = buildPreInits(getASTContext(), Captures);
18599 }
18600 }
18601
18602 return new (getASTContext()) OMPNovariantsClause(
18603 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18604}
18605
18607 SourceLocation StartLoc,
18608 SourceLocation LParenLoc,
18609 SourceLocation EndLoc) {
18610 Expr *ValExpr = Condition;
18611 Stmt *HelperValStmt = nullptr;
18612 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18613 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18614 !Condition->isInstantiationDependent() &&
18615 !Condition->containsUnexpandedParameterPack()) {
18616 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
18617 if (Val.isInvalid())
18618 return nullptr;
18619
18620 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
18621
18622 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18623 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext,
18624 getLangOpts().OpenMP);
18625 if (CaptureRegion != OMPD_unknown &&
18626 !SemaRef.CurContext->isDependentContext()) {
18627 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18628 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18629 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18630 HelperValStmt = buildPreInits(getASTContext(), Captures);
18631 }
18632 }
18633
18634 return new (getASTContext()) OMPNocontextClause(
18635 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18636}
18637
18639 SourceLocation StartLoc,
18640 SourceLocation LParenLoc,
18641 SourceLocation EndLoc) {
18642 Expr *ValExpr = ThreadID;
18643 Stmt *HelperValStmt = nullptr;
18644
18645 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18646 OpenMPDirectiveKind CaptureRegion =
18647 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP);
18648 if (CaptureRegion != OMPD_unknown &&
18649 !SemaRef.CurContext->isDependentContext()) {
18650 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18651 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18652 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18653 HelperValStmt = buildPreInits(getASTContext(), Captures);
18654 }
18655
18656 return new (getASTContext()) OMPFilterClause(
18657 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18658}
18659
18661 ArrayRef<Expr *> VarList,
18662 const OMPVarListLocTy &Locs,
18664 SourceLocation StartLoc = Locs.StartLoc;
18665 SourceLocation LParenLoc = Locs.LParenLoc;
18666 SourceLocation EndLoc = Locs.EndLoc;
18667 OMPClause *Res = nullptr;
18668 int ExtraModifier = Data.ExtraModifier;
18669 int OriginalSharingModifier = Data.OriginalSharingModifier;
18670 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
18671 SourceLocation ColonLoc = Data.ColonLoc;
18672 switch (Kind) {
18673 case OMPC_private:
18674 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18675 break;
18676 case OMPC_firstprivate:
18677 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18678 break;
18679 case OMPC_lastprivate:
18680 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
18681 "Unexpected lastprivate modifier.");
18683 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
18684 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
18685 break;
18686 case OMPC_shared:
18687 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
18688 break;
18689 case OMPC_reduction:
18690 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
18691 "Unexpected lastprivate modifier.");
18693 VarList,
18695 ExtraModifier, OriginalSharingModifier),
18696 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
18697 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18698 break;
18699 case OMPC_task_reduction:
18701 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18702 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18703 break;
18704 case OMPC_in_reduction:
18706 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18707 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18708 break;
18709 case OMPC_linear:
18710 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
18711 "Unexpected linear modifier.");
18713 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
18714 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
18715 ColonLoc, Data.StepModifierLoc, EndLoc);
18716 break;
18717 case OMPC_aligned:
18718 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
18719 LParenLoc, ColonLoc, EndLoc);
18720 break;
18721 case OMPC_copyin:
18722 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
18723 break;
18724 case OMPC_copyprivate:
18725 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18726 break;
18727 case OMPC_flush:
18728 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
18729 break;
18730 case OMPC_depend:
18731 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
18732 "Unexpected depend modifier.");
18734 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
18735 ColonLoc, Data.OmpAllMemoryLoc},
18736 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
18737 break;
18738 case OMPC_map:
18739 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
18740 "Unexpected map modifier.");
18742 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
18743 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
18744 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
18745 ExtraModifierLoc, ColonLoc, VarList, Locs);
18746 break;
18747 case OMPC_to:
18748 Res = ActOnOpenMPToClause(
18749 Data.MotionModifiers, Data.MotionModifiersLoc, Data.IteratorExpr,
18750 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, ColonLoc,
18751 VarList, Locs);
18752 break;
18753 case OMPC_from:
18755 Data.MotionModifiers, Data.MotionModifiersLoc, Data.IteratorExpr,
18756 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, ColonLoc,
18757 VarList, Locs);
18758 break;
18759 case OMPC_use_device_ptr:
18760 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
18761 break;
18762 case OMPC_use_device_addr:
18763 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
18764 break;
18765 case OMPC_is_device_ptr:
18766 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
18767 break;
18768 case OMPC_has_device_addr:
18769 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
18770 break;
18771 case OMPC_allocate: {
18774 SourceLocation Modifier1Loc, Modifier2Loc;
18775 if (!Data.AllocClauseModifiers.empty()) {
18776 assert(Data.AllocClauseModifiers.size() <= 2 &&
18777 "More allocate modifiers than expected");
18778 Modifier1 = Data.AllocClauseModifiers[0];
18779 Modifier1Loc = Data.AllocClauseModifiersLoc[0];
18780 if (Data.AllocClauseModifiers.size() == 2) {
18781 Modifier2 = Data.AllocClauseModifiers[1];
18782 Modifier2Loc = Data.AllocClauseModifiersLoc[1];
18783 }
18784 }
18786 Data.DepModOrTailExpr, Data.AllocateAlignment, Modifier1, Modifier1Loc,
18787 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
18788 EndLoc);
18789 break;
18790 }
18791 case OMPC_nontemporal:
18792 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
18793 break;
18794 case OMPC_inclusive:
18795 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18796 break;
18797 case OMPC_exclusive:
18798 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18799 break;
18800 case OMPC_affinity:
18801 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
18802 Data.DepModOrTailExpr, VarList);
18803 break;
18804 case OMPC_doacross:
18806 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
18807 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
18808 break;
18809 case OMPC_num_teams:
18810 Res = ActOnOpenMPNumTeamsClause(VarList, StartLoc, LParenLoc, EndLoc);
18811 break;
18812 case OMPC_thread_limit:
18813 Res = ActOnOpenMPThreadLimitClause(VarList, StartLoc, LParenLoc, EndLoc);
18814 break;
18815 case OMPC_if:
18816 case OMPC_depobj:
18817 case OMPC_final:
18818 case OMPC_num_threads:
18819 case OMPC_safelen:
18820 case OMPC_simdlen:
18821 case OMPC_sizes:
18822 case OMPC_allocator:
18823 case OMPC_collapse:
18824 case OMPC_default:
18825 case OMPC_proc_bind:
18826 case OMPC_schedule:
18827 case OMPC_ordered:
18828 case OMPC_nowait:
18829 case OMPC_untied:
18830 case OMPC_mergeable:
18831 case OMPC_threadprivate:
18832 case OMPC_groupprivate:
18833 case OMPC_read:
18834 case OMPC_write:
18835 case OMPC_update:
18836 case OMPC_capture:
18837 case OMPC_compare:
18838 case OMPC_seq_cst:
18839 case OMPC_acq_rel:
18840 case OMPC_acquire:
18841 case OMPC_release:
18842 case OMPC_relaxed:
18843 case OMPC_device:
18844 case OMPC_threads:
18845 case OMPC_simd:
18846 case OMPC_priority:
18847 case OMPC_grainsize:
18848 case OMPC_nogroup:
18849 case OMPC_num_tasks:
18850 case OMPC_hint:
18851 case OMPC_dist_schedule:
18852 case OMPC_defaultmap:
18853 case OMPC_unknown:
18854 case OMPC_uniform:
18855 case OMPC_unified_address:
18856 case OMPC_unified_shared_memory:
18857 case OMPC_reverse_offload:
18858 case OMPC_dynamic_allocators:
18859 case OMPC_atomic_default_mem_order:
18860 case OMPC_self_maps:
18861 case OMPC_device_type:
18862 case OMPC_match:
18863 case OMPC_order:
18864 case OMPC_at:
18865 case OMPC_severity:
18866 case OMPC_message:
18867 case OMPC_destroy:
18868 case OMPC_novariants:
18869 case OMPC_nocontext:
18870 case OMPC_detach:
18871 case OMPC_uses_allocators:
18872 case OMPC_when:
18873 case OMPC_bind:
18874 default:
18875 llvm_unreachable("Clause is not allowed.");
18876 }
18877 return Res;
18878}
18879
18881 ExprObjectKind OK,
18882 SourceLocation Loc) {
18883 ExprResult Res = SemaRef.BuildDeclRefExpr(
18884 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
18885 if (!Res.isUsable())
18886 return ExprError();
18887 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
18888 Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
18889 if (!Res.isUsable())
18890 return ExprError();
18891 }
18892 if (VK != VK_LValue && Res.get()->isGLValue()) {
18893 Res = SemaRef.DefaultLvalueConversion(Res.get());
18894 if (!Res.isUsable())
18895 return ExprError();
18896 }
18897 return Res;
18898}
18899
18901 SourceLocation StartLoc,
18902 SourceLocation LParenLoc,
18903 SourceLocation EndLoc) {
18905 SmallVector<Expr *, 8> PrivateCopies;
18906 unsigned OMPVersion = getLangOpts().OpenMP;
18907 bool IsImplicitClause =
18908 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18909 for (Expr *RefExpr : VarList) {
18910 assert(RefExpr && "NULL expr in OpenMP private clause.");
18911 SourceLocation ELoc;
18912 SourceRange ERange;
18913 Expr *SimpleRefExpr = RefExpr;
18914 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
18915 if (Res.second) {
18916 // It will be analyzed later.
18917 Vars.push_back(RefExpr);
18918 PrivateCopies.push_back(nullptr);
18919 }
18920 ValueDecl *D = Res.first;
18921 if (!D)
18922 continue;
18923
18924 QualType Type = D->getType();
18925 auto *VD = dyn_cast<VarDecl>(D);
18926
18927 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18928 // A variable that appears in a private clause must not have an incomplete
18929 // type or a reference type.
18930 if (SemaRef.RequireCompleteType(ELoc, Type,
18931 diag::err_omp_private_incomplete_type))
18932 continue;
18933 Type = Type.getNonReferenceType();
18934
18935 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18936 // A variable that is privatized must not have a const-qualified type
18937 // unless it is of class type with a mutable member. This restriction does
18938 // not apply to the firstprivate clause.
18939 //
18940 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
18941 // A variable that appears in a private clause must not have a
18942 // const-qualified type unless it is of class type with a mutable member.
18943 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc))
18944 continue;
18945
18946 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18947 // in a Construct]
18948 // Variables with the predetermined data-sharing attributes may not be
18949 // listed in data-sharing attributes clauses, except for the cases
18950 // listed below. For these exceptions only, listing a predetermined
18951 // variable in a data-sharing attribute clause is allowed and overrides
18952 // the variable's predetermined data-sharing attributes.
18953 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18954 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
18955 Diag(ELoc, diag::err_omp_wrong_dsa)
18956 << getOpenMPClauseNameForDiag(DVar.CKind)
18957 << getOpenMPClauseNameForDiag(OMPC_private);
18959 continue;
18960 }
18961
18962 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18963 // Variably modified types are not supported for tasks.
18965 isOpenMPTaskingDirective(CurrDir)) {
18966 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18967 << getOpenMPClauseNameForDiag(OMPC_private) << Type
18968 << getOpenMPDirectiveName(CurrDir, OMPVersion);
18969 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
18971 Diag(D->getLocation(),
18972 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18973 << D;
18974 continue;
18975 }
18976
18977 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18978 // A list item cannot appear in both a map clause and a data-sharing
18979 // attribute clause on the same construct
18980 //
18981 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18982 // A list item cannot appear in both a map clause and a data-sharing
18983 // attribute clause on the same construct unless the construct is a
18984 // combined construct.
18985 if ((getLangOpts().OpenMP <= 45 &&
18987 CurrDir == OMPD_target) {
18988 OpenMPClauseKind ConflictKind;
18989 if (DSAStack->checkMappableExprComponentListsForDecl(
18990 VD, /*CurrentRegionOnly=*/true,
18992 OpenMPClauseKind WhereFoundClauseKind) -> bool {
18993 ConflictKind = WhereFoundClauseKind;
18994 return true;
18995 })) {
18996 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18997 << getOpenMPClauseNameForDiag(OMPC_private)
18998 << getOpenMPClauseNameForDiag(ConflictKind)
18999 << getOpenMPDirectiveName(CurrDir, OMPVersion);
19001 continue;
19002 }
19003 }
19004
19005 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
19006 // A variable of class type (or array thereof) that appears in a private
19007 // clause requires an accessible, unambiguous default constructor for the
19008 // class type.
19009 // Generate helper private variable and initialize it with the default
19010 // value. The address of the original variable is replaced by the address of
19011 // the new private variable in CodeGen. This new variable is not added to
19012 // IdResolver, so the code in the OpenMP region uses original variable for
19013 // proper diagnostics.
19014 Type = Type.getUnqualifiedType();
19015 VarDecl *VDPrivate =
19016 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
19017 D->hasAttrs() ? &D->getAttrs() : nullptr,
19018 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19019 SemaRef.ActOnUninitializedDecl(VDPrivate);
19020 if (VDPrivate->isInvalidDecl())
19021 continue;
19022 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
19023 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
19024
19025 DeclRefExpr *Ref = nullptr;
19026 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19027 auto *FD = dyn_cast<FieldDecl>(D);
19028 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
19029 if (VD)
19031 RefExpr->getExprLoc());
19032 else
19033 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19034 }
19035 if (!IsImplicitClause)
19036 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
19037 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19038 ? RefExpr->IgnoreParens()
19039 : Ref);
19040 PrivateCopies.push_back(VDPrivateRefExpr);
19041 }
19042
19043 if (Vars.empty())
19044 return nullptr;
19045
19046 return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19047 Vars, PrivateCopies);
19048}
19049
19051 SourceLocation StartLoc,
19052 SourceLocation LParenLoc,
19053 SourceLocation EndLoc) {
19055 SmallVector<Expr *, 8> PrivateCopies;
19057 SmallVector<Decl *, 4> ExprCaptures;
19058 bool IsImplicitClause =
19059 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
19060 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
19061 unsigned OMPVersion = getLangOpts().OpenMP;
19062
19063 for (Expr *RefExpr : VarList) {
19064 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
19065 SourceLocation ELoc;
19066 SourceRange ERange;
19067 Expr *SimpleRefExpr = RefExpr;
19068 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19069 if (Res.second) {
19070 // It will be analyzed later.
19071 Vars.push_back(RefExpr);
19072 PrivateCopies.push_back(nullptr);
19073 Inits.push_back(nullptr);
19074 }
19075 ValueDecl *D = Res.first;
19076 if (!D)
19077 continue;
19078
19079 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
19080 QualType Type = D->getType();
19081 auto *VD = dyn_cast<VarDecl>(D);
19082
19083 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19084 // A variable that appears in a private clause must not have an incomplete
19085 // type or a reference type.
19086 if (SemaRef.RequireCompleteType(ELoc, Type,
19087 diag::err_omp_firstprivate_incomplete_type))
19088 continue;
19089 Type = Type.getNonReferenceType();
19090
19091 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
19092 // A variable of class type (or array thereof) that appears in a private
19093 // clause requires an accessible, unambiguous copy constructor for the
19094 // class type.
19095 QualType ElemType =
19097
19098 // If an implicit firstprivate variable found it was checked already.
19099 DSAStackTy::DSAVarData TopDVar;
19100 if (!IsImplicitClause) {
19101 DSAStackTy::DSAVarData DVar =
19102 DSAStack->getTopDSA(D, /*FromParent=*/false);
19103 TopDVar = DVar;
19104 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19105 bool IsConstant = ElemType.isConstant(getASTContext());
19106 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
19107 // A list item that specifies a given variable may not appear in more
19108 // than one clause on the same directive, except that a variable may be
19109 // specified in both firstprivate and lastprivate clauses.
19110 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
19111 // A list item may appear in a firstprivate or lastprivate clause but not
19112 // both.
19113 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
19114 (isOpenMPDistributeDirective(CurrDir) ||
19115 DVar.CKind != OMPC_lastprivate) &&
19116 DVar.RefExpr) {
19117 Diag(ELoc, diag::err_omp_wrong_dsa)
19118 << getOpenMPClauseNameForDiag(DVar.CKind)
19119 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
19121 continue;
19122 }
19123
19124 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19125 // in a Construct]
19126 // Variables with the predetermined data-sharing attributes may not be
19127 // listed in data-sharing attributes clauses, except for the cases
19128 // listed below. For these exceptions only, listing a predetermined
19129 // variable in a data-sharing attribute clause is allowed and overrides
19130 // the variable's predetermined data-sharing attributes.
19131 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19132 // in a Construct, C/C++, p.2]
19133 // Variables with const-qualified type having no mutable member may be
19134 // listed in a firstprivate clause, even if they are static data members.
19135 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
19136 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
19137 Diag(ELoc, diag::err_omp_wrong_dsa)
19138 << getOpenMPClauseNameForDiag(DVar.CKind)
19139 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
19141 continue;
19142 }
19143
19144 // OpenMP [2.9.3.4, Restrictions, p.2]
19145 // A list item that is private within a parallel region must not appear
19146 // in a firstprivate clause on a worksharing construct if any of the
19147 // worksharing regions arising from the worksharing construct ever bind
19148 // to any of the parallel regions arising from the parallel construct.
19149 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
19150 // A list item that is private within a teams region must not appear in a
19151 // firstprivate clause on a distribute construct if any of the distribute
19152 // regions arising from the distribute construct ever bind to any of the
19153 // teams regions arising from the teams construct.
19154 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
19155 // A list item that appears in a reduction clause of a teams construct
19156 // must not appear in a firstprivate clause on a distribute construct if
19157 // any of the distribute regions arising from the distribute construct
19158 // ever bind to any of the teams regions arising from the teams construct.
19159 if ((isOpenMPWorksharingDirective(CurrDir) ||
19160 isOpenMPDistributeDirective(CurrDir)) &&
19161 !isOpenMPParallelDirective(CurrDir) &&
19162 !isOpenMPTeamsDirective(CurrDir)) {
19163 DVar = DSAStack->getImplicitDSA(D, true);
19164 if (DVar.CKind != OMPC_shared &&
19165 (isOpenMPParallelDirective(DVar.DKind) ||
19166 isOpenMPTeamsDirective(DVar.DKind) ||
19167 DVar.DKind == OMPD_unknown)) {
19168 Diag(ELoc, diag::err_omp_required_access)
19169 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
19170 << getOpenMPClauseNameForDiag(OMPC_shared);
19172 continue;
19173 }
19174 }
19175 // OpenMP [2.9.3.4, Restrictions, p.3]
19176 // A list item that appears in a reduction clause of a parallel construct
19177 // must not appear in a firstprivate clause on a worksharing or task
19178 // construct if any of the worksharing or task regions arising from the
19179 // worksharing or task construct ever bind to any of the parallel regions
19180 // arising from the parallel construct.
19181 // OpenMP [2.9.3.4, Restrictions, p.4]
19182 // A list item that appears in a reduction clause in worksharing
19183 // construct must not appear in a firstprivate clause in a task construct
19184 // encountered during execution of any of the worksharing regions arising
19185 // from the worksharing construct.
19186 if (isOpenMPTaskingDirective(CurrDir)) {
19187 DVar = DSAStack->hasInnermostDSA(
19188 D,
19189 [](OpenMPClauseKind C, bool AppliedToPointee) {
19190 return C == OMPC_reduction && !AppliedToPointee;
19191 },
19192 [](OpenMPDirectiveKind K) {
19193 return isOpenMPParallelDirective(K) ||
19196 },
19197 /*FromParent=*/true);
19198 if (DVar.CKind == OMPC_reduction &&
19199 (isOpenMPParallelDirective(DVar.DKind) ||
19200 isOpenMPWorksharingDirective(DVar.DKind) ||
19201 isOpenMPTeamsDirective(DVar.DKind))) {
19202 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
19203 << getOpenMPDirectiveName(DVar.DKind, OMPVersion);
19205 continue;
19206 }
19207 }
19208
19209 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
19210 // A list item cannot appear in both a map clause and a data-sharing
19211 // attribute clause on the same construct
19212 //
19213 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
19214 // A list item cannot appear in both a map clause and a data-sharing
19215 // attribute clause on the same construct unless the construct is a
19216 // combined construct.
19217 if ((getLangOpts().OpenMP <= 45 &&
19219 CurrDir == OMPD_target) {
19220 OpenMPClauseKind ConflictKind;
19221 if (DSAStack->checkMappableExprComponentListsForDecl(
19222 VD, /*CurrentRegionOnly=*/true,
19223 [&ConflictKind](
19225 OpenMPClauseKind WhereFoundClauseKind) {
19226 ConflictKind = WhereFoundClauseKind;
19227 return true;
19228 })) {
19229 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
19230 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
19231 << getOpenMPClauseNameForDiag(ConflictKind)
19232 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
19233 OMPVersion);
19235 continue;
19236 }
19237 }
19238 }
19239
19240 // Variably modified types are not supported for tasks.
19242 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
19243 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19244 << getOpenMPClauseNameForDiag(OMPC_firstprivate) << Type
19245 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
19246 OMPVersion);
19247 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19249 Diag(D->getLocation(),
19250 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19251 << D;
19252 continue;
19253 }
19254
19255 Type = Type.getUnqualifiedType();
19256 VarDecl *VDPrivate =
19257 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
19258 D->hasAttrs() ? &D->getAttrs() : nullptr,
19259 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19260 // Generate helper private variable and initialize it with the value of the
19261 // original variable. The address of the original variable is replaced by
19262 // the address of the new private variable in the CodeGen. This new variable
19263 // is not added to IdResolver, so the code in the OpenMP region uses
19264 // original variable for proper diagnostics and variable capturing.
19265 Expr *VDInitRefExpr = nullptr;
19266 // For arrays generate initializer for single element and replace it by the
19267 // original array element in CodeGen.
19268 if (Type->isArrayType()) {
19269 VarDecl *VDInit =
19270 buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName());
19271 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc);
19272 Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get();
19273 ElemType = ElemType.getUnqualifiedType();
19274 VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(),
19275 ElemType, ".firstprivate.temp");
19276 InitializedEntity Entity =
19279
19280 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
19281 ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init);
19282 if (Result.isInvalid())
19283 VDPrivate->setInvalidDecl();
19284 else
19285 VDPrivate->setInit(Result.getAs<Expr>());
19286 // Remove temp variable declaration.
19287 getASTContext().Deallocate(VDInitTemp);
19288 } else {
19289 VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type,
19290 ".firstprivate.temp");
19291 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(),
19292 RefExpr->getExprLoc());
19293 SemaRef.AddInitializerToDecl(
19294 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
19295 /*DirectInit=*/false);
19296 }
19297 if (VDPrivate->isInvalidDecl()) {
19298 if (IsImplicitClause) {
19299 Diag(RefExpr->getExprLoc(),
19300 diag::note_omp_task_predetermined_firstprivate_here);
19301 }
19302 continue;
19303 }
19304 SemaRef.CurContext->addDecl(VDPrivate);
19305 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
19306 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(),
19307 RefExpr->getExprLoc());
19308 DeclRefExpr *Ref = nullptr;
19309 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19310 if (TopDVar.CKind == OMPC_lastprivate) {
19311 Ref = TopDVar.PrivateCopy;
19312 } else {
19313 auto *FD = dyn_cast<FieldDecl>(D);
19314 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
19315 if (VD)
19316 Ref =
19318 RefExpr->getExprLoc());
19319 else
19320 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19321 if (VD || !isOpenMPCapturedDecl(D))
19322 ExprCaptures.push_back(Ref->getDecl());
19323 }
19324 }
19325 if (!IsImplicitClause)
19326 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
19327 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19328 ? RefExpr->IgnoreParens()
19329 : Ref);
19330 PrivateCopies.push_back(VDPrivateRefExpr);
19331 Inits.push_back(VDInitRefExpr);
19332 }
19333
19334 if (Vars.empty())
19335 return nullptr;
19336
19338 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
19339 buildPreInits(getASTContext(), ExprCaptures));
19340}
19341
19344 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
19345 SourceLocation LParenLoc, SourceLocation EndLoc) {
19346 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
19347 assert(ColonLoc.isValid() && "Colon location must be valid.");
19348 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
19349 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
19350 /*Last=*/OMPC_LASTPRIVATE_unknown)
19351 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
19352 return nullptr;
19353 }
19354
19356 SmallVector<Expr *, 8> SrcExprs;
19357 SmallVector<Expr *, 8> DstExprs;
19358 SmallVector<Expr *, 8> AssignmentOps;
19359 SmallVector<Decl *, 4> ExprCaptures;
19360 SmallVector<Expr *, 4> ExprPostUpdates;
19361 for (Expr *RefExpr : VarList) {
19362 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
19363 SourceLocation ELoc;
19364 SourceRange ERange;
19365 Expr *SimpleRefExpr = RefExpr;
19366 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19367 if (Res.second) {
19368 // It will be analyzed later.
19369 Vars.push_back(RefExpr);
19370 SrcExprs.push_back(nullptr);
19371 DstExprs.push_back(nullptr);
19372 AssignmentOps.push_back(nullptr);
19373 }
19374 ValueDecl *D = Res.first;
19375 if (!D)
19376 continue;
19377
19378 QualType Type = D->getType();
19379 auto *VD = dyn_cast<VarDecl>(D);
19380
19381 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
19382 // A variable that appears in a lastprivate clause must not have an
19383 // incomplete type or a reference type.
19384 if (SemaRef.RequireCompleteType(ELoc, Type,
19385 diag::err_omp_lastprivate_incomplete_type))
19386 continue;
19387 Type = Type.getNonReferenceType();
19388
19389 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19390 // A variable that is privatized must not have a const-qualified type
19391 // unless it is of class type with a mutable member. This restriction does
19392 // not apply to the firstprivate clause.
19393 //
19394 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
19395 // A variable that appears in a lastprivate clause must not have a
19396 // const-qualified type unless it is of class type with a mutable member.
19397 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc))
19398 continue;
19399
19400 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
19401 // A list item that appears in a lastprivate clause with the conditional
19402 // modifier must be a scalar variable.
19403 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
19404 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
19405 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19407 Diag(D->getLocation(),
19408 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19409 << D;
19410 continue;
19411 }
19412
19413 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19414 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19415 // in a Construct]
19416 // Variables with the predetermined data-sharing attributes may not be
19417 // listed in data-sharing attributes clauses, except for the cases
19418 // listed below.
19419 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
19420 // A list item may appear in a firstprivate or lastprivate clause but not
19421 // both.
19422 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19423 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
19424 (isOpenMPDistributeDirective(CurrDir) ||
19425 DVar.CKind != OMPC_firstprivate) &&
19426 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
19427 Diag(ELoc, diag::err_omp_wrong_dsa)
19428 << getOpenMPClauseNameForDiag(DVar.CKind)
19429 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
19431 continue;
19432 }
19433
19434 // OpenMP [2.14.3.5, Restrictions, p.2]
19435 // A list item that is private within a parallel region, or that appears in
19436 // the reduction clause of a parallel construct, must not appear in a
19437 // lastprivate clause on a worksharing construct if any of the corresponding
19438 // worksharing regions ever binds to any of the corresponding parallel
19439 // regions.
19440 DSAStackTy::DSAVarData TopDVar = DVar;
19441 if (isOpenMPWorksharingDirective(CurrDir) &&
19442 !isOpenMPParallelDirective(CurrDir) &&
19443 !isOpenMPTeamsDirective(CurrDir)) {
19444 DVar = DSAStack->getImplicitDSA(D, true);
19445 if (DVar.CKind != OMPC_shared) {
19446 Diag(ELoc, diag::err_omp_required_access)
19447 << getOpenMPClauseNameForDiag(OMPC_lastprivate)
19448 << getOpenMPClauseNameForDiag(OMPC_shared);
19450 continue;
19451 }
19452 }
19453
19454 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
19455 // A variable of class type (or array thereof) that appears in a
19456 // lastprivate clause requires an accessible, unambiguous default
19457 // constructor for the class type, unless the list item is also specified
19458 // in a firstprivate clause.
19459 // A variable of class type (or array thereof) that appears in a
19460 // lastprivate clause requires an accessible, unambiguous copy assignment
19461 // operator for the class type.
19463 VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(),
19464 Type.getUnqualifiedType(), ".lastprivate.src",
19465 D->hasAttrs() ? &D->getAttrs() : nullptr);
19466 DeclRefExpr *PseudoSrcExpr =
19467 buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc);
19468 VarDecl *DstVD =
19469 buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst",
19470 D->hasAttrs() ? &D->getAttrs() : nullptr);
19471 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
19472 // For arrays generate assignment operation for single element and replace
19473 // it by the original array element in CodeGen.
19474 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
19475 PseudoDstExpr, PseudoSrcExpr);
19476 if (AssignmentOp.isInvalid())
19477 continue;
19478 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
19479 /*DiscardedValue=*/false);
19480 if (AssignmentOp.isInvalid())
19481 continue;
19482
19483 DeclRefExpr *Ref = nullptr;
19484 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19485 if (TopDVar.CKind == OMPC_firstprivate) {
19486 Ref = TopDVar.PrivateCopy;
19487 } else {
19488 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19489 if (!isOpenMPCapturedDecl(D))
19490 ExprCaptures.push_back(Ref->getDecl());
19491 }
19492 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
19493 (!isOpenMPCapturedDecl(D) &&
19494 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
19495 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
19496 if (!RefRes.isUsable())
19497 continue;
19498 ExprResult PostUpdateRes =
19499 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
19500 SimpleRefExpr, RefRes.get());
19501 if (!PostUpdateRes.isUsable())
19502 continue;
19503 ExprPostUpdates.push_back(
19504 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
19505 }
19506 }
19507 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
19508 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19509 ? RefExpr->IgnoreParens()
19510 : Ref);
19511 SrcExprs.push_back(PseudoSrcExpr);
19512 DstExprs.push_back(PseudoDstExpr);
19513 AssignmentOps.push_back(AssignmentOp.get());
19514 }
19515
19516 if (Vars.empty())
19517 return nullptr;
19518
19520 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
19521 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
19522 buildPreInits(getASTContext(), ExprCaptures),
19523 buildPostUpdate(SemaRef, ExprPostUpdates));
19524}
19525
19527 SourceLocation StartLoc,
19528 SourceLocation LParenLoc,
19529 SourceLocation EndLoc) {
19531 for (Expr *RefExpr : VarList) {
19532 assert(RefExpr && "NULL expr in OpenMP shared clause.");
19533 SourceLocation ELoc;
19534 SourceRange ERange;
19535 Expr *SimpleRefExpr = RefExpr;
19536 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19537 if (Res.second) {
19538 // It will be analyzed later.
19539 Vars.push_back(RefExpr);
19540 }
19541 ValueDecl *D = Res.first;
19542 if (!D)
19543 continue;
19544
19545 auto *VD = dyn_cast<VarDecl>(D);
19546 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19547 // in a Construct]
19548 // Variables with the predetermined data-sharing attributes may not be
19549 // listed in data-sharing attributes clauses, except for the cases
19550 // listed below. For these exceptions only, listing a predetermined
19551 // variable in a data-sharing attribute clause is allowed and overrides
19552 // the variable's predetermined data-sharing attributes.
19553 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19554 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
19555 DVar.RefExpr) {
19556 Diag(ELoc, diag::err_omp_wrong_dsa)
19557 << getOpenMPClauseNameForDiag(DVar.CKind)
19558 << getOpenMPClauseNameForDiag(OMPC_shared);
19560 continue;
19561 }
19562
19563 DeclRefExpr *Ref = nullptr;
19564 if (!VD && isOpenMPCapturedDecl(D) &&
19565 !SemaRef.CurContext->isDependentContext())
19566 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19567 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
19568 Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext())
19569 ? RefExpr->IgnoreParens()
19570 : Ref);
19571 }
19572
19573 if (Vars.empty())
19574 return nullptr;
19575
19576 return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19577 Vars);
19578}
19579
19580namespace {
19581class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
19582 DSAStackTy *Stack;
19583
19584public:
19585 bool VisitDeclRefExpr(DeclRefExpr *E) {
19586 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
19587 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
19588 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
19589 return false;
19590 if (DVar.CKind != OMPC_unknown)
19591 return true;
19592 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
19593 VD,
19594 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
19595 return isOpenMPPrivate(C) && !AppliedToPointee;
19596 },
19597 [](OpenMPDirectiveKind) { return true; },
19598 /*FromParent=*/true);
19599 return DVarPrivate.CKind != OMPC_unknown;
19600 }
19601 return false;
19602 }
19603 bool VisitStmt(Stmt *S) {
19604 for (Stmt *Child : S->children()) {
19605 if (Child && Visit(Child))
19606 return true;
19607 }
19608 return false;
19609 }
19610 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
19611};
19612} // namespace
19613
19614namespace {
19615// Transform MemberExpression for specified FieldDecl of current class to
19616// DeclRefExpr to specified OMPCapturedExprDecl.
19617class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
19618 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
19619 ValueDecl *Field = nullptr;
19620 DeclRefExpr *CapturedExpr = nullptr;
19621
19622public:
19623 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
19624 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
19625
19626 ExprResult TransformMemberExpr(MemberExpr *E) {
19628 E->getMemberDecl() == Field) {
19629 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
19630 return CapturedExpr;
19631 }
19632 return BaseTransform::TransformMemberExpr(E);
19633 }
19634 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
19635};
19636} // namespace
19637
19638template <typename T, typename U>
19640 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
19641 for (U &Set : Lookups) {
19642 for (auto *D : Set) {
19643 if (T Res = Gen(cast<ValueDecl>(D)))
19644 return Res;
19645 }
19646 }
19647 return T();
19648}
19649
19651 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
19652
19653 for (auto *RD : D->redecls()) {
19654 // Don't bother with extra checks if we already know this one isn't visible.
19655 if (RD == D)
19656 continue;
19657
19658 auto ND = cast<NamedDecl>(RD);
19659 if (LookupResult::isVisible(SemaRef, ND))
19660 return ND;
19661 }
19662
19663 return nullptr;
19664}
19665
19666static void
19668 SourceLocation Loc, QualType Ty,
19670 // Find all of the associated namespaces and classes based on the
19671 // arguments we have.
19672 Sema::AssociatedNamespaceSet AssociatedNamespaces;
19673 Sema::AssociatedClassSet AssociatedClasses;
19674 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
19675 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
19676 AssociatedClasses);
19677
19678 // C++ [basic.lookup.argdep]p3:
19679 // Let X be the lookup set produced by unqualified lookup (3.4.1)
19680 // and let Y be the lookup set produced by argument dependent
19681 // lookup (defined as follows). If X contains [...] then Y is
19682 // empty. Otherwise Y is the set of declarations found in the
19683 // namespaces associated with the argument types as described
19684 // below. The set of declarations found by the lookup of the name
19685 // is the union of X and Y.
19686 //
19687 // Here, we compute Y and add its members to the overloaded
19688 // candidate set.
19689 for (auto *NS : AssociatedNamespaces) {
19690 // When considering an associated namespace, the lookup is the
19691 // same as the lookup performed when the associated namespace is
19692 // used as a qualifier (3.4.3.2) except that:
19693 //
19694 // -- Any using-directives in the associated namespace are
19695 // ignored.
19696 //
19697 // -- Any namespace-scope friend functions declared in
19698 // associated classes are visible within their respective
19699 // namespaces even if they are not visible during an ordinary
19700 // lookup (11.4).
19701 DeclContext::lookup_result R = NS->lookup(Id.getName());
19702 for (auto *D : R) {
19703 auto *Underlying = D;
19704 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19705 Underlying = USD->getTargetDecl();
19706
19707 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
19708 !isa<OMPDeclareMapperDecl>(Underlying))
19709 continue;
19710
19711 if (!SemaRef.isVisible(D)) {
19712 D = findAcceptableDecl(SemaRef, D);
19713 if (!D)
19714 continue;
19715 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19716 Underlying = USD->getTargetDecl();
19717 }
19718 Lookups.emplace_back();
19719 Lookups.back().addDecl(Underlying);
19720 }
19721 }
19722}
19723
19724static ExprResult
19726 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
19727 const DeclarationNameInfo &ReductionId, QualType Ty,
19728 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
19729 if (ReductionIdScopeSpec.isInvalid())
19730 return ExprError();
19731 SmallVector<UnresolvedSet<8>, 4> Lookups;
19732 if (S) {
19733 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19734 Lookup.suppressDiagnostics();
19735 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec,
19736 /*ObjectType=*/QualType())) {
19737 NamedDecl *D = Lookup.getRepresentativeDecl();
19738 do {
19739 S = S->getParent();
19740 } while (S && !S->isDeclScope(D));
19741 if (S)
19742 S = S->getParent();
19743 Lookups.emplace_back();
19744 Lookups.back().append(Lookup.begin(), Lookup.end());
19745 Lookup.clear();
19746 }
19747 } else if (auto *ULE =
19748 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
19749 Lookups.push_back(UnresolvedSet<8>());
19750 Decl *PrevD = nullptr;
19751 for (NamedDecl *D : ULE->decls()) {
19752 if (D == PrevD)
19753 Lookups.push_back(UnresolvedSet<8>());
19754 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
19755 Lookups.back().addDecl(DRD);
19756 PrevD = D;
19757 }
19758 }
19759 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
19763 return !D->isInvalidDecl() &&
19764 (D->getType()->isDependentType() ||
19765 D->getType()->isInstantiationDependentType() ||
19766 D->getType()->containsUnexpandedParameterPack());
19767 })) {
19768 UnresolvedSet<8> ResSet;
19769 for (const UnresolvedSet<8> &Set : Lookups) {
19770 if (Set.empty())
19771 continue;
19772 ResSet.append(Set.begin(), Set.end());
19773 // The last item marks the end of all declarations at the specified scope.
19774 ResSet.addDecl(Set[Set.size() - 1]);
19775 }
19777 SemaRef.Context, /*NamingClass=*/nullptr,
19778 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
19779 /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false,
19780 /*KnownInstantiationDependent=*/false);
19781 }
19782 // Lookup inside the classes.
19783 // C++ [over.match.oper]p3:
19784 // For a unary operator @ with an operand of a type whose
19785 // cv-unqualified version is T1, and for a binary operator @ with
19786 // a left operand of a type whose cv-unqualified version is T1 and
19787 // a right operand of a type whose cv-unqualified version is T2,
19788 // three sets of candidate functions, designated member
19789 // candidates, non-member candidates and built-in candidates, are
19790 // constructed as follows:
19791 // -- If T1 is a complete class type or a class currently being
19792 // defined, the set of member candidates is the result of the
19793 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
19794 // the set of member candidates is empty.
19795 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19796 Lookup.suppressDiagnostics();
19797 if (Ty->isRecordType()) {
19798 // Complete the type if it can be completed.
19799 // If the type is neither complete nor being defined, bail out now.
19800 bool IsComplete = SemaRef.isCompleteType(Loc, Ty);
19801 auto *RD = Ty->castAsRecordDecl();
19802 if (IsComplete || RD->isBeingDefined()) {
19803 Lookup.clear();
19804 SemaRef.LookupQualifiedName(Lookup, RD);
19805 if (Lookup.empty()) {
19806 Lookups.emplace_back();
19807 Lookups.back().append(Lookup.begin(), Lookup.end());
19808 }
19809 }
19810 }
19811 // Perform ADL.
19812 if (SemaRef.getLangOpts().CPlusPlus)
19813 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
19815 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
19816 if (!D->isInvalidDecl() &&
19817 SemaRef.Context.hasSameType(D->getType(), Ty))
19818 return D;
19819 return nullptr;
19820 }))
19821 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
19822 VK_LValue, Loc);
19823 if (SemaRef.getLangOpts().CPlusPlus) {
19825 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
19826 if (!D->isInvalidDecl() &&
19827 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
19829 SemaRef.getASTContext()))
19830 return D;
19831 return nullptr;
19832 })) {
19833 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
19834 /*DetectVirtual=*/false);
19835 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
19836 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
19837 VD->getType().getUnqualifiedType()))) {
19838 if (SemaRef.CheckBaseClassAccess(
19839 Loc, VD->getType(), Ty, Paths.front(),
19840 /*DiagID=*/0) != Sema::AR_inaccessible) {
19841 SemaRef.BuildBasePathArray(Paths, BasePath);
19842 return SemaRef.BuildDeclRefExpr(
19843 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc);
19844 }
19845 }
19846 }
19847 }
19848 }
19849 if (ReductionIdScopeSpec.isSet()) {
19850 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
19851 << Ty << Range;
19852 return ExprError();
19853 }
19854 return ExprEmpty();
19855}
19856
19857namespace {
19858/// Data for the reduction-based clauses.
19859struct ReductionData {
19860 /// List of original reduction items.
19861 SmallVector<Expr *, 8> Vars;
19862 /// List of private copies of the reduction items.
19863 SmallVector<Expr *, 8> Privates;
19864 /// LHS expressions for the reduction_op expressions.
19865 SmallVector<Expr *, 8> LHSs;
19866 /// RHS expressions for the reduction_op expressions.
19867 SmallVector<Expr *, 8> RHSs;
19868 /// Reduction operation expression.
19869 SmallVector<Expr *, 8> ReductionOps;
19870 /// inscan copy operation expressions.
19871 SmallVector<Expr *, 8> InscanCopyOps;
19872 /// inscan copy temp array expressions for prefix sums.
19873 SmallVector<Expr *, 8> InscanCopyArrayTemps;
19874 /// inscan copy temp array element expressions for prefix sums.
19875 SmallVector<Expr *, 8> InscanCopyArrayElems;
19876 /// Taskgroup descriptors for the corresponding reduction items in
19877 /// in_reduction clauses.
19878 SmallVector<Expr *, 8> TaskgroupDescriptors;
19879 /// List of captures for clause.
19880 SmallVector<Decl *, 4> ExprCaptures;
19881 /// List of postupdate expressions.
19882 SmallVector<Expr *, 4> ExprPostUpdates;
19883 /// Reduction modifier.
19884 unsigned RedModifier = 0;
19885 /// Original modifier.
19886 unsigned OrigSharingModifier = 0;
19887 /// Private Variable Reduction
19888 SmallVector<bool, 8> IsPrivateVarReduction;
19889 ReductionData() = delete;
19890 /// Reserves required memory for the reduction data.
19891 ReductionData(unsigned Size, unsigned Modifier = 0, unsigned OrgModifier = 0)
19892 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
19893 Vars.reserve(Size);
19894 Privates.reserve(Size);
19895 LHSs.reserve(Size);
19896 RHSs.reserve(Size);
19897 ReductionOps.reserve(Size);
19898 IsPrivateVarReduction.reserve(Size);
19899 if (RedModifier == OMPC_REDUCTION_inscan) {
19900 InscanCopyOps.reserve(Size);
19901 InscanCopyArrayTemps.reserve(Size);
19902 InscanCopyArrayElems.reserve(Size);
19903 }
19904 TaskgroupDescriptors.reserve(Size);
19905 ExprCaptures.reserve(Size);
19906 ExprPostUpdates.reserve(Size);
19907 }
19908 /// Stores reduction item and reduction operation only (required for dependent
19909 /// reduction item).
19910 void push(Expr *Item, Expr *ReductionOp) {
19911 Vars.emplace_back(Item);
19912 Privates.emplace_back(nullptr);
19913 LHSs.emplace_back(nullptr);
19914 RHSs.emplace_back(nullptr);
19915 ReductionOps.emplace_back(ReductionOp);
19916 IsPrivateVarReduction.emplace_back(false);
19917 TaskgroupDescriptors.emplace_back(nullptr);
19918 if (RedModifier == OMPC_REDUCTION_inscan) {
19919 InscanCopyOps.push_back(nullptr);
19920 InscanCopyArrayTemps.push_back(nullptr);
19921 InscanCopyArrayElems.push_back(nullptr);
19922 }
19923 }
19924 /// Stores reduction data.
19925 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
19926 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
19927 Expr *CopyArrayElem, bool IsPrivate) {
19928 Vars.emplace_back(Item);
19929 Privates.emplace_back(Private);
19930 LHSs.emplace_back(LHS);
19931 RHSs.emplace_back(RHS);
19932 ReductionOps.emplace_back(ReductionOp);
19933 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
19934 if (RedModifier == OMPC_REDUCTION_inscan) {
19935 InscanCopyOps.push_back(CopyOp);
19936 InscanCopyArrayTemps.push_back(CopyArrayTemp);
19937 InscanCopyArrayElems.push_back(CopyArrayElem);
19938 } else {
19939 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
19940 CopyArrayElem == nullptr &&
19941 "Copy operation must be used for inscan reductions only.");
19942 }
19943 IsPrivateVarReduction.emplace_back(IsPrivate);
19944 }
19945};
19946} // namespace
19947
19949 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
19950 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
19951 const Expr *Length = OASE->getLength();
19952 if (Length == nullptr) {
19953 // For array sections of the form [1:] or [:], we would need to analyze
19954 // the lower bound...
19955 if (OASE->getColonLocFirst().isValid())
19956 return false;
19957
19958 // This is an array subscript which has implicit length 1!
19959 SingleElement = true;
19960 ArraySizes.push_back(llvm::APSInt::get(1));
19961 } else {
19962 Expr::EvalResult Result;
19963 if (!Length->EvaluateAsInt(Result, Context))
19964 return false;
19965
19966 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19967 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
19968 ArraySizes.push_back(ConstantLengthValue);
19969 }
19970
19971 // Get the base of this array section and walk up from there.
19972 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
19973
19974 // We require length = 1 for all array sections except the right-most to
19975 // guarantee that the memory region is contiguous and has no holes in it.
19976 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) {
19977 Length = TempOASE->getLength();
19978 if (Length == nullptr) {
19979 // For array sections of the form [1:] or [:], we would need to analyze
19980 // the lower bound...
19981 if (OASE->getColonLocFirst().isValid())
19982 return false;
19983
19984 // This is an array subscript which has implicit length 1!
19985 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
19986 ArraySizes.push_back(ConstantOne);
19987 } else {
19988 Expr::EvalResult Result;
19989 if (!Length->EvaluateAsInt(Result, Context))
19990 return false;
19991
19992 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19993 if (ConstantLengthValue.getSExtValue() != 1)
19994 return false;
19995
19996 ArraySizes.push_back(ConstantLengthValue);
19997 }
19998 Base = TempOASE->getBase()->IgnoreParenImpCasts();
19999 }
20000
20001 // If we have a single element, we don't need to add the implicit lengths.
20002 if (!SingleElement) {
20003 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
20004 // Has implicit length 1!
20005 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
20006 ArraySizes.push_back(ConstantOne);
20007 Base = TempASE->getBase()->IgnoreParenImpCasts();
20008 }
20009 }
20010
20011 // This array section can be privatized as a single value or as a constant
20012 // sized array.
20013 return true;
20014}
20015
20016static BinaryOperatorKind
20018 if (BOK == BO_Add)
20019 return BO_AddAssign;
20020 if (BOK == BO_Mul)
20021 return BO_MulAssign;
20022 if (BOK == BO_And)
20023 return BO_AndAssign;
20024 if (BOK == BO_Or)
20025 return BO_OrAssign;
20026 if (BOK == BO_Xor)
20027 return BO_XorAssign;
20028 return BOK;
20029}
20030
20032 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
20033 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20034 SourceLocation ColonLoc, SourceLocation EndLoc,
20035 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20036 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
20037 DeclarationName DN = ReductionId.getName();
20039 BinaryOperatorKind BOK = BO_Comma;
20040
20041 ASTContext &Context = S.Context;
20042 // OpenMP [2.14.3.6, reduction clause]
20043 // C
20044 // reduction-identifier is either an identifier or one of the following
20045 // operators: +, -, *, &, |, ^, && and ||
20046 // C++
20047 // reduction-identifier is either an id-expression or one of the following
20048 // operators: +, -, *, &, |, ^, && and ||
20049 switch (OOK) {
20050 case OO_Plus:
20051 BOK = BO_Add;
20052 break;
20053 case OO_Minus:
20054 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
20055 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
20056 // reduction identifier.
20057 if (S.LangOpts.OpenMP > 52)
20058 BOK = BO_Comma;
20059 else
20060 BOK = BO_Add;
20061 break;
20062 case OO_Star:
20063 BOK = BO_Mul;
20064 break;
20065 case OO_Amp:
20066 BOK = BO_And;
20067 break;
20068 case OO_Pipe:
20069 BOK = BO_Or;
20070 break;
20071 case OO_Caret:
20072 BOK = BO_Xor;
20073 break;
20074 case OO_AmpAmp:
20075 BOK = BO_LAnd;
20076 break;
20077 case OO_PipePipe:
20078 BOK = BO_LOr;
20079 break;
20080 case OO_New:
20081 case OO_Delete:
20082 case OO_Array_New:
20083 case OO_Array_Delete:
20084 case OO_Slash:
20085 case OO_Percent:
20086 case OO_Tilde:
20087 case OO_Exclaim:
20088 case OO_Equal:
20089 case OO_Less:
20090 case OO_Greater:
20091 case OO_LessEqual:
20092 case OO_GreaterEqual:
20093 case OO_PlusEqual:
20094 case OO_MinusEqual:
20095 case OO_StarEqual:
20096 case OO_SlashEqual:
20097 case OO_PercentEqual:
20098 case OO_CaretEqual:
20099 case OO_AmpEqual:
20100 case OO_PipeEqual:
20101 case OO_LessLess:
20102 case OO_GreaterGreater:
20103 case OO_LessLessEqual:
20104 case OO_GreaterGreaterEqual:
20105 case OO_EqualEqual:
20106 case OO_ExclaimEqual:
20107 case OO_Spaceship:
20108 case OO_PlusPlus:
20109 case OO_MinusMinus:
20110 case OO_Comma:
20111 case OO_ArrowStar:
20112 case OO_Arrow:
20113 case OO_Call:
20114 case OO_Subscript:
20115 case OO_Conditional:
20116 case OO_Coawait:
20118 llvm_unreachable("Unexpected reduction identifier");
20119 case OO_None:
20120 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
20121 if (II->isStr("max"))
20122 BOK = BO_GT;
20123 else if (II->isStr("min"))
20124 BOK = BO_LT;
20125 }
20126 break;
20127 }
20128
20129 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
20130 // A reduction clause with the minus (-) operator was deprecated
20131 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
20132 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
20133
20134 SourceRange ReductionIdRange;
20135 if (ReductionIdScopeSpec.isValid())
20136 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
20137 else
20138 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
20139 ReductionIdRange.setEnd(ReductionId.getEndLoc());
20140
20141 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
20142 bool FirstIter = true;
20143 for (Expr *RefExpr : VarList) {
20144 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
20145 // OpenMP [2.1, C/C++]
20146 // A list item is a variable or array section, subject to the restrictions
20147 // specified in Section 2.4 on page 42 and in each of the sections
20148 // describing clauses and directives for which a list appears.
20149 // OpenMP [2.14.3.3, Restrictions, p.1]
20150 // A variable that is part of another variable (as an array or
20151 // structure element) cannot appear in a private clause.
20152 if (!FirstIter && IR != ER)
20153 ++IR;
20154 FirstIter = false;
20155 SourceLocation ELoc;
20156 SourceRange ERange;
20157 bool IsPrivate = false;
20158 Expr *SimpleRefExpr = RefExpr;
20159 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
20160 /*AllowArraySection=*/true);
20161 if (Res.second) {
20162 // Try to find 'declare reduction' corresponding construct before using
20163 // builtin/overloaded operators.
20164 QualType Type = Context.DependentTy;
20165 CXXCastPath BasePath;
20166 ExprResult DeclareReductionRef = buildDeclareReductionRef(
20167 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20168 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
20169 Expr *ReductionOp = nullptr;
20170 if (S.CurContext->isDependentContext() &&
20171 (DeclareReductionRef.isUnset() ||
20172 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
20173 ReductionOp = DeclareReductionRef.get();
20174 // It will be analyzed later.
20175 RD.push(RefExpr, ReductionOp);
20176 }
20177 ValueDecl *D = Res.first;
20178 if (!D)
20179 continue;
20180
20181 Expr *TaskgroupDescriptor = nullptr;
20182 QualType Type;
20183 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
20184 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
20185 if (ASE) {
20186 Type = ASE->getType().getNonReferenceType();
20187 } else if (OASE) {
20188 QualType BaseType =
20190 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20191 Type = ATy->getElementType();
20192 else
20193 Type = BaseType->getPointeeType();
20194 Type = Type.getNonReferenceType();
20195 } else {
20196 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
20197 }
20198 auto *VD = dyn_cast<VarDecl>(D);
20199
20200 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
20201 // A variable that appears in a private clause must not have an incomplete
20202 // type or a reference type.
20203 if (S.RequireCompleteType(ELoc, D->getType(),
20204 diag::err_omp_reduction_incomplete_type))
20205 continue;
20206 // OpenMP [2.14.3.6, reduction clause, Restrictions]
20207 // A list item that appears in a reduction clause must not be
20208 // const-qualified.
20209 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
20210 /*AcceptIfMutable=*/false, ASE || OASE))
20211 continue;
20212
20213 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
20214 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
20215 // If a list-item is a reference type then it must bind to the same object
20216 // for all threads of the team.
20217 if (!ASE && !OASE) {
20218 if (VD) {
20219 VarDecl *VDDef = VD->getDefinition();
20220 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
20221 DSARefChecker Check(Stack);
20222 if (Check.Visit(VDDef->getInit())) {
20223 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
20224 << getOpenMPClauseNameForDiag(ClauseKind) << ERange;
20225 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
20226 continue;
20227 }
20228 }
20229 }
20230
20231 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
20232 // in a Construct]
20233 // Variables with the predetermined data-sharing attributes may not be
20234 // listed in data-sharing attributes clauses, except for the cases
20235 // listed below. For these exceptions only, listing a predetermined
20236 // variable in a data-sharing attribute clause is allowed and overrides
20237 // the variable's predetermined data-sharing attributes.
20238 // OpenMP [2.14.3.6, Restrictions, p.3]
20239 // Any number of reduction clauses can be specified on the directive,
20240 // but a list item can appear only once in the reduction clauses for that
20241 // directive.
20242 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
20243 if (DVar.CKind == OMPC_reduction) {
20244 S.Diag(ELoc, diag::err_omp_once_referenced)
20245 << getOpenMPClauseNameForDiag(ClauseKind);
20246 if (DVar.RefExpr)
20247 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
20248 continue;
20249 }
20250 if (DVar.CKind != OMPC_unknown) {
20251 S.Diag(ELoc, diag::err_omp_wrong_dsa)
20252 << getOpenMPClauseNameForDiag(DVar.CKind)
20253 << getOpenMPClauseNameForDiag(OMPC_reduction);
20254 reportOriginalDsa(S, Stack, D, DVar);
20255 continue;
20256 }
20257
20258 // OpenMP [2.14.3.6, Restrictions, p.1]
20259 // A list item that appears in a reduction clause of a worksharing
20260 // construct must be shared in the parallel regions to which any of the
20261 // worksharing regions arising from the worksharing construct bind.
20262
20263 if (S.getLangOpts().OpenMP <= 52 &&
20265 !isOpenMPParallelDirective(CurrDir) &&
20266 !isOpenMPTeamsDirective(CurrDir)) {
20267 DVar = Stack->getImplicitDSA(D, true);
20268 if (DVar.CKind != OMPC_shared) {
20269 S.Diag(ELoc, diag::err_omp_required_access)
20270 << getOpenMPClauseNameForDiag(OMPC_reduction)
20271 << getOpenMPClauseNameForDiag(OMPC_shared);
20272 reportOriginalDsa(S, Stack, D, DVar);
20273 continue;
20274 }
20275 } else if (isOpenMPWorksharingDirective(CurrDir) &&
20276 !isOpenMPParallelDirective(CurrDir) &&
20277 !isOpenMPTeamsDirective(CurrDir)) {
20278 // OpenMP 6.0 [ 7.6.10 ]
20279 // Support Reduction over private variables with reduction clause.
20280 // A list item in a reduction clause can now be private in the enclosing
20281 // context. For orphaned constructs it is assumed to be shared unless
20282 // the original(private) modifier appears in the clause.
20283 DVar = Stack->getImplicitDSA(D, true);
20284 // Determine if the variable should be considered private
20285 IsPrivate = DVar.CKind != OMPC_shared;
20286 bool IsOrphaned = false;
20287 OpenMPDirectiveKind ParentDir = Stack->getParentDirective();
20288 IsOrphaned = ParentDir == OMPD_unknown;
20289 if ((IsOrphaned &&
20290 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
20291 IsPrivate = true;
20292 }
20293 } else {
20294 // Threadprivates cannot be shared between threads, so dignose if the base
20295 // is a threadprivate variable.
20296 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
20297 if (DVar.CKind == OMPC_threadprivate) {
20298 S.Diag(ELoc, diag::err_omp_wrong_dsa)
20299 << getOpenMPClauseNameForDiag(DVar.CKind)
20300 << getOpenMPClauseNameForDiag(OMPC_reduction);
20301 reportOriginalDsa(S, Stack, D, DVar);
20302 continue;
20303 }
20304 }
20305
20306 // Try to find 'declare reduction' corresponding construct before using
20307 // builtin/overloaded operators.
20308 CXXCastPath BasePath;
20309 ExprResult DeclareReductionRef = buildDeclareReductionRef(
20310 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20311 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
20312 if (DeclareReductionRef.isInvalid())
20313 continue;
20314 if (S.CurContext->isDependentContext() &&
20315 (DeclareReductionRef.isUnset() ||
20316 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
20317 RD.push(RefExpr, DeclareReductionRef.get());
20318 continue;
20319 }
20320 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
20321 // Not allowed reduction identifier is found.
20322 if (S.LangOpts.OpenMP > 52)
20323 S.Diag(ReductionId.getBeginLoc(),
20324 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
20325 << Type << ReductionIdRange;
20326 else
20327 S.Diag(ReductionId.getBeginLoc(),
20328 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
20329 << Type << ReductionIdRange;
20330 continue;
20331 }
20332
20333 // OpenMP [2.14.3.6, reduction clause, Restrictions]
20334 // The type of a list item that appears in a reduction clause must be valid
20335 // for the reduction-identifier. For a max or min reduction in C, the type
20336 // of the list item must be an allowed arithmetic data type: char, int,
20337 // float, double, or _Bool, possibly modified with long, short, signed, or
20338 // unsigned. For a max or min reduction in C++, the type of the list item
20339 // must be an allowed arithmetic data type: char, wchar_t, int, float,
20340 // double, or bool, possibly modified with long, short, signed, or unsigned.
20341 if (DeclareReductionRef.isUnset()) {
20342 if ((BOK == BO_GT || BOK == BO_LT) &&
20343 !(Type->isScalarType() ||
20344 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
20345 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
20346 << getOpenMPClauseNameForDiag(ClauseKind)
20347 << S.getLangOpts().CPlusPlus;
20348 if (!ASE && !OASE) {
20349 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20351 S.Diag(D->getLocation(),
20352 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20353 << D;
20354 }
20355 continue;
20356 }
20357 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
20358 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
20359 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
20360 << getOpenMPClauseNameForDiag(ClauseKind);
20361 if (!ASE && !OASE) {
20362 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20364 S.Diag(D->getLocation(),
20365 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20366 << D;
20367 }
20368 continue;
20369 }
20370 }
20371
20372 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
20373 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
20374 D->hasAttrs() ? &D->getAttrs() : nullptr);
20375 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
20376 D->hasAttrs() ? &D->getAttrs() : nullptr);
20377 QualType PrivateTy = Type;
20378
20379 // Try if we can determine constant lengths for all array sections and avoid
20380 // the VLA.
20381 bool ConstantLengthOASE = false;
20382 if (OASE) {
20383 bool SingleElement;
20385 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
20386 Context, OASE, SingleElement, ArraySizes);
20387
20388 // If we don't have a single element, we must emit a constant array type.
20389 if (ConstantLengthOASE && !SingleElement) {
20390 for (llvm::APSInt &Size : ArraySizes)
20391 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
20393 /*IndexTypeQuals=*/0);
20394 }
20395 }
20396
20397 if ((OASE && !ConstantLengthOASE) ||
20398 (!OASE && !ASE &&
20400 if (!Context.getTargetInfo().isVLASupported()) {
20401 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
20402 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20403 S.Diag(ELoc, diag::note_vla_unsupported);
20404 continue;
20405 } else {
20406 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20407 S.targetDiag(ELoc, diag::note_vla_unsupported);
20408 }
20409 }
20410 // For arrays/array sections only:
20411 // Create pseudo array type for private copy. The size for this array will
20412 // be generated during codegen.
20413 // For array subscripts or single variables Private Ty is the same as Type
20414 // (type of the variable or single array element).
20415 PrivateTy = Context.getVariableArrayType(
20416 Type,
20417 new (Context)
20418 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
20419 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0);
20420 } else if (!ASE && !OASE &&
20421 Context.getAsArrayType(D->getType().getNonReferenceType())) {
20422 PrivateTy = D->getType().getNonReferenceType();
20423 }
20424 // Private copy.
20425 VarDecl *PrivateVD =
20426 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
20427 D->hasAttrs() ? &D->getAttrs() : nullptr,
20428 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
20429 // Add initializer for private variable.
20430 Expr *Init = nullptr;
20431 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
20432 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
20433 if (DeclareReductionRef.isUsable()) {
20434 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
20435 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
20436 if (DRD->getInitializer()) {
20437 Init = DRDRef;
20438 RHSVD->setInit(DRDRef);
20440 }
20441 } else {
20442 switch (BOK) {
20443 case BO_Add:
20444 case BO_Xor:
20445 case BO_Or:
20446 case BO_LOr:
20447 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
20449 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
20450 break;
20451 case BO_Mul:
20452 case BO_LAnd:
20453 if (Type->isScalarType() || Type->isAnyComplexType()) {
20454 // '*' and '&&' reduction ops - initializer is '1'.
20455 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
20456 }
20457 break;
20458 case BO_And: {
20459 // '&' reduction op - initializer is '~0'.
20460 QualType OrigType = Type;
20461 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
20462 Type = ComplexTy->getElementType();
20463 if (Type->isRealFloatingType()) {
20464 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
20465 Context.getFloatTypeSemantics(Type));
20466 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
20467 Type, ELoc);
20468 } else if (Type->isScalarType()) {
20469 uint64_t Size = Context.getTypeSize(Type);
20470 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
20471 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
20472 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
20473 }
20474 if (Init && OrigType->isAnyComplexType()) {
20475 // Init = 0xFFFF + 0xFFFFi;
20476 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
20477 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
20478 }
20479 Type = OrigType;
20480 break;
20481 }
20482 case BO_LT:
20483 case BO_GT: {
20484 // 'min' reduction op - initializer is 'Largest representable number in
20485 // the reduction list item type'.
20486 // 'max' reduction op - initializer is 'Least representable number in
20487 // the reduction list item type'.
20488 if (Type->isIntegerType() || Type->isPointerType()) {
20489 bool IsSigned = Type->hasSignedIntegerRepresentation();
20490 uint64_t Size = Context.getTypeSize(Type);
20491 QualType IntTy =
20492 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
20493 llvm::APInt InitValue =
20494 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
20495 : llvm::APInt::getMinValue(Size)
20496 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
20497 : llvm::APInt::getMaxValue(Size);
20498 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
20499 if (Type->isPointerType()) {
20500 // Cast to pointer type.
20502 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
20503 if (CastExpr.isInvalid())
20504 continue;
20505 Init = CastExpr.get();
20506 }
20507 } else if (Type->isRealFloatingType()) {
20508 llvm::APFloat InitValue = llvm::APFloat::getLargest(
20509 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
20510 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
20511 Type, ELoc);
20512 }
20513 break;
20514 }
20515 case BO_PtrMemD:
20516 case BO_PtrMemI:
20517 case BO_MulAssign:
20518 case BO_Div:
20519 case BO_Rem:
20520 case BO_Sub:
20521 case BO_Shl:
20522 case BO_Shr:
20523 case BO_LE:
20524 case BO_GE:
20525 case BO_EQ:
20526 case BO_NE:
20527 case BO_Cmp:
20528 case BO_AndAssign:
20529 case BO_XorAssign:
20530 case BO_OrAssign:
20531 case BO_Assign:
20532 case BO_AddAssign:
20533 case BO_SubAssign:
20534 case BO_DivAssign:
20535 case BO_RemAssign:
20536 case BO_ShlAssign:
20537 case BO_ShrAssign:
20538 case BO_Comma:
20539 llvm_unreachable("Unexpected reduction operation");
20540 }
20541 }
20542 if (Init && DeclareReductionRef.isUnset()) {
20543 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
20544 // Store initializer for single element in private copy. Will be used
20545 // during codegen.
20546 PrivateVD->setInit(RHSVD->getInit());
20547 PrivateVD->setInitStyle(RHSVD->getInitStyle());
20548 } else if (!Init) {
20549 S.ActOnUninitializedDecl(RHSVD);
20550 // Store initializer for single element in private copy. Will be used
20551 // during codegen.
20552 PrivateVD->setInit(RHSVD->getInit());
20553 PrivateVD->setInitStyle(RHSVD->getInitStyle());
20554 }
20555 if (RHSVD->isInvalidDecl())
20556 continue;
20557 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
20558 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
20559 << Type << ReductionIdRange;
20560 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20562 S.Diag(D->getLocation(),
20563 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20564 << D;
20565 continue;
20566 }
20567 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
20568 ExprResult ReductionOp;
20569 if (DeclareReductionRef.isUsable()) {
20570 QualType RedTy = DeclareReductionRef.get()->getType();
20571 QualType PtrRedTy = Context.getPointerType(RedTy);
20572 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
20573 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
20574 if (!BasePath.empty()) {
20575 LHS = S.DefaultLvalueConversion(LHS.get());
20576 RHS = S.DefaultLvalueConversion(RHS.get());
20578 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
20579 LHS.get()->getValueKind(), FPOptionsOverride());
20581 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
20582 RHS.get()->getValueKind(), FPOptionsOverride());
20583 }
20585 QualType Params[] = {PtrRedTy, PtrRedTy};
20586 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
20587 auto *OVE = new (Context) OpaqueValueExpr(
20588 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
20589 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
20590 Expr *Args[] = {LHS.get(), RHS.get()};
20591 ReductionOp =
20592 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
20594 } else {
20596 if (Type->isRecordType() && CombBOK != BOK) {
20598 ReductionOp =
20599 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20600 CombBOK, LHSDRE, RHSDRE);
20601 }
20602 if (!ReductionOp.isUsable()) {
20603 ReductionOp =
20604 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
20605 LHSDRE, RHSDRE);
20606 if (ReductionOp.isUsable()) {
20607 if (BOK != BO_LT && BOK != BO_GT) {
20608 ReductionOp =
20609 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20610 BO_Assign, LHSDRE, ReductionOp.get());
20611 } else {
20612 auto *ConditionalOp = new (Context)
20613 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
20614 RHSDRE, Type, VK_LValue, OK_Ordinary);
20615 ReductionOp =
20616 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20617 BO_Assign, LHSDRE, ConditionalOp);
20618 }
20619 }
20620 }
20621 if (ReductionOp.isUsable())
20622 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
20623 /*DiscardedValue=*/false);
20624 if (!ReductionOp.isUsable())
20625 continue;
20626 }
20627
20628 // Add copy operations for inscan reductions.
20629 // LHS = RHS;
20630 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
20631 if (ClauseKind == OMPC_reduction &&
20632 RD.RedModifier == OMPC_REDUCTION_inscan) {
20633 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
20634 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
20635 RHS.get());
20636 if (!CopyOpRes.isUsable())
20637 continue;
20638 CopyOpRes =
20639 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
20640 if (!CopyOpRes.isUsable())
20641 continue;
20642 // For simd directive and simd-based directives in simd mode no need to
20643 // construct temp array, need just a single temp element.
20644 if (Stack->getCurrentDirective() == OMPD_simd ||
20645 (S.getLangOpts().OpenMPSimd &&
20646 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
20647 VarDecl *TempArrayVD =
20648 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
20649 D->hasAttrs() ? &D->getAttrs() : nullptr);
20650 // Add a constructor to the temp decl.
20651 S.ActOnUninitializedDecl(TempArrayVD);
20652 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
20653 } else {
20654 // Build temp array for prefix sum.
20655 auto *Dim = new (S.Context)
20658 PrivateTy, Dim, ArraySizeModifier::Normal,
20659 /*IndexTypeQuals=*/0);
20660 VarDecl *TempArrayVD =
20661 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
20662 D->hasAttrs() ? &D->getAttrs() : nullptr);
20663 // Add a constructor to the temp decl.
20664 S.ActOnUninitializedDecl(TempArrayVD);
20665 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
20666 TempArrayElem =
20667 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
20668 auto *Idx = new (S.Context)
20670 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
20671 ELoc, Idx, ELoc);
20672 }
20673 }
20674
20675 // OpenMP [2.15.4.6, Restrictions, p.2]
20676 // A list item that appears in an in_reduction clause of a task construct
20677 // must appear in a task_reduction clause of a construct associated with a
20678 // taskgroup region that includes the participating task in its taskgroup
20679 // set. The construct associated with the innermost region that meets this
20680 // condition must specify the same reduction-identifier as the in_reduction
20681 // clause.
20682 if (ClauseKind == OMPC_in_reduction) {
20683 SourceRange ParentSR;
20684 BinaryOperatorKind ParentBOK;
20685 const Expr *ParentReductionOp = nullptr;
20686 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
20687 DSAStackTy::DSAVarData ParentBOKDSA =
20688 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
20689 ParentBOKTD);
20690 DSAStackTy::DSAVarData ParentReductionOpDSA =
20691 Stack->getTopMostTaskgroupReductionData(
20692 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
20693 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
20694 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
20695 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
20696 (DeclareReductionRef.isUsable() && IsParentBOK) ||
20697 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
20698 bool EmitError = true;
20699 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
20700 llvm::FoldingSetNodeID RedId, ParentRedId;
20701 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
20702 DeclareReductionRef.get()->Profile(RedId, Context,
20703 /*Canonical=*/true);
20704 EmitError = RedId != ParentRedId;
20705 }
20706 if (EmitError) {
20707 S.Diag(ReductionId.getBeginLoc(),
20708 diag::err_omp_reduction_identifier_mismatch)
20709 << ReductionIdRange << RefExpr->getSourceRange();
20710 S.Diag(ParentSR.getBegin(),
20711 diag::note_omp_previous_reduction_identifier)
20712 << ParentSR
20713 << (IsParentBOK ? ParentBOKDSA.RefExpr
20714 : ParentReductionOpDSA.RefExpr)
20715 ->getSourceRange();
20716 continue;
20717 }
20718 }
20719 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
20720 }
20721
20722 DeclRefExpr *Ref = nullptr;
20723 Expr *VarsExpr = RefExpr->IgnoreParens();
20724 if (!VD && !S.CurContext->isDependentContext()) {
20725 if (ASE || OASE) {
20726 TransformExprToCaptures RebuildToCapture(S, D);
20727 VarsExpr =
20728 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
20729 Ref = RebuildToCapture.getCapturedExpr();
20730 } else {
20731 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
20732 }
20733 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
20734 RD.ExprCaptures.emplace_back(Ref->getDecl());
20735 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20736 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
20737 if (!RefRes.isUsable())
20738 continue;
20739 ExprResult PostUpdateRes =
20740 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
20741 RefRes.get());
20742 if (!PostUpdateRes.isUsable())
20743 continue;
20744 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
20745 Stack->getCurrentDirective() == OMPD_taskgroup) {
20746 S.Diag(RefExpr->getExprLoc(),
20747 diag::err_omp_reduction_non_addressable_expression)
20748 << RefExpr->getSourceRange();
20749 continue;
20750 }
20751 RD.ExprPostUpdates.emplace_back(
20752 S.IgnoredValueConversions(PostUpdateRes.get()).get());
20753 }
20754 }
20755 }
20756 // All reduction items are still marked as reduction (to do not increase
20757 // code base size).
20758 unsigned Modifier = RD.RedModifier;
20759 // Consider task_reductions as reductions with task modifier. Required for
20760 // correct analysis of in_reduction clauses.
20761 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
20762 Modifier = OMPC_REDUCTION_task;
20763 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
20764 ASE || OASE);
20765 if (Modifier == OMPC_REDUCTION_task &&
20766 (CurrDir == OMPD_taskgroup ||
20767 ((isOpenMPParallelDirective(CurrDir) ||
20768 isOpenMPWorksharingDirective(CurrDir)) &&
20769 !isOpenMPSimdDirective(CurrDir)))) {
20770 if (DeclareReductionRef.isUsable())
20771 Stack->addTaskgroupReductionData(D, ReductionIdRange,
20772 DeclareReductionRef.get());
20773 else
20774 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
20775 }
20776 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
20777 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
20778 TempArrayElem.get(), IsPrivate);
20779 }
20780 return RD.Vars.empty();
20781}
20782
20784 ArrayRef<Expr *> VarList,
20786 SourceLocation StartLoc, SourceLocation LParenLoc,
20787 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
20788 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20789 ArrayRef<Expr *> UnresolvedReductions) {
20791 static_cast<OpenMPReductionClauseModifier>(Modifiers.ExtraModifier);
20792 OpenMPOriginalSharingModifier OriginalSharingModifier =
20793 static_cast<OpenMPOriginalSharingModifier>(
20794 Modifiers.OriginalSharingModifier);
20795 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
20796 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
20797 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
20798 /*Last=*/OMPC_REDUCTION_unknown)
20799 << getOpenMPClauseNameForDiag(OMPC_reduction);
20800 return nullptr;
20801 }
20802 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
20803 // A reduction clause with the inscan reduction-modifier may only appear on a
20804 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
20805 // construct, a parallel worksharing-loop construct or a parallel
20806 // worksharing-loop SIMD construct.
20807 if (Modifier == OMPC_REDUCTION_inscan &&
20808 (DSAStack->getCurrentDirective() != OMPD_for &&
20809 DSAStack->getCurrentDirective() != OMPD_for_simd &&
20810 DSAStack->getCurrentDirective() != OMPD_simd &&
20811 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
20812 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
20813 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
20814 return nullptr;
20815 }
20816 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
20817 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
20818 StartLoc, LParenLoc, ColonLoc, EndLoc,
20819 ReductionIdScopeSpec, ReductionId,
20820 UnresolvedReductions, RD))
20821 return nullptr;
20822
20824 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
20825 Modifier, RD.Vars,
20826 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20827 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
20828 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
20829 buildPreInits(getASTContext(), RD.ExprCaptures),
20830 buildPostUpdate(SemaRef, RD.ExprPostUpdates), RD.IsPrivateVarReduction,
20831 OriginalSharingModifier);
20832}
20833
20835 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20836 SourceLocation ColonLoc, SourceLocation EndLoc,
20837 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20838 ArrayRef<Expr *> UnresolvedReductions) {
20839 ReductionData RD(VarList.size());
20840 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction,
20841 VarList, StartLoc, LParenLoc, ColonLoc,
20842 EndLoc, ReductionIdScopeSpec, ReductionId,
20843 UnresolvedReductions, RD))
20844 return nullptr;
20845
20847 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20848 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20849 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
20850 buildPreInits(getASTContext(), RD.ExprCaptures),
20851 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
20852}
20853
20855 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20856 SourceLocation ColonLoc, SourceLocation EndLoc,
20857 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20858 ArrayRef<Expr *> UnresolvedReductions) {
20859 ReductionData RD(VarList.size());
20860 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList,
20861 StartLoc, LParenLoc, ColonLoc, EndLoc,
20862 ReductionIdScopeSpec, ReductionId,
20863 UnresolvedReductions, RD))
20864 return nullptr;
20865
20867 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20868 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20869 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
20870 buildPreInits(getASTContext(), RD.ExprCaptures),
20871 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
20872}
20873
20875 SourceLocation LinLoc) {
20876 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
20877 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
20878 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
20879 << getLangOpts().CPlusPlus;
20880 return true;
20881 }
20882 return false;
20883}
20884
20886 OpenMPLinearClauseKind LinKind,
20887 QualType Type, bool IsDeclareSimd) {
20888 const auto *VD = dyn_cast_or_null<VarDecl>(D);
20889 // A variable must not have an incomplete type or a reference type.
20890 if (SemaRef.RequireCompleteType(ELoc, Type,
20891 diag::err_omp_linear_incomplete_type))
20892 return true;
20893 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
20894 !Type->isReferenceType()) {
20895 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
20896 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
20897 return true;
20898 }
20899 Type = Type.getNonReferenceType();
20900
20901 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
20902 // A variable that is privatized must not have a const-qualified type
20903 // unless it is of class type with a mutable member. This restriction does
20904 // not apply to the firstprivate clause, nor to the linear clause on
20905 // declarative directives (like declare simd).
20906 if (!IsDeclareSimd &&
20907 rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc))
20908 return true;
20909
20910 // A list item must be of integral or pointer type.
20911 Type = Type.getUnqualifiedType().getCanonicalType();
20912 const auto *Ty = Type.getTypePtrOrNull();
20913 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
20914 !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) {
20915 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
20916 if (D) {
20917 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20919 Diag(D->getLocation(),
20920 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20921 << D;
20922 }
20923 return true;
20924 }
20925 return false;
20926}
20927
20929 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
20930 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
20931 SourceLocation LinLoc, SourceLocation ColonLoc,
20932 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
20934 SmallVector<Expr *, 8> Privates;
20936 SmallVector<Decl *, 4> ExprCaptures;
20937 SmallVector<Expr *, 4> ExprPostUpdates;
20938 // OpenMP 5.2 [Section 5.4.6, linear clause]
20939 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
20940 // 'ref'
20941 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
20942 getLangOpts().OpenMP >= 52)
20943 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
20944 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
20945 LinKind = OMPC_LINEAR_val;
20946 for (Expr *RefExpr : VarList) {
20947 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20948 SourceLocation ELoc;
20949 SourceRange ERange;
20950 Expr *SimpleRefExpr = RefExpr;
20951 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20952 if (Res.second) {
20953 // It will be analyzed later.
20954 Vars.push_back(RefExpr);
20955 Privates.push_back(nullptr);
20956 Inits.push_back(nullptr);
20957 }
20958 ValueDecl *D = Res.first;
20959 if (!D)
20960 continue;
20961
20962 QualType Type = D->getType();
20963 auto *VD = dyn_cast<VarDecl>(D);
20964
20965 // OpenMP [2.14.3.7, linear clause]
20966 // A list-item cannot appear in more than one linear clause.
20967 // A list-item that appears in a linear clause cannot appear in any
20968 // other data-sharing attribute clause.
20969 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
20970 if (DVar.RefExpr) {
20971 Diag(ELoc, diag::err_omp_wrong_dsa)
20972 << getOpenMPClauseNameForDiag(DVar.CKind)
20973 << getOpenMPClauseNameForDiag(OMPC_linear);
20975 continue;
20976 }
20977
20978 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
20979 continue;
20980 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20981
20982 // Build private copy of original var.
20983 VarDecl *Private =
20984 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
20985 D->hasAttrs() ? &D->getAttrs() : nullptr,
20986 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
20987 DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc);
20988 // Build var to save initial value.
20989 VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start");
20990 Expr *InitExpr;
20991 DeclRefExpr *Ref = nullptr;
20992 if (!VD && !SemaRef.CurContext->isDependentContext()) {
20993 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
20994 if (!isOpenMPCapturedDecl(D)) {
20995 ExprCaptures.push_back(Ref->getDecl());
20996 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20997 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
20998 if (!RefRes.isUsable())
20999 continue;
21000 ExprResult PostUpdateRes =
21001 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
21002 SimpleRefExpr, RefRes.get());
21003 if (!PostUpdateRes.isUsable())
21004 continue;
21005 ExprPostUpdates.push_back(
21006 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
21007 }
21008 }
21009 }
21010 if (LinKind == OMPC_LINEAR_uval)
21011 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
21012 else
21013 InitExpr = VD ? SimpleRefExpr : Ref;
21014 SemaRef.AddInitializerToDecl(
21015 Init, SemaRef.DefaultLvalueConversion(InitExpr).get(),
21016 /*DirectInit=*/false);
21017 DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc);
21018
21019 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
21020 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
21021 ? RefExpr->IgnoreParens()
21022 : Ref);
21023 Privates.push_back(PrivateRef);
21024 Inits.push_back(InitRef);
21025 }
21026
21027 if (Vars.empty())
21028 return nullptr;
21029
21030 Expr *StepExpr = Step;
21031 Expr *CalcStepExpr = nullptr;
21032 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
21033 !Step->isInstantiationDependent() &&
21035 SourceLocation StepLoc = Step->getBeginLoc();
21037 if (Val.isInvalid())
21038 return nullptr;
21039 StepExpr = Val.get();
21040
21041 // Build var to save the step value.
21042 VarDecl *SaveVar =
21043 buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step");
21044 ExprResult SaveRef =
21045 buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc);
21046 ExprResult CalcStep = SemaRef.BuildBinOp(
21047 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr);
21048 CalcStep =
21049 SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue=*/false);
21050
21051 // Warn about zero linear step (it would be probably better specified as
21052 // making corresponding variables 'const').
21053 if (std::optional<llvm::APSInt> Result =
21055 if (!Result->isNegative() && !Result->isStrictlyPositive())
21056 Diag(StepLoc, diag::warn_omp_linear_step_zero)
21057 << Vars[0] << (Vars.size() > 1);
21058 } else if (CalcStep.isUsable()) {
21059 // Calculate the step beforehand instead of doing this on each iteration.
21060 // (This is not used if the number of iterations may be kfold-ed).
21061 CalcStepExpr = CalcStep.get();
21062 }
21063 }
21064
21065 return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind,
21066 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
21067 Vars, Privates, Inits, StepExpr, CalcStepExpr,
21068 buildPreInits(getASTContext(), ExprCaptures),
21069 buildPostUpdate(SemaRef, ExprPostUpdates));
21070}
21071
21073 Expr *NumIterations, Sema &SemaRef,
21074 Scope *S, DSAStackTy *Stack) {
21075 // Walk the vars and build update/final expressions for the CodeGen.
21076 SmallVector<Expr *, 8> Updates;
21078 SmallVector<Expr *, 8> UsedExprs;
21079 Expr *Step = Clause.getStep();
21080 Expr *CalcStep = Clause.getCalcStep();
21081 // OpenMP [2.14.3.7, linear clause]
21082 // If linear-step is not specified it is assumed to be 1.
21083 if (!Step)
21084 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
21085 else if (CalcStep)
21086 Step = cast<BinaryOperator>(CalcStep)->getLHS();
21087 bool HasErrors = false;
21088 auto CurInit = Clause.inits().begin();
21089 auto CurPrivate = Clause.privates().begin();
21090 OpenMPLinearClauseKind LinKind = Clause.getModifier();
21091 for (Expr *RefExpr : Clause.varlist()) {
21092 SourceLocation ELoc;
21093 SourceRange ERange;
21094 Expr *SimpleRefExpr = RefExpr;
21095 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21096 ValueDecl *D = Res.first;
21097 if (Res.second || !D) {
21098 Updates.push_back(nullptr);
21099 Finals.push_back(nullptr);
21100 HasErrors = true;
21101 continue;
21102 }
21103 auto &&Info = Stack->isLoopControlVariable(D);
21104 // OpenMP [2.15.11, distribute simd Construct]
21105 // A list item may not appear in a linear clause, unless it is the loop
21106 // iteration variable.
21107 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
21108 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
21109 SemaRef.Diag(ELoc,
21110 diag::err_omp_linear_distribute_var_non_loop_iteration);
21111 Updates.push_back(nullptr);
21112 Finals.push_back(nullptr);
21113 HasErrors = true;
21114 continue;
21115 }
21116 Expr *InitExpr = *CurInit;
21117
21118 // Build privatized reference to the current linear var.
21119 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
21120 Expr *CapturedRef;
21121 if (LinKind == OMPC_LINEAR_uval)
21122 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
21123 else
21124 CapturedRef =
21125 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
21126 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
21127 /*RefersToCapture=*/true);
21128
21129 // Build update: Var = InitExpr + IV * Step
21131 if (!Info.first)
21133 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
21134 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
21135 else
21136 Update = *CurPrivate;
21137 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
21138 /*DiscardedValue=*/false);
21139
21140 // Build final: Var = PrivCopy;
21141 ExprResult Final;
21142 if (!Info.first)
21143 Final = SemaRef.BuildBinOp(
21144 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
21145 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
21146 else
21147 Final = *CurPrivate;
21148 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
21149 /*DiscardedValue=*/false);
21150
21151 if (!Update.isUsable() || !Final.isUsable()) {
21152 Updates.push_back(nullptr);
21153 Finals.push_back(nullptr);
21154 UsedExprs.push_back(nullptr);
21155 HasErrors = true;
21156 } else {
21157 Updates.push_back(Update.get());
21158 Finals.push_back(Final.get());
21159 if (!Info.first)
21160 UsedExprs.push_back(SimpleRefExpr);
21161 }
21162 ++CurInit;
21163 ++CurPrivate;
21164 }
21165 if (Expr *S = Clause.getStep())
21166 UsedExprs.push_back(S);
21167 // Fill the remaining part with the nullptr.
21168 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
21169 Clause.setUpdates(Updates);
21170 Clause.setFinals(Finals);
21171 Clause.setUsedExprs(UsedExprs);
21172 return HasErrors;
21173}
21174
21176 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
21177 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
21179 for (Expr *RefExpr : VarList) {
21180 assert(RefExpr && "NULL expr in OpenMP aligned clause.");
21181 SourceLocation ELoc;
21182 SourceRange ERange;
21183 Expr *SimpleRefExpr = RefExpr;
21184 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21185 if (Res.second) {
21186 // It will be analyzed later.
21187 Vars.push_back(RefExpr);
21188 }
21189 ValueDecl *D = Res.first;
21190 if (!D)
21191 continue;
21192
21193 QualType QType = D->getType();
21194 auto *VD = dyn_cast<VarDecl>(D);
21195
21196 // OpenMP [2.8.1, simd construct, Restrictions]
21197 // The type of list items appearing in the aligned clause must be
21198 // array, pointer, reference to array, or reference to pointer.
21200 const Type *Ty = QType.getTypePtrOrNull();
21201 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
21202 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
21203 << QType << getLangOpts().CPlusPlus << ERange;
21204 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21206 Diag(D->getLocation(),
21207 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21208 << D;
21209 continue;
21210 }
21211
21212 // OpenMP [2.8.1, simd construct, Restrictions]
21213 // A list-item cannot appear in more than one aligned clause.
21214 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
21215 Diag(ELoc, diag::err_omp_used_in_clause_twice)
21216 << 0 << getOpenMPClauseNameForDiag(OMPC_aligned) << ERange;
21217 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
21218 << getOpenMPClauseNameForDiag(OMPC_aligned);
21219 continue;
21220 }
21221
21222 DeclRefExpr *Ref = nullptr;
21223 if (!VD && isOpenMPCapturedDecl(D))
21224 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
21225 Vars.push_back(SemaRef
21226 .DefaultFunctionArrayConversion(
21227 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
21228 .get());
21229 }
21230
21231 // OpenMP [2.8.1, simd construct, Description]
21232 // The parameter of the aligned clause, alignment, must be a constant
21233 // positive integer expression.
21234 // If no optional parameter is specified, implementation-defined default
21235 // alignments for SIMD instructions on the target platforms are assumed.
21236 if (Alignment != nullptr) {
21237 ExprResult AlignResult =
21238 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
21239 if (AlignResult.isInvalid())
21240 return nullptr;
21241 Alignment = AlignResult.get();
21242 }
21243 if (Vars.empty())
21244 return nullptr;
21245
21246 return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc,
21247 ColonLoc, EndLoc, Vars, Alignment);
21248}
21249
21251 SourceLocation StartLoc,
21252 SourceLocation LParenLoc,
21253 SourceLocation EndLoc) {
21255 SmallVector<Expr *, 8> SrcExprs;
21256 SmallVector<Expr *, 8> DstExprs;
21257 SmallVector<Expr *, 8> AssignmentOps;
21258 for (Expr *RefExpr : VarList) {
21259 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
21260 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21261 // It will be analyzed later.
21262 Vars.push_back(RefExpr);
21263 SrcExprs.push_back(nullptr);
21264 DstExprs.push_back(nullptr);
21265 AssignmentOps.push_back(nullptr);
21266 continue;
21267 }
21268
21269 SourceLocation ELoc = RefExpr->getExprLoc();
21270 // OpenMP [2.1, C/C++]
21271 // A list item is a variable name.
21272 // OpenMP [2.14.4.1, Restrictions, p.1]
21273 // A list item that appears in a copyin clause must be threadprivate.
21274 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
21275 if (!DE || !isa<VarDecl>(DE->getDecl())) {
21276 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
21277 << 0 << RefExpr->getSourceRange();
21278 continue;
21279 }
21280
21281 Decl *D = DE->getDecl();
21282 auto *VD = cast<VarDecl>(D);
21283
21284 QualType Type = VD->getType();
21286 // It will be analyzed later.
21287 Vars.push_back(DE);
21288 SrcExprs.push_back(nullptr);
21289 DstExprs.push_back(nullptr);
21290 AssignmentOps.push_back(nullptr);
21291 continue;
21292 }
21293
21294 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
21295 // A list item that appears in a copyin clause must be threadprivate.
21296 if (!DSAStack->isThreadPrivate(VD)) {
21297 unsigned OMPVersion = getLangOpts().OpenMP;
21298 Diag(ELoc, diag::err_omp_required_access)
21299 << getOpenMPClauseNameForDiag(OMPC_copyin)
21300 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion);
21301 continue;
21302 }
21303
21304 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
21305 // A variable of class type (or array thereof) that appears in a
21306 // copyin clause requires an accessible, unambiguous copy assignment
21307 // operator for the class type.
21308 QualType ElemType =
21310 VarDecl *SrcVD =
21311 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
21312 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
21313 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
21314 SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
21315 VarDecl *DstVD =
21316 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst",
21317 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
21318 DeclRefExpr *PseudoDstExpr =
21319 buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc());
21320 // For arrays generate assignment operation for single element and replace
21321 // it by the original array element in CodeGen.
21322 ExprResult AssignmentOp =
21323 SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
21324 PseudoDstExpr, PseudoSrcExpr);
21325 if (AssignmentOp.isInvalid())
21326 continue;
21327 AssignmentOp =
21328 SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
21329 /*DiscardedValue=*/false);
21330 if (AssignmentOp.isInvalid())
21331 continue;
21332
21333 DSAStack->addDSA(VD, DE, OMPC_copyin);
21334 Vars.push_back(DE);
21335 SrcExprs.push_back(PseudoSrcExpr);
21336 DstExprs.push_back(PseudoDstExpr);
21337 AssignmentOps.push_back(AssignmentOp.get());
21338 }
21339
21340 if (Vars.empty())
21341 return nullptr;
21342
21343 return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21344 Vars, SrcExprs, DstExprs, AssignmentOps);
21345}
21346
21348 SourceLocation StartLoc,
21349 SourceLocation LParenLoc,
21350 SourceLocation EndLoc) {
21352 SmallVector<Expr *, 8> SrcExprs;
21353 SmallVector<Expr *, 8> DstExprs;
21354 SmallVector<Expr *, 8> AssignmentOps;
21355 for (Expr *RefExpr : VarList) {
21356 assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");
21357 SourceLocation ELoc;
21358 SourceRange ERange;
21359 Expr *SimpleRefExpr = RefExpr;
21360 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21361 if (Res.second) {
21362 // It will be analyzed later.
21363 Vars.push_back(RefExpr);
21364 SrcExprs.push_back(nullptr);
21365 DstExprs.push_back(nullptr);
21366 AssignmentOps.push_back(nullptr);
21367 }
21368 ValueDecl *D = Res.first;
21369 if (!D)
21370 continue;
21371
21372 QualType Type = D->getType();
21373 auto *VD = dyn_cast<VarDecl>(D);
21374
21375 // OpenMP [2.14.4.2, Restrictions, p.2]
21376 // A list item that appears in a copyprivate clause may not appear in a
21377 // private or firstprivate clause on the single construct.
21378 if (!VD || !DSAStack->isThreadPrivate(VD)) {
21379 DSAStackTy::DSAVarData DVar =
21380 DSAStack->getTopDSA(D, /*FromParent=*/false);
21381 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
21382 DVar.RefExpr) {
21383 Diag(ELoc, diag::err_omp_wrong_dsa)
21384 << getOpenMPClauseNameForDiag(DVar.CKind)
21385 << getOpenMPClauseNameForDiag(OMPC_copyprivate);
21387 continue;
21388 }
21389
21390 // OpenMP [2.11.4.2, Restrictions, p.1]
21391 // All list items that appear in a copyprivate clause must be either
21392 // threadprivate or private in the enclosing context.
21393 if (DVar.CKind == OMPC_unknown) {
21394 DVar = DSAStack->getImplicitDSA(D, false);
21395 if (DVar.CKind == OMPC_shared) {
21396 Diag(ELoc, diag::err_omp_required_access)
21397 << getOpenMPClauseNameForDiag(OMPC_copyprivate)
21398 << "threadprivate or private in the enclosing context";
21400 continue;
21401 }
21402 }
21403 }
21404
21405 // Variably modified types are not supported.
21407 unsigned OMPVersion = getLangOpts().OpenMP;
21408 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
21409 << getOpenMPClauseNameForDiag(OMPC_copyprivate) << Type
21410 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
21411 OMPVersion);
21412 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21414 Diag(D->getLocation(),
21415 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21416 << D;
21417 continue;
21418 }
21419
21420 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
21421 // A variable of class type (or array thereof) that appears in a
21422 // copyin clause requires an accessible, unambiguous copy assignment
21423 // operator for the class type.
21425 .getBaseElementType(Type.getNonReferenceType())
21427 VarDecl *SrcVD =
21428 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
21429 D->hasAttrs() ? &D->getAttrs() : nullptr);
21430 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc);
21431 VarDecl *DstVD =
21432 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
21433 D->hasAttrs() ? &D->getAttrs() : nullptr);
21434 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
21435 ExprResult AssignmentOp = SemaRef.BuildBinOp(
21436 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
21437 if (AssignmentOp.isInvalid())
21438 continue;
21439 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
21440 /*DiscardedValue=*/false);
21441 if (AssignmentOp.isInvalid())
21442 continue;
21443
21444 // No need to mark vars as copyprivate, they are already threadprivate or
21445 // implicitly private.
21446 assert(VD || isOpenMPCapturedDecl(D));
21447 Vars.push_back(
21448 VD ? RefExpr->IgnoreParens()
21449 : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false));
21450 SrcExprs.push_back(PseudoSrcExpr);
21451 DstExprs.push_back(PseudoDstExpr);
21452 AssignmentOps.push_back(AssignmentOp.get());
21453 }
21454
21455 if (Vars.empty())
21456 return nullptr;
21457
21458 return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc,
21459 EndLoc, Vars, SrcExprs, DstExprs,
21460 AssignmentOps);
21461}
21462
21464 SourceLocation StartLoc,
21465 SourceLocation LParenLoc,
21466 SourceLocation EndLoc) {
21467 if (VarList.empty())
21468 return nullptr;
21469
21470 return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21471 VarList);
21472}
21473
21474/// Tries to find omp_depend_t. type.
21475static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
21476 bool Diagnose = true) {
21477 QualType OMPDependT = Stack->getOMPDependT();
21478 if (!OMPDependT.isNull())
21479 return true;
21480 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
21481 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
21482 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
21483 if (Diagnose)
21484 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
21485 return false;
21486 }
21487 Stack->setOMPDependT(PT.get());
21488 return true;
21489}
21490
21492 SourceLocation StartLoc,
21493 SourceLocation LParenLoc,
21494 SourceLocation EndLoc) {
21495 if (!Depobj)
21496 return nullptr;
21497
21498 bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack);
21499
21500 // OpenMP 5.0, 2.17.10.1 depobj Construct
21501 // depobj is an lvalue expression of type omp_depend_t.
21502 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
21503 !Depobj->isInstantiationDependent() &&
21505 (OMPDependTFound && !getASTContext().typesAreCompatible(
21506 DSAStack->getOMPDependT(), Depobj->getType(),
21507 /*CompareUnqualified=*/true))) {
21508 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21509 << 0 << Depobj->getType() << Depobj->getSourceRange();
21510 }
21511
21512 if (!Depobj->isLValue()) {
21513 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21514 << 1 << Depobj->getSourceRange();
21515 }
21516
21517 return OMPDepobjClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21518 Depobj);
21519}
21520
21521namespace {
21522// Utility struct that gathers the related info for doacross clause.
21523struct DoacrossDataInfoTy {
21524 // The list of expressions.
21526 // The OperatorOffset for doacross loop.
21527 DSAStackTy::OperatorOffsetTy OpsOffs;
21528 // The depended loop count.
21529 llvm::APSInt TotalDepCount;
21530};
21531} // namespace
21532static DoacrossDataInfoTy
21534 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
21535 SourceLocation EndLoc) {
21536
21538 DSAStackTy::OperatorOffsetTy OpsOffs;
21539 llvm::APSInt DepCounter(/*BitWidth=*/32);
21540 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
21541
21542 if (const Expr *OrderedCountExpr =
21543 Stack->getParentOrderedRegionParam().first) {
21544 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
21545 TotalDepCount.setIsUnsigned(/*Val=*/true);
21546 }
21547
21548 for (Expr *RefExpr : VarList) {
21549 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
21550 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21551 // It will be analyzed later.
21552 Vars.push_back(RefExpr);
21553 continue;
21554 }
21555
21556 SourceLocation ELoc = RefExpr->getExprLoc();
21557 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
21558 if (!IsSource) {
21559 if (Stack->getParentOrderedRegionParam().first &&
21560 DepCounter >= TotalDepCount) {
21561 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
21562 continue;
21563 }
21564 ++DepCounter;
21565 // OpenMP [2.13.9, Summary]
21566 // depend(dependence-type : vec), where dependence-type is:
21567 // 'sink' and where vec is the iteration vector, which has the form:
21568 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
21569 // where n is the value specified by the ordered clause in the loop
21570 // directive, xi denotes the loop iteration variable of the i-th nested
21571 // loop associated with the loop directive, and di is a constant
21572 // non-negative integer.
21573 if (SemaRef.CurContext->isDependentContext()) {
21574 // It will be analyzed later.
21575 Vars.push_back(RefExpr);
21576 continue;
21577 }
21578 SimpleExpr = SimpleExpr->IgnoreImplicit();
21580 SourceLocation OOLoc;
21581 Expr *LHS = SimpleExpr;
21582 Expr *RHS = nullptr;
21583 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
21584 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
21585 OOLoc = BO->getOperatorLoc();
21586 LHS = BO->getLHS()->IgnoreParenImpCasts();
21587 RHS = BO->getRHS()->IgnoreParenImpCasts();
21588 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
21589 OOK = OCE->getOperator();
21590 OOLoc = OCE->getOperatorLoc();
21591 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
21592 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
21593 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
21594 OOK = MCE->getMethodDecl()
21595 ->getNameInfo()
21596 .getName()
21597 .getCXXOverloadedOperator();
21598 OOLoc = MCE->getCallee()->getExprLoc();
21599 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
21600 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
21601 }
21602 SourceLocation ELoc;
21603 SourceRange ERange;
21604 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
21605 if (Res.second) {
21606 // It will be analyzed later.
21607 Vars.push_back(RefExpr);
21608 }
21609 ValueDecl *D = Res.first;
21610 if (!D)
21611 continue;
21612
21613 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
21614 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
21615 continue;
21616 }
21617 if (RHS) {
21618 ExprResult RHSRes =
21620 RHS, OMPC_depend, /*StrictlyPositive=*/false);
21621 if (RHSRes.isInvalid())
21622 continue;
21623 }
21624 if (!SemaRef.CurContext->isDependentContext() &&
21625 Stack->getParentOrderedRegionParam().first &&
21626 DepCounter != Stack->isParentLoopControlVariable(D).first) {
21627 const ValueDecl *VD =
21628 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
21629 if (VD)
21630 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21631 << 1 << VD;
21632 else
21633 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21634 << 0;
21635 continue;
21636 }
21637 OpsOffs.emplace_back(RHS, OOK);
21638 }
21639 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21640 }
21641 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
21642 TotalDepCount > VarList.size() &&
21643 Stack->getParentOrderedRegionParam().first &&
21644 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
21645 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
21646 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
21647 }
21648 return {Vars, OpsOffs, TotalDepCount};
21649}
21650
21652 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
21653 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
21654 SourceLocation EndLoc) {
21655 OpenMPDependClauseKind DepKind = Data.DepKind;
21656 SourceLocation DepLoc = Data.DepLoc;
21657 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
21658 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
21659 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21660 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_depend);
21661 return nullptr;
21662 }
21663 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
21664 DepKind == OMPC_DEPEND_mutexinoutset) {
21665 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
21666 return nullptr;
21667 }
21668 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
21669 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21670 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
21671 DepKind == OMPC_DEPEND_sink ||
21672 ((getLangOpts().OpenMP < 50 ||
21673 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21674 DepKind == OMPC_DEPEND_depobj))) {
21675 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
21676 OMPC_DEPEND_outallmemory,
21677 OMPC_DEPEND_inoutallmemory};
21678 if (getLangOpts().OpenMP < 50 ||
21679 DSAStack->getCurrentDirective() == OMPD_depobj)
21680 Except.push_back(OMPC_DEPEND_depobj);
21681 if (getLangOpts().OpenMP < 51)
21682 Except.push_back(OMPC_DEPEND_inoutset);
21683 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
21684 ? "depend modifier(iterator) or "
21685 : "";
21686 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21687 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
21688 /*Last=*/OMPC_DEPEND_unknown,
21689 Except)
21690 << getOpenMPClauseNameForDiag(OMPC_depend);
21691 return nullptr;
21692 }
21693 if (DepModifier &&
21694 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
21695 Diag(DepModifier->getExprLoc(),
21696 diag::err_omp_depend_sink_source_with_modifier);
21697 return nullptr;
21698 }
21699 if (DepModifier &&
21700 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
21701 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
21702
21704 DSAStackTy::OperatorOffsetTy OpsOffs;
21705 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
21706
21707 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
21708 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
21709 SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
21710 Vars = VarOffset.Vars;
21711 OpsOffs = VarOffset.OpsOffs;
21712 TotalDepCount = VarOffset.TotalDepCount;
21713 } else {
21714 for (Expr *RefExpr : VarList) {
21715 assert(RefExpr && "NULL expr in OpenMP depend clause.");
21716 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21717 // It will be analyzed later.
21718 Vars.push_back(RefExpr);
21719 continue;
21720 }
21721
21722 SourceLocation ELoc = RefExpr->getExprLoc();
21723 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
21724 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
21725 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
21726 if (OMPDependTFound)
21727 OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack,
21728 DepKind == OMPC_DEPEND_depobj);
21729 if (DepKind == OMPC_DEPEND_depobj) {
21730 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21731 // List items used in depend clauses with the depobj dependence type
21732 // must be expressions of the omp_depend_t type.
21733 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21734 !RefExpr->isInstantiationDependent() &&
21735 !RefExpr->containsUnexpandedParameterPack() &&
21736 (OMPDependTFound &&
21737 !getASTContext().hasSameUnqualifiedType(
21738 DSAStack->getOMPDependT(), RefExpr->getType()))) {
21739 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21740 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
21741 continue;
21742 }
21743 if (!RefExpr->isLValue()) {
21744 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21745 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
21746 continue;
21747 }
21748 } else {
21749 // OpenMP 5.0 [2.17.11, Restrictions]
21750 // List items used in depend clauses cannot be zero-length array
21751 // sections.
21752 QualType ExprTy = RefExpr->getType().getNonReferenceType();
21753 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
21754 if (OASE) {
21755 QualType BaseType =
21757 if (BaseType.isNull())
21758 return nullptr;
21759 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21760 ExprTy = ATy->getElementType();
21761 else
21762 ExprTy = BaseType->getPointeeType();
21763 if (BaseType.isNull() || ExprTy.isNull())
21764 return nullptr;
21765 ExprTy = ExprTy.getNonReferenceType();
21766 const Expr *Length = OASE->getLength();
21768 if (Length && !Length->isValueDependent() &&
21769 Length->EvaluateAsInt(Result, getASTContext()) &&
21770 Result.Val.getInt().isZero()) {
21771 Diag(ELoc,
21772 diag::err_omp_depend_zero_length_array_section_not_allowed)
21773 << SimpleExpr->getSourceRange();
21774 continue;
21775 }
21776 }
21777
21778 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21779 // List items used in depend clauses with the in, out, inout,
21780 // inoutset, or mutexinoutset dependence types cannot be
21781 // expressions of the omp_depend_t type.
21782 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21783 !RefExpr->isInstantiationDependent() &&
21784 !RefExpr->containsUnexpandedParameterPack() &&
21785 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
21786 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
21787 ExprTy.getTypePtr()))) {
21788 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21789 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21790 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21791 << RefExpr->getSourceRange();
21792 continue;
21793 }
21794
21795 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
21796 if (ASE && !ASE->getBase()->isTypeDependent() &&
21797 !ASE->getBase()
21798 ->getType()
21799 .getNonReferenceType()
21800 ->isPointerType() &&
21801 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
21802 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21803 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21804 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21805 << RefExpr->getSourceRange();
21806 continue;
21807 }
21808
21809 ExprResult Res;
21810 {
21812 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
21813 RefExpr->IgnoreParenImpCasts());
21814 }
21815 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
21817 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21818 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21819 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21820 << RefExpr->getSourceRange();
21821 continue;
21822 }
21823 }
21824 }
21825 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21826 }
21827 }
21828
21829 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
21830 DepKind != OMPC_DEPEND_outallmemory &&
21831 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
21832 return nullptr;
21833
21834 auto *C = OMPDependClause::Create(
21835 getASTContext(), StartLoc, LParenLoc, EndLoc,
21836 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
21837 TotalDepCount.getZExtValue());
21838 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
21839 DSAStack->isParentOrderedRegion())
21840 DSAStack->addDoacrossDependClause(C, OpsOffs);
21841 return C;
21842}
21843
21846 SourceLocation LParenLoc, SourceLocation ModifierLoc,
21847 SourceLocation EndLoc) {
21848 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
21849 "Unexpected device modifier in OpenMP < 50.");
21850
21851 bool ErrorFound = false;
21852 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
21853 std::string Values =
21854 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
21855 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21856 << Values << getOpenMPClauseNameForDiag(OMPC_device);
21857 ErrorFound = true;
21858 }
21859
21860 Expr *ValExpr = Device;
21861 Stmt *HelperValStmt = nullptr;
21862
21863 // OpenMP [2.9.1, Restrictions]
21864 // The device expression must evaluate to a non-negative integer value.
21865 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device,
21866 /*StrictlyPositive=*/false) ||
21867 ErrorFound;
21868 if (ErrorFound)
21869 return nullptr;
21870
21871 // OpenMP 5.0 [2.12.5, Restrictions]
21872 // In case of ancestor device-modifier, a requires directive with
21873 // the reverse_offload clause must be specified.
21874 if (Modifier == OMPC_DEVICE_ancestor) {
21875 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
21876 SemaRef.targetDiag(
21877 StartLoc,
21878 diag::err_omp_device_ancestor_without_requires_reverse_offload);
21879 ErrorFound = true;
21880 }
21881 }
21882
21883 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
21884 OpenMPDirectiveKind CaptureRegion =
21885 getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP);
21886 if (CaptureRegion != OMPD_unknown &&
21887 !SemaRef.CurContext->isDependentContext()) {
21888 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
21889 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21890 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
21891 HelperValStmt = buildPreInits(getASTContext(), Captures);
21892 }
21893
21894 return new (getASTContext())
21895 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
21896 LParenLoc, ModifierLoc, EndLoc);
21897}
21898
21900 DSAStackTy *Stack, QualType QTy,
21901 bool FullCheck = true) {
21902 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
21903 return false;
21904 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
21905 !QTy.isTriviallyCopyableType(SemaRef.Context))
21906 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
21907 return true;
21908}
21909
21910/// Return true if it can be proven that the provided array expression
21911/// (array section or array subscript) does NOT specify the whole size of the
21912/// array whose base type is \a BaseQTy.
21914 const Expr *E,
21915 QualType BaseQTy) {
21916 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21917
21918 // If this is an array subscript, it refers to the whole size if the size of
21919 // the dimension is constant and equals 1. Also, an array section assumes the
21920 // format of an array subscript if no colon is used.
21921 if (isa<ArraySubscriptExpr>(E) ||
21922 (OASE && OASE->getColonLocFirst().isInvalid())) {
21923 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21924 return ATy->getSExtSize() != 1;
21925 // Size can't be evaluated statically.
21926 return false;
21927 }
21928
21929 assert(OASE && "Expecting array section if not an array subscript.");
21930 const Expr *LowerBound = OASE->getLowerBound();
21931 const Expr *Length = OASE->getLength();
21932
21933 // If there is a lower bound that does not evaluates to zero, we are not
21934 // covering the whole dimension.
21935 if (LowerBound) {
21936 Expr::EvalResult Result;
21937 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
21938 return false; // Can't get the integer value as a constant.
21939
21940 llvm::APSInt ConstLowerBound = Result.Val.getInt();
21941 if (ConstLowerBound.getSExtValue())
21942 return true;
21943 }
21944
21945 // If we don't have a length we covering the whole dimension.
21946 if (!Length)
21947 return false;
21948
21949 // If the base is a pointer, we don't have a way to get the size of the
21950 // pointee.
21951 if (BaseQTy->isPointerType())
21952 return false;
21953
21954 // We can only check if the length is the same as the size of the dimension
21955 // if we have a constant array.
21956 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
21957 if (!CATy)
21958 return false;
21959
21960 Expr::EvalResult Result;
21961 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21962 return false; // Can't get the integer value as a constant.
21963
21964 llvm::APSInt ConstLength = Result.Val.getInt();
21965 return CATy->getSExtSize() != ConstLength.getSExtValue();
21966}
21967
21968// Return true if it can be proven that the provided array expression (array
21969// section or array subscript) does NOT specify a single element of the array
21970// whose base type is \a BaseQTy.
21972 const Expr *E,
21973 QualType BaseQTy) {
21974 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21975
21976 // An array subscript always refer to a single element. Also, an array section
21977 // assumes the format of an array subscript if no colon is used.
21978 if (isa<ArraySubscriptExpr>(E) ||
21979 (OASE && OASE->getColonLocFirst().isInvalid()))
21980 return false;
21981
21982 assert(OASE && "Expecting array section if not an array subscript.");
21983 const Expr *Length = OASE->getLength();
21984
21985 // If we don't have a length we have to check if the array has unitary size
21986 // for this dimension. Also, we should always expect a length if the base type
21987 // is pointer.
21988 if (!Length) {
21989 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21990 return ATy->getSExtSize() != 1;
21991 // We cannot assume anything.
21992 return false;
21993 }
21994
21995 // Check if the length evaluates to 1.
21996 Expr::EvalResult Result;
21997 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21998 return false; // Can't get the integer value as a constant.
21999
22000 llvm::APSInt ConstLength = Result.Val.getInt();
22001 return ConstLength.getSExtValue() != 1;
22002}
22003
22004// The base of elements of list in a map clause have to be either:
22005// - a reference to variable or field.
22006// - a member expression.
22007// - an array expression.
22008//
22009// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
22010// reference to 'r'.
22011//
22012// If we have:
22013//
22014// struct SS {
22015// Bla S;
22016// foo() {
22017// #pragma omp target map (S.Arr[:12]);
22018// }
22019// }
22020//
22021// We want to retrieve the member expression 'this->S';
22022
22023// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
22024// If a list item is an array section, it must specify contiguous storage.
22025//
22026// For this restriction it is sufficient that we make sure only references
22027// to variables or fields and array expressions, and that no array sections
22028// exist except in the rightmost expression (unless they cover the whole
22029// dimension of the array). E.g. these would be invalid:
22030//
22031// r.ArrS[3:5].Arr[6:7]
22032//
22033// r.ArrS[3:5].x
22034//
22035// but these would be valid:
22036// r.ArrS[3].Arr[6:7]
22037//
22038// r.ArrS[3].x
22039namespace {
22040class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
22041 Sema &SemaRef;
22042 OpenMPClauseKind CKind = OMPC_unknown;
22043 OpenMPDirectiveKind DKind = OMPD_unknown;
22045 bool IsNonContiguous = false;
22046 bool NoDiagnose = false;
22047 const Expr *RelevantExpr = nullptr;
22048 bool AllowUnitySizeArraySection = true;
22049 bool AllowWholeSizeArraySection = true;
22050 bool AllowAnotherPtr = true;
22051 SourceLocation ELoc;
22052 SourceRange ERange;
22053
22054 void emitErrorMsg() {
22055 // If nothing else worked, this is not a valid map clause expression.
22056 if (SemaRef.getLangOpts().OpenMP < 50) {
22057 SemaRef.Diag(ELoc,
22058 diag::err_omp_expected_named_var_member_or_array_expression)
22059 << ERange;
22060 } else {
22061 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22062 << getOpenMPClauseNameForDiag(CKind) << ERange;
22063 }
22064 }
22065
22066public:
22067 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
22068 if (!isa<VarDecl>(DRE->getDecl())) {
22069 emitErrorMsg();
22070 return false;
22071 }
22072 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22073 RelevantExpr = DRE;
22074 // Record the component.
22075 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
22076 return true;
22077 }
22078
22079 bool VisitMemberExpr(MemberExpr *ME) {
22080 Expr *E = ME;
22081 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
22082
22083 if (isa<CXXThisExpr>(BaseE)) {
22084 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22085 // We found a base expression: this->Val.
22086 RelevantExpr = ME;
22087 } else {
22088 E = BaseE;
22089 }
22090
22091 if (!isa<FieldDecl>(ME->getMemberDecl())) {
22092 if (!NoDiagnose) {
22093 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
22094 << ME->getSourceRange();
22095 return false;
22096 }
22097 if (RelevantExpr)
22098 return false;
22099 return Visit(E);
22100 }
22101
22102 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
22103
22104 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
22105 // A bit-field cannot appear in a map clause.
22106 //
22107 if (FD->isBitField()) {
22108 if (!NoDiagnose) {
22109 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
22110 << ME->getSourceRange() << getOpenMPClauseNameForDiag(CKind);
22111 return false;
22112 }
22113 if (RelevantExpr)
22114 return false;
22115 return Visit(E);
22116 }
22117
22118 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22119 // If the type of a list item is a reference to a type T then the type
22120 // will be considered to be T for all purposes of this clause.
22121 QualType CurType = BaseE->getType().getNonReferenceType();
22122
22123 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
22124 // A list item cannot be a variable that is a member of a structure with
22125 // a union type.
22126 //
22127 if (CurType->isUnionType()) {
22128 if (!NoDiagnose) {
22129 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
22130 << ME->getSourceRange();
22131 return false;
22132 }
22133 return RelevantExpr || Visit(E);
22134 }
22135
22136 // If we got a member expression, we should not expect any array section
22137 // before that:
22138 //
22139 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
22140 // If a list item is an element of a structure, only the rightmost symbol
22141 // of the variable reference can be an array section.
22142 //
22143 AllowUnitySizeArraySection = false;
22144 AllowWholeSizeArraySection = false;
22145
22146 // Record the component.
22147 Components.emplace_back(ME, FD, IsNonContiguous);
22148 return RelevantExpr || Visit(E);
22149 }
22150
22151 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
22152 Expr *E = AE->getBase()->IgnoreParenImpCasts();
22153
22154 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
22155 if (!NoDiagnose) {
22156 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22157 << 0 << AE->getSourceRange();
22158 return false;
22159 }
22160 return RelevantExpr || Visit(E);
22161 }
22162
22163 // If we got an array subscript that express the whole dimension we
22164 // can have any array expressions before. If it only expressing part of
22165 // the dimension, we can only have unitary-size array expressions.
22167 AllowWholeSizeArraySection = false;
22168
22169 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
22170 Expr::EvalResult Result;
22171 if (!AE->getIdx()->isValueDependent() &&
22172 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
22173 !Result.Val.getInt().isZero()) {
22174 SemaRef.Diag(AE->getIdx()->getExprLoc(),
22175 diag::err_omp_invalid_map_this_expr);
22176 SemaRef.Diag(AE->getIdx()->getExprLoc(),
22177 diag::note_omp_invalid_subscript_on_this_ptr_map);
22178 }
22179 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22180 RelevantExpr = TE;
22181 }
22182
22183 // Record the component - we don't have any declaration associated.
22184 Components.emplace_back(AE, nullptr, IsNonContiguous);
22185
22186 return RelevantExpr || Visit(E);
22187 }
22188
22189 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
22190 // After OMP 5.0 Array section in reduction clause will be implicitly
22191 // mapped
22192 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
22193 "Array sections cannot be implicitly mapped.");
22194 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
22195 QualType CurType =
22197
22198 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22199 // If the type of a list item is a reference to a type T then the type
22200 // will be considered to be T for all purposes of this clause.
22201 if (CurType->isReferenceType())
22202 CurType = CurType->getPointeeType();
22203
22204 bool IsPointer = CurType->isAnyPointerType();
22205
22206 if (!IsPointer && !CurType->isArrayType()) {
22207 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22208 << 0 << OASE->getSourceRange();
22209 return false;
22210 }
22211
22212 bool NotWhole =
22213 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
22214 bool NotUnity =
22215 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
22216
22217 if (AllowWholeSizeArraySection) {
22218 // Any array section is currently allowed. Allowing a whole size array
22219 // section implies allowing a unity array section as well.
22220 //
22221 // If this array section refers to the whole dimension we can still
22222 // accept other array sections before this one, except if the base is a
22223 // pointer. Otherwise, only unitary sections are accepted.
22224 if (NotWhole || IsPointer)
22225 AllowWholeSizeArraySection = false;
22226 } else if (DKind == OMPD_target_update &&
22227 SemaRef.getLangOpts().OpenMP >= 50) {
22228 if (IsPointer && !AllowAnotherPtr)
22229 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
22230 << /*array of unknown bound */ 1;
22231 else
22232 IsNonContiguous = true;
22233 } else if (AllowUnitySizeArraySection && NotUnity) {
22234 // A unity or whole array section is not allowed and that is not
22235 // compatible with the properties of the current array section.
22236 if (NoDiagnose)
22237 return false;
22238 SemaRef.Diag(ELoc,
22239 diag::err_array_section_does_not_specify_contiguous_storage)
22240 << OASE->getSourceRange();
22241 return false;
22242 }
22243
22244 if (IsPointer)
22245 AllowAnotherPtr = false;
22246
22247 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
22248 Expr::EvalResult ResultR;
22249 Expr::EvalResult ResultL;
22250 if (!OASE->getLength()->isValueDependent() &&
22251 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
22252 !ResultR.Val.getInt().isOne()) {
22253 SemaRef.Diag(OASE->getLength()->getExprLoc(),
22254 diag::err_omp_invalid_map_this_expr);
22255 SemaRef.Diag(OASE->getLength()->getExprLoc(),
22256 diag::note_omp_invalid_length_on_this_ptr_mapping);
22257 }
22258 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
22259 OASE->getLowerBound()->EvaluateAsInt(ResultL,
22260 SemaRef.getASTContext()) &&
22261 !ResultL.Val.getInt().isZero()) {
22262 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
22263 diag::err_omp_invalid_map_this_expr);
22264 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
22265 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
22266 }
22267 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22268 RelevantExpr = TE;
22269 }
22270
22271 // Record the component - we don't have any declaration associated.
22272 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
22273 return RelevantExpr || Visit(E);
22274 }
22275 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
22276 Expr *Base = E->getBase();
22277
22278 // Record the component - we don't have any declaration associated.
22279 Components.emplace_back(E, nullptr, IsNonContiguous);
22280
22281 return Visit(Base->IgnoreParenImpCasts());
22282 }
22283
22284 bool VisitUnaryOperator(UnaryOperator *UO) {
22285 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
22286 UO->getOpcode() != UO_Deref) {
22287 emitErrorMsg();
22288 return false;
22289 }
22290 if (!RelevantExpr) {
22291 // Record the component if haven't found base decl.
22292 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
22293 }
22294 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
22295 }
22296 bool VisitBinaryOperator(BinaryOperator *BO) {
22297 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
22298 emitErrorMsg();
22299 return false;
22300 }
22301
22302 // Pointer arithmetic is the only thing we expect to happen here so after we
22303 // make sure the binary operator is a pointer type, the only thing we need
22304 // to do is to visit the subtree that has the same type as root (so that we
22305 // know the other subtree is just an offset)
22306 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
22307 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
22308 Components.emplace_back(BO, nullptr, false);
22309 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
22310 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
22311 "Either LHS or RHS have base decl inside");
22312 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
22313 return RelevantExpr || Visit(LE);
22314 return RelevantExpr || Visit(RE);
22315 }
22316 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
22317 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22318 RelevantExpr = CTE;
22319 Components.emplace_back(CTE, nullptr, IsNonContiguous);
22320 return true;
22321 }
22322 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
22323 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22324 Components.emplace_back(COCE, nullptr, IsNonContiguous);
22325 return true;
22326 }
22327 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
22328 Expr *Source = E->getSourceExpr();
22329 if (!Source) {
22330 emitErrorMsg();
22331 return false;
22332 }
22333 return Visit(Source);
22334 }
22335 bool VisitStmt(Stmt *) {
22336 emitErrorMsg();
22337 return false;
22338 }
22339 const Expr *getFoundBase() const { return RelevantExpr; }
22340 explicit MapBaseChecker(
22341 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
22343 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
22344 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
22345 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
22346};
22347} // namespace
22348
22349/// Return the expression of the base of the mappable expression or null if it
22350/// cannot be determined and do all the necessary checks to see if the
22351/// expression is valid as a standalone mappable expression. In the process,
22352/// record all the components of the expression.
22354 Sema &SemaRef, Expr *E,
22356 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
22357 SourceLocation ELoc = E->getExprLoc();
22358 SourceRange ERange = E->getSourceRange();
22359 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
22360 ERange);
22361 if (Checker.Visit(E->IgnoreParens())) {
22362 // Check if the highest dimension array section has length specified
22363 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
22364 (CKind == OMPC_to || CKind == OMPC_from)) {
22365 auto CI = CurComponents.rbegin();
22366 auto CE = CurComponents.rend();
22367 for (; CI != CE; ++CI) {
22368 const auto *OASE =
22369 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
22370 if (!OASE)
22371 continue;
22372 if (OASE && OASE->getLength())
22373 break;
22374 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
22375 << ERange;
22376 }
22377 }
22378 return Checker.getFoundBase();
22379 }
22380 return nullptr;
22381}
22382
22383// Return true if expression E associated with value VD has conflicts with other
22384// map information.
22386 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
22387 bool CurrentRegionOnly,
22389 OpenMPClauseKind CKind) {
22390 assert(VD && E);
22391 SourceLocation ELoc = E->getExprLoc();
22392 SourceRange ERange = E->getSourceRange();
22393
22394 // In order to easily check the conflicts we need to match each component of
22395 // the expression under test with the components of the expressions that are
22396 // already in the stack.
22397
22398 assert(!CurComponents.empty() && "Map clause expression with no components!");
22399 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
22400 "Map clause expression with unexpected base!");
22401
22402 // Variables to help detecting enclosing problems in data environment nests.
22403 bool IsEnclosedByDataEnvironmentExpr = false;
22404 const Expr *EnclosingExpr = nullptr;
22405
22406 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
22407 VD, CurrentRegionOnly,
22408 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
22409 ERange, CKind, &EnclosingExpr,
22411 StackComponents,
22412 OpenMPClauseKind Kind) {
22413 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
22414 return false;
22415 assert(!StackComponents.empty() &&
22416 "Map clause expression with no components!");
22417 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
22418 "Map clause expression with unexpected base!");
22419 (void)VD;
22420
22421 // The whole expression in the stack.
22422 const Expr *RE = StackComponents.front().getAssociatedExpression();
22423
22424 // Expressions must start from the same base. Here we detect at which
22425 // point both expressions diverge from each other and see if we can
22426 // detect if the memory referred to both expressions is contiguous and
22427 // do not overlap.
22428 auto CI = CurComponents.rbegin();
22429 auto CE = CurComponents.rend();
22430 auto SI = StackComponents.rbegin();
22431 auto SE = StackComponents.rend();
22432 for (; CI != CE && SI != SE; ++CI, ++SI) {
22433
22434 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
22435 // At most one list item can be an array item derived from a given
22436 // variable in map clauses of the same construct.
22437 if (CurrentRegionOnly &&
22438 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
22439 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
22440 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
22441 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
22442 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
22443 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
22444 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
22445 diag::err_omp_multiple_array_items_in_map_clause)
22446 << CI->getAssociatedExpression()->getSourceRange();
22447 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
22448 diag::note_used_here)
22449 << SI->getAssociatedExpression()->getSourceRange();
22450 return true;
22451 }
22452
22453 // Do both expressions have the same kind?
22454 if (CI->getAssociatedExpression()->getStmtClass() !=
22455 SI->getAssociatedExpression()->getStmtClass())
22456 break;
22457
22458 // Are we dealing with different variables/fields?
22459 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
22460 break;
22461 }
22462 // Check if the extra components of the expressions in the enclosing
22463 // data environment are redundant for the current base declaration.
22464 // If they are, the maps completely overlap, which is legal.
22465 for (; SI != SE; ++SI) {
22466 QualType Type;
22467 if (const auto *ASE =
22468 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
22469 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
22470 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
22471 SI->getAssociatedExpression())) {
22472 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
22474 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
22475 SI->getAssociatedExpression())) {
22476 Type = OASE->getBase()->getType()->getPointeeType();
22477 }
22478 if (Type.isNull() || Type->isAnyPointerType() ||
22480 SemaRef, SI->getAssociatedExpression(), Type))
22481 break;
22482 }
22483
22484 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
22485 // List items of map clauses in the same construct must not share
22486 // original storage.
22487 //
22488 // If the expressions are exactly the same or one is a subset of the
22489 // other, it means they are sharing storage.
22490 if (CI == CE && SI == SE) {
22491 if (CurrentRegionOnly) {
22492 if (CKind == OMPC_map) {
22493 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22494 } else {
22495 assert(CKind == OMPC_to || CKind == OMPC_from);
22496 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22497 << ERange;
22498 }
22499 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22500 << RE->getSourceRange();
22501 return true;
22502 }
22503 // If we find the same expression in the enclosing data environment,
22504 // that is legal.
22505 IsEnclosedByDataEnvironmentExpr = true;
22506 return false;
22507 }
22508
22509 QualType DerivedType =
22510 std::prev(CI)->getAssociatedDeclaration()->getType();
22511 SourceLocation DerivedLoc =
22512 std::prev(CI)->getAssociatedExpression()->getExprLoc();
22513
22514 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22515 // If the type of a list item is a reference to a type T then the type
22516 // will be considered to be T for all purposes of this clause.
22517 DerivedType = DerivedType.getNonReferenceType();
22518
22519 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
22520 // A variable for which the type is pointer and an array section
22521 // derived from that variable must not appear as list items of map
22522 // clauses of the same construct.
22523 //
22524 // Also, cover one of the cases in:
22525 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
22526 // If any part of the original storage of a list item has corresponding
22527 // storage in the device data environment, all of the original storage
22528 // must have corresponding storage in the device data environment.
22529 //
22530 if (DerivedType->isAnyPointerType()) {
22531 if (CI == CE || SI == SE) {
22532 SemaRef.Diag(
22533 DerivedLoc,
22534 diag::err_omp_pointer_mapped_along_with_derived_section)
22535 << DerivedLoc;
22536 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22537 << RE->getSourceRange();
22538 return true;
22539 }
22540 if (CI->getAssociatedExpression()->getStmtClass() !=
22541 SI->getAssociatedExpression()->getStmtClass() ||
22542 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
22543 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
22544 assert(CI != CE && SI != SE);
22545 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
22546 << DerivedLoc;
22547 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22548 << RE->getSourceRange();
22549 return true;
22550 }
22551 }
22552
22553 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
22554 // List items of map clauses in the same construct must not share
22555 // original storage.
22556 //
22557 // An expression is a subset of the other.
22558 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
22559 if (CKind == OMPC_map) {
22560 if (CI != CE || SI != SE) {
22561 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
22562 // a pointer.
22563 auto Begin =
22564 CI != CE ? CurComponents.begin() : StackComponents.begin();
22565 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
22566 auto It = Begin;
22567 while (It != End && !It->getAssociatedDeclaration())
22568 std::advance(It, 1);
22569 assert(It != End &&
22570 "Expected at least one component with the declaration.");
22571 if (It != Begin && It->getAssociatedDeclaration()
22572 ->getType()
22573 .getCanonicalType()
22574 ->isAnyPointerType()) {
22575 IsEnclosedByDataEnvironmentExpr = false;
22576 EnclosingExpr = nullptr;
22577 return false;
22578 }
22579 }
22580 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22581 } else {
22582 assert(CKind == OMPC_to || CKind == OMPC_from);
22583 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22584 << ERange;
22585 }
22586 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22587 << RE->getSourceRange();
22588 return true;
22589 }
22590
22591 // The current expression uses the same base as other expression in the
22592 // data environment but does not contain it completely.
22593 if (!CurrentRegionOnly && SI != SE)
22594 EnclosingExpr = RE;
22595
22596 // The current expression is a subset of the expression in the data
22597 // environment.
22598 IsEnclosedByDataEnvironmentExpr |=
22599 (!CurrentRegionOnly && CI != CE && SI == SE);
22600
22601 return false;
22602 });
22603
22604 if (CurrentRegionOnly)
22605 return FoundError;
22606
22607 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
22608 // If any part of the original storage of a list item has corresponding
22609 // storage in the device data environment, all of the original storage must
22610 // have corresponding storage in the device data environment.
22611 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
22612 // If a list item is an element of a structure, and a different element of
22613 // the structure has a corresponding list item in the device data environment
22614 // prior to a task encountering the construct associated with the map clause,
22615 // then the list item must also have a corresponding list item in the device
22616 // data environment prior to the task encountering the construct.
22617 //
22618 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
22619 SemaRef.Diag(ELoc,
22620 diag::err_omp_original_storage_is_shared_and_does_not_contain)
22621 << ERange;
22622 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
22623 << EnclosingExpr->getSourceRange();
22624 return true;
22625 }
22626
22627 return FoundError;
22628}
22629
22630// Look up the user-defined mapper given the mapper name and mapped type, and
22631// build a reference to it.
22633 CXXScopeSpec &MapperIdScopeSpec,
22634 const DeclarationNameInfo &MapperId,
22635 QualType Type,
22636 Expr *UnresolvedMapper) {
22637 if (MapperIdScopeSpec.isInvalid())
22638 return ExprError();
22639 // Get the actual type for the array type.
22640 if (Type->isArrayType()) {
22641 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
22643 }
22644 // Find all user-defined mappers with the given MapperId.
22645 SmallVector<UnresolvedSet<8>, 4> Lookups;
22646 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
22647 Lookup.suppressDiagnostics();
22648 if (S) {
22649 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
22650 /*ObjectType=*/QualType())) {
22651 NamedDecl *D = Lookup.getRepresentativeDecl();
22652 while (S && !S->isDeclScope(D))
22653 S = S->getParent();
22654 if (S)
22655 S = S->getParent();
22656 Lookups.emplace_back();
22657 Lookups.back().append(Lookup.begin(), Lookup.end());
22658 Lookup.clear();
22659 }
22660 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
22661 // Extract the user-defined mappers with the given MapperId.
22662 Lookups.push_back(UnresolvedSet<8>());
22663 for (NamedDecl *D : ULE->decls()) {
22664 auto *DMD = cast<OMPDeclareMapperDecl>(D);
22665 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
22666 Lookups.back().addDecl(DMD);
22667 }
22668 }
22669 // Defer the lookup for dependent types. The results will be passed through
22670 // UnresolvedMapper on instantiation.
22671 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
22675 return !D->isInvalidDecl() &&
22676 (D->getType()->isDependentType() ||
22677 D->getType()->isInstantiationDependentType() ||
22678 D->getType()->containsUnexpandedParameterPack());
22679 })) {
22680 UnresolvedSet<8> URS;
22681 for (const UnresolvedSet<8> &Set : Lookups) {
22682 if (Set.empty())
22683 continue;
22684 URS.append(Set.begin(), Set.end());
22685 }
22687 SemaRef.Context, /*NamingClass=*/nullptr,
22688 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
22689 /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false,
22690 /*KnownInstantiationDependent=*/false);
22691 }
22692 SourceLocation Loc = MapperId.getLoc();
22693 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22694 // The type must be of struct, union or class type in C and C++
22696 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
22697 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
22698 return ExprError();
22699 }
22700 // Perform argument dependent lookup.
22701 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
22702 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
22703 // Return the first user-defined mapper with the desired type.
22705 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
22706 if (!D->isInvalidDecl() &&
22707 SemaRef.Context.hasSameType(D->getType(), Type))
22708 return D;
22709 return nullptr;
22710 }))
22711 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
22712 // Find the first user-defined mapper with a type derived from the desired
22713 // type.
22715 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
22716 if (!D->isInvalidDecl() &&
22717 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
22718 !Type.isMoreQualifiedThan(D->getType(),
22719 SemaRef.getASTContext()))
22720 return D;
22721 return nullptr;
22722 })) {
22723 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
22724 /*DetectVirtual=*/false);
22725 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
22726 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
22727 VD->getType().getUnqualifiedType()))) {
22728 if (SemaRef.CheckBaseClassAccess(
22729 Loc, VD->getType(), Type, Paths.front(),
22730 /*DiagID=*/0) != Sema::AR_inaccessible) {
22731 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
22732 }
22733 }
22734 }
22735 }
22736 // Report error if a mapper is specified, but cannot be found.
22737 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
22738 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
22739 << Type << MapperId.getName();
22740 return ExprError();
22741 }
22742 return ExprEmpty();
22743}
22744
22745namespace {
22746// Utility struct that gathers all the related lists associated with a mappable
22747// expression.
22748struct MappableVarListInfo {
22749 // The list of expressions.
22750 ArrayRef<Expr *> VarList;
22751 // The list of processed expressions.
22752 SmallVector<Expr *, 16> ProcessedVarList;
22753 // The mappble components for each expression.
22755 // The base declaration of the variable.
22756 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
22757 // The reference to the user-defined mapper associated with every expression.
22758 SmallVector<Expr *, 16> UDMapperList;
22759
22760 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
22761 // We have a list of components and base declarations for each entry in the
22762 // variable list.
22763 VarComponents.reserve(VarList.size());
22764 VarBaseDeclarations.reserve(VarList.size());
22765 }
22766};
22767} // namespace
22768
22770 DSAStackTy *Stack,
22772
22773 const RecordDecl *RD = BaseType->getAsRecordDecl();
22774 SourceRange Range = RD->getSourceRange();
22775 DeclarationNameInfo ImplicitName;
22776 // Dummy variable _s for Mapper.
22777 VarDecl *VD = buildVarDecl(S, Range.getEnd(), BaseType, "_s");
22778 DeclRefExpr *MapperVarRef =
22779 buildDeclRefExpr(S, VD, BaseType, SourceLocation());
22780
22781 // Create implicit map clause for mapper.
22783 for (auto *FD : RD->fields()) {
22784 Expr *BE = S.BuildMemberExpr(
22785 MapperVarRef, /*IsArrow=*/false, Range.getBegin(),
22786 NestedNameSpecifierLoc(), Range.getBegin(), FD,
22788 /*HadMultipleCandidates=*/false,
22790 FD->getType(), VK_LValue, OK_Ordinary);
22791 SExprs.push_back(BE);
22792 }
22793 CXXScopeSpec MapperIdScopeSpec;
22794 DeclarationNameInfo MapperId;
22795 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
22796
22797 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
22798 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec,
22799 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
22800 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), SExprs,
22801 OMPVarListLocTy());
22802 Maps.push_back(MapClause);
22803 return MapperVarRef;
22804}
22805
22807 DSAStackTy *Stack) {
22808
22809 // Build impilicit map for mapper
22811 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
22812
22813 const RecordDecl *RD = BaseType->getAsRecordDecl();
22814 // AST context is RD's ParentASTContext().
22815 ASTContext &Ctx = RD->getParentASTContext();
22816 // DeclContext is RD's DeclContext.
22817 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
22818
22819 // Create implicit default mapper for "RD".
22820 DeclarationName MapperId;
22821 auto &DeclNames = Ctx.DeclarationNames;
22822 MapperId = DeclNames.getIdentifier(&Ctx.Idents.get("default"));
22823 auto *DMD = OMPDeclareMapperDecl::Create(Ctx, DCT, SourceLocation(), MapperId,
22824 BaseType, MapperId, Maps, nullptr);
22825 Scope *Scope = S.getScopeForContext(DCT);
22826 if (Scope)
22827 S.PushOnScopeChains(DMD, Scope, /*AddToContext=*/false);
22828 DCT->addDecl(DMD);
22829 DMD->setAccess(clang::AS_none);
22830 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22831 VD->setDeclContext(DMD);
22832 VD->setLexicalDeclContext(DMD);
22833 DMD->addDecl(VD);
22834 DMD->setMapperVarRef(MapperVarRef);
22835 FieldDecl *FD = *RD->field_begin();
22836 // create mapper refence.
22838 DMD, false, SourceLocation(), BaseType, VK_LValue);
22839}
22840
22841// Look up the user-defined mapper given the mapper name and mapper type,
22842// return true if found one.
22843static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
22844 CXXScopeSpec &MapperIdScopeSpec,
22845 const DeclarationNameInfo &MapperId,
22846 QualType Type) {
22847 // Find all user-defined mappers with the given MapperId.
22848 SmallVector<UnresolvedSet<8>, 4> Lookups;
22849 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
22850 Lookup.suppressDiagnostics();
22851 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
22852 /*ObjectType=*/QualType())) {
22853 NamedDecl *D = Lookup.getRepresentativeDecl();
22854 while (S && !S->isDeclScope(D))
22855 S = S->getParent();
22856 if (S)
22857 S = S->getParent();
22858 Lookups.emplace_back();
22859 Lookups.back().append(Lookup.begin(), Lookup.end());
22860 Lookup.clear();
22861 }
22862 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
22866 return !D->isInvalidDecl() &&
22867 (D->getType()->isDependentType() ||
22868 D->getType()->isInstantiationDependentType() ||
22869 D->getType()->containsUnexpandedParameterPack());
22870 }))
22871 return false;
22872 // Perform argument dependent lookup.
22873 SourceLocation Loc = MapperId.getLoc();
22874 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
22875 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
22877 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
22878 if (!D->isInvalidDecl() &&
22879 SemaRef.Context.hasSameType(D->getType(), Type))
22880 return D;
22881 return nullptr;
22882 }))
22883 return true;
22884 // Find the first user-defined mapper with a type derived from the desired
22885 // type.
22887 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
22888 if (!D->isInvalidDecl() &&
22889 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
22890 !Type.isMoreQualifiedThan(D->getType(), SemaRef.getASTContext()))
22891 return D;
22892 return nullptr;
22893 });
22894 if (!VD)
22895 return false;
22896 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
22897 /*DetectVirtual=*/false);
22898 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
22899 bool IsAmbiguous = !Paths.isAmbiguous(
22901 if (IsAmbiguous)
22902 return false;
22903 if (SemaRef.CheckBaseClassAccess(Loc, VD->getType(), Type, Paths.front(),
22904 /*DiagID=*/0) != Sema::AR_inaccessible)
22905 return true;
22906 }
22907 return false;
22908}
22909
22910static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
22911 QualType CanonType, const Expr *E) {
22912
22913 // DFS over data members in structures/classes.
22915 {CanonType, nullptr});
22916 llvm::DenseMap<const Type *, bool> Visited;
22917 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
22918 while (!Types.empty()) {
22919 auto [BaseType, CurFD] = Types.pop_back_val();
22920 while (ParentChain.back().second == 0)
22921 ParentChain.pop_back();
22922 --ParentChain.back().second;
22923 if (BaseType.isNull())
22924 continue;
22925 // Only structs/classes are allowed to have mappers.
22926 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
22927 if (!RD)
22928 continue;
22929 auto It = Visited.find(BaseType.getTypePtr());
22930 if (It == Visited.end()) {
22931 // Try to find the associated user-defined mapper.
22932 CXXScopeSpec MapperIdScopeSpec;
22933 DeclarationNameInfo DefaultMapperId;
22935 &S.Context.Idents.get("default")));
22936 DefaultMapperId.setLoc(E->getExprLoc());
22937 bool HasUDMapper =
22938 hasUserDefinedMapper(S, Stack->getCurScope(), MapperIdScopeSpec,
22939 DefaultMapperId, BaseType);
22940 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
22941 }
22942 // Found default mapper.
22943 if (It->second)
22944 return true;
22945 // Check for the "default" mapper for data members.
22946 bool FirstIter = true;
22947 for (FieldDecl *FD : RD->fields()) {
22948 if (!FD)
22949 continue;
22950 QualType FieldTy = FD->getType();
22951 if (FieldTy.isNull() ||
22952 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
22953 continue;
22954 if (FirstIter) {
22955 FirstIter = false;
22956 ParentChain.emplace_back(CurFD, 1);
22957 } else {
22958 ++ParentChain.back().second;
22959 }
22960 Types.emplace_back(FieldTy, FD);
22961 }
22962 }
22963 return false;
22964}
22965
22966// Check the validity of the provided variable list for the provided clause kind
22967// \a CKind. In the check process the valid expressions, mappable expression
22968// components, variables, and user-defined mappers are extracted and used to
22969// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
22970// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
22971// and \a MapperId are expected to be valid if the clause kind is 'map'.
22973 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
22974 MappableVarListInfo &MVLI, SourceLocation StartLoc,
22975 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
22976 ArrayRef<Expr *> UnresolvedMappers,
22978 ArrayRef<OpenMPMapModifierKind> Modifiers = {},
22979 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
22980 // We only expect mappable expressions in 'to', 'from', 'map', and
22981 // 'use_device_addr' clauses.
22982 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from ||
22983 CKind == OMPC_use_device_addr) &&
22984 "Unexpected clause kind with mappable expressions!");
22985 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
22986
22987 // If the identifier of user-defined mapper is not specified, it is "default".
22988 // We do not change the actual name in this clause to distinguish whether a
22989 // mapper is specified explicitly, i.e., it is not explicitly specified when
22990 // MapperId.getName() is empty.
22991 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
22992 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
22993 MapperId.setName(DeclNames.getIdentifier(
22994 &SemaRef.getASTContext().Idents.get("default")));
22995 MapperId.setLoc(StartLoc);
22996 }
22997
22998 // Iterators to find the current unresolved mapper expression.
22999 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
23000 bool UpdateUMIt = false;
23001 Expr *UnresolvedMapper = nullptr;
23002
23003 bool HasHoldModifier =
23004 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
23005
23006 // Keep track of the mappable components and base declarations in this clause.
23007 // Each entry in the list is going to have a list of components associated. We
23008 // record each set of the components so that we can build the clause later on.
23009 // In the end we should have the same amount of declarations and component
23010 // lists.
23011
23012 for (Expr *RE : MVLI.VarList) {
23013 assert(RE && "Null expr in omp to/from/map clause");
23014 SourceLocation ELoc = RE->getExprLoc();
23015
23016 // Find the current unresolved mapper expression.
23017 if (UpdateUMIt && UMIt != UMEnd) {
23018 UMIt++;
23019 assert(
23020 UMIt != UMEnd &&
23021 "Expect the size of UnresolvedMappers to match with that of VarList");
23022 }
23023 UpdateUMIt = true;
23024 if (UMIt != UMEnd)
23025 UnresolvedMapper = *UMIt;
23026
23027 const Expr *VE = RE->IgnoreParenLValueCasts();
23028
23029 if (VE->isValueDependent() || VE->isTypeDependent() ||
23030 VE->isInstantiationDependent() ||
23031 VE->containsUnexpandedParameterPack()) {
23032 // Try to find the associated user-defined mapper.
23034 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23035 VE->getType().getCanonicalType(), UnresolvedMapper);
23036 if (ER.isInvalid())
23037 continue;
23038 MVLI.UDMapperList.push_back(ER.get());
23039 // We can only analyze this information once the missing information is
23040 // resolved.
23041 MVLI.ProcessedVarList.push_back(RE);
23042 continue;
23043 }
23044
23046
23047 if (!RE->isLValue()) {
23048 if (SemaRef.getLangOpts().OpenMP < 50) {
23049 SemaRef.Diag(
23050 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
23051 << RE->getSourceRange();
23052 } else {
23053 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
23054 << getOpenMPClauseNameForDiag(CKind) << RE->getSourceRange();
23055 }
23056 continue;
23057 }
23058
23060 ValueDecl *CurDeclaration = nullptr;
23061
23062 // Obtain the array or member expression bases if required. Also, fill the
23063 // components array with all the components identified in the process.
23064 const Expr *BE =
23065 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
23066 DSAS->getCurrentDirective(), NoDiagnose);
23067 if (!BE)
23068 continue;
23069
23070 assert(!CurComponents.empty() &&
23071 "Invalid mappable expression information.");
23072
23073 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
23074 // Add store "this" pointer to class in DSAStackTy for future checking
23075 DSAS->addMappedClassesQualTypes(TE->getType());
23076 // Try to find the associated user-defined mapper.
23078 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23079 VE->getType().getCanonicalType(), UnresolvedMapper);
23080 if (ER.isInvalid())
23081 continue;
23082 MVLI.UDMapperList.push_back(ER.get());
23083 // Skip restriction checking for variable or field declarations
23084 MVLI.ProcessedVarList.push_back(RE);
23085 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23086 MVLI.VarComponents.back().append(CurComponents.begin(),
23087 CurComponents.end());
23088 MVLI.VarBaseDeclarations.push_back(nullptr);
23089 continue;
23090 }
23091
23092 // For the following checks, we rely on the base declaration which is
23093 // expected to be associated with the last component. The declaration is
23094 // expected to be a variable or a field (if 'this' is being mapped).
23095 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
23096 assert(CurDeclaration && "Null decl on map clause.");
23097 assert(
23098 CurDeclaration->isCanonicalDecl() &&
23099 "Expecting components to have associated only canonical declarations.");
23100
23101 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
23102 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
23103
23104 assert((VD || FD) && "Only variables or fields are expected here!");
23105 (void)FD;
23106
23107 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
23108 // threadprivate variables cannot appear in a map clause.
23109 // OpenMP 4.5 [2.10.5, target update Construct]
23110 // threadprivate variables cannot appear in a from clause.
23111 if (VD && DSAS->isThreadPrivate(VD)) {
23112 if (NoDiagnose)
23113 continue;
23114 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
23115 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
23117 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
23118 continue;
23119 }
23120
23121 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
23122 // A list item cannot appear in both a map clause and a data-sharing
23123 // attribute clause on the same construct.
23124
23125 // Check conflicts with other map clause expressions. We check the conflicts
23126 // with the current construct separately from the enclosing data
23127 // environment, because the restrictions are different. We only have to
23128 // check conflicts across regions for the map clauses.
23129 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
23130 /*CurrentRegionOnly=*/true, CurComponents, CKind))
23131 break;
23132 if (CKind == OMPC_map &&
23133 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
23134 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
23135 /*CurrentRegionOnly=*/false, CurComponents, CKind))
23136 break;
23137
23138 // OpenMP 4.5 [2.10.5, target update Construct]
23139 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
23140 // If the type of a list item is a reference to a type T then the type will
23141 // be considered to be T for all purposes of this clause.
23142 auto I = llvm::find_if(
23143 CurComponents,
23145 return MC.getAssociatedDeclaration();
23146 });
23147 assert(I != CurComponents.end() && "Null decl on map clause.");
23148 (void)I;
23149 QualType Type;
23150 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
23151 auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens());
23152 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
23153 if (ASE) {
23154 Type = ASE->getType().getNonReferenceType();
23155 } else if (OASE) {
23156 QualType BaseType =
23158 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
23159 Type = ATy->getElementType();
23160 else
23161 Type = BaseType->getPointeeType();
23162 Type = Type.getNonReferenceType();
23163 } else if (OAShE) {
23164 Type = OAShE->getBase()->getType()->getPointeeType();
23165 } else {
23166 Type = VE->getType();
23167 }
23168
23169 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
23170 // A list item in a to or from clause must have a mappable type.
23171 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
23172 // A list item must have a mappable type.
23173 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
23174 DSAS, Type, /*FullCheck=*/true))
23175 continue;
23176
23177 if (CKind == OMPC_map) {
23178 // target enter data
23179 // OpenMP [2.10.2, Restrictions, p. 99]
23180 // A map-type must be specified in all map clauses and must be either
23181 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
23182 // no map type is present.
23183 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
23184 if (DKind == OMPD_target_enter_data &&
23185 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
23186 SemaRef.getLangOpts().OpenMP >= 52)) {
23187 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23188 << (IsMapTypeImplicit ? 1 : 0)
23189 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
23190 << getOpenMPDirectiveName(DKind, OMPVersion);
23191 continue;
23192 }
23193
23194 // target exit_data
23195 // OpenMP [2.10.3, Restrictions, p. 102]
23196 // A map-type must be specified in all map clauses and must be either
23197 // from, release, or delete. Starting with OpenMP 5.2 the default map
23198 // type is `from` if no map type is present.
23199 if (DKind == OMPD_target_exit_data &&
23200 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
23201 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
23202 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23203 << (IsMapTypeImplicit ? 1 : 0)
23204 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
23205 << getOpenMPDirectiveName(DKind, OMPVersion);
23206 continue;
23207 }
23208
23209 // The 'ompx_hold' modifier is specifically intended to be used on a
23210 // 'target' or 'target data' directive to prevent data from being unmapped
23211 // during the associated statement. It is not permitted on a 'target
23212 // enter data' or 'target exit data' directive, which have no associated
23213 // statement.
23214 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
23215 HasHoldModifier) {
23216 SemaRef.Diag(StartLoc,
23217 diag::err_omp_invalid_map_type_modifier_for_directive)
23219 OMPC_MAP_MODIFIER_ompx_hold)
23220 << getOpenMPDirectiveName(DKind, OMPVersion);
23221 continue;
23222 }
23223
23224 // target, target data
23225 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
23226 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
23227 // A map-type in a map clause must be to, from, tofrom or alloc
23228 if ((DKind == OMPD_target_data ||
23230 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
23231 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
23232 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23233 << (IsMapTypeImplicit ? 1 : 0)
23234 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
23235 << getOpenMPDirectiveName(DKind, OMPVersion);
23236 continue;
23237 }
23238
23239 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
23240 // A list item cannot appear in both a map clause and a data-sharing
23241 // attribute clause on the same construct
23242 //
23243 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
23244 // A list item cannot appear in both a map clause and a data-sharing
23245 // attribute clause on the same construct unless the construct is a
23246 // combined construct.
23247 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
23249 DKind == OMPD_target)) {
23250 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
23251 if (isOpenMPPrivate(DVar.CKind)) {
23252 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23253 << getOpenMPClauseNameForDiag(DVar.CKind)
23254 << getOpenMPClauseNameForDiag(OMPC_map)
23255 << getOpenMPDirectiveName(DSAS->getCurrentDirective(),
23256 OMPVersion);
23257 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
23258 continue;
23259 }
23260 }
23261 }
23262
23263 // Try to find the associated user-defined mapper.
23265 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23266 Type.getCanonicalType(), UnresolvedMapper);
23267 if (ER.isInvalid())
23268 continue;
23269
23270 // If no user-defined mapper is found, we need to create an implicit one for
23271 // arrays/array-sections on structs that have members that have
23272 // user-defined mappers. This is needed to ensure that the mapper for the
23273 // member is invoked when mapping each element of the array/array-section.
23274 if (!ER.get()) {
23275 QualType BaseType;
23276
23278 BaseType = VE->getType().getCanonicalType();
23279 if (BaseType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
23280 const auto *OASE = cast<ArraySectionExpr>(VE->IgnoreParenImpCasts());
23281 QualType BType =
23283 QualType ElemType;
23284 if (const auto *ATy = BType->getAsArrayTypeUnsafe())
23285 ElemType = ATy->getElementType();
23286 else
23287 ElemType = BType->getPointeeType();
23288 BaseType = ElemType.getCanonicalType();
23289 }
23290 } else if (VE->getType()->isArrayType()) {
23291 const ArrayType *AT = VE->getType()->getAsArrayTypeUnsafe();
23292 const QualType ElemType = AT->getElementType();
23293 BaseType = ElemType.getCanonicalType();
23294 }
23295
23296 if (!BaseType.isNull() && BaseType->getAsRecordDecl() &&
23297 isImplicitMapperNeeded(SemaRef, DSAS, BaseType, VE)) {
23298 ER = buildImplicitMapper(SemaRef, BaseType, DSAS);
23299 }
23300 }
23301 MVLI.UDMapperList.push_back(ER.get());
23302
23303 // Save the current expression.
23304 MVLI.ProcessedVarList.push_back(RE);
23305
23306 // Store the components in the stack so that they can be used to check
23307 // against other clauses later on.
23308 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
23309 /*WhereFoundClauseKind=*/OMPC_map);
23310
23311 // Save the components and declaration to create the clause. For purposes of
23312 // the clause creation, any component list that has base 'this' uses
23313 // null as base declaration.
23314 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23315 MVLI.VarComponents.back().append(CurComponents.begin(),
23316 CurComponents.end());
23317 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
23318 : CurDeclaration);
23319 }
23320}
23321
23323 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
23324 ArrayRef<SourceLocation> MapTypeModifiersLoc,
23325 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23326 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
23327 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23328 const OMPVarListLocTy &Locs, bool NoDiagnose,
23329 ArrayRef<Expr *> UnresolvedMappers) {
23330 OpenMPMapModifierKind Modifiers[] = {
23336
23337 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
23338 BuiltinType::OMPIterator))
23339 Diag(IteratorModifier->getExprLoc(),
23340 diag::err_omp_map_modifier_not_iterator);
23341
23342 // Process map-type-modifiers, flag errors for duplicate modifiers.
23343 unsigned Count = 0;
23344 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
23345 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
23346 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
23347 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
23348 continue;
23349 }
23350 assert(Count < NumberOfOMPMapClauseModifiers &&
23351 "Modifiers exceed the allowed number of map type modifiers");
23352 Modifiers[Count] = MapTypeModifiers[I];
23353 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
23354 ++Count;
23355 }
23356
23357 MappableVarListInfo MVLI(VarList);
23359 MapperIdScopeSpec, MapperId, UnresolvedMappers,
23360 MapType, Modifiers, IsMapTypeImplicit,
23361 NoDiagnose);
23362
23363 // We need to produce a map clause even if we don't have variables so that
23364 // other diagnostics related with non-existing map clauses are accurate.
23365 return OMPMapClause::Create(
23366 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23367 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
23368 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
23369 MapperId, MapType, IsMapTypeImplicit, MapLoc);
23370}
23371
23374 assert(ParsedType.isUsable());
23375
23376 QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get());
23377 if (ReductionType.isNull())
23378 return QualType();
23379
23380 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
23381 // A type name in a declare reduction directive cannot be a function type, an
23382 // array type, a reference type, or a type qualified with const, volatile or
23383 // restrict.
23384 if (ReductionType.hasQualifiers()) {
23385 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
23386 return QualType();
23387 }
23388
23389 if (ReductionType->isFunctionType()) {
23390 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
23391 return QualType();
23392 }
23393 if (ReductionType->isReferenceType()) {
23394 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
23395 return QualType();
23396 }
23397 if (ReductionType->isArrayType()) {
23398 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
23399 return QualType();
23400 }
23401 return ReductionType;
23402}
23403
23406 Scope *S, DeclContext *DC, DeclarationName Name,
23407 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
23408 AccessSpecifier AS, Decl *PrevDeclInScope) {
23410 Decls.reserve(ReductionTypes.size());
23411
23412 LookupResult Lookup(SemaRef, Name, SourceLocation(),
23414 SemaRef.forRedeclarationInCurContext());
23415 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
23416 // A reduction-identifier may not be re-declared in the current scope for the
23417 // same type or for a type that is compatible according to the base language
23418 // rules.
23419 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
23420 OMPDeclareReductionDecl *PrevDRD = nullptr;
23421 bool InCompoundScope = true;
23422 if (S != nullptr) {
23423 // Find previous declaration with the same name not referenced in other
23424 // declarations.
23425 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
23426 InCompoundScope =
23427 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
23428 SemaRef.LookupName(Lookup, S);
23429 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
23430 /*AllowInlineNamespace=*/false);
23431 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
23432 LookupResult::Filter Filter = Lookup.makeFilter();
23433 while (Filter.hasNext()) {
23434 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
23435 if (InCompoundScope) {
23436 UsedAsPrevious.try_emplace(PrevDecl, false);
23437 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
23438 UsedAsPrevious[D] = true;
23439 }
23440 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
23441 PrevDecl->getLocation();
23442 }
23443 Filter.done();
23444 if (InCompoundScope) {
23445 for (const auto &PrevData : UsedAsPrevious) {
23446 if (!PrevData.second) {
23447 PrevDRD = PrevData.first;
23448 break;
23449 }
23450 }
23451 }
23452 } else if (PrevDeclInScope != nullptr) {
23453 auto *PrevDRDInScope = PrevDRD =
23454 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
23455 do {
23456 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
23457 PrevDRDInScope->getLocation();
23458 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
23459 } while (PrevDRDInScope != nullptr);
23460 }
23461 for (const auto &TyData : ReductionTypes) {
23462 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
23463 bool Invalid = false;
23464 if (I != PreviousRedeclTypes.end()) {
23465 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
23466 << TyData.first;
23467 Diag(I->second, diag::note_previous_definition);
23468 Invalid = true;
23469 }
23470 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
23472 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
23473 DC->addDecl(DRD);
23474 DRD->setAccess(AS);
23475 Decls.push_back(DRD);
23476 if (Invalid)
23477 DRD->setInvalidDecl();
23478 else
23479 PrevDRD = DRD;
23480 }
23481
23482 return DeclGroupPtrTy::make(
23483 DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size()));
23484}
23485
23487 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23488
23489 // Enter new function scope.
23490 SemaRef.PushFunctionScope();
23491 SemaRef.setFunctionHasBranchProtectedScope();
23492 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
23493
23494 if (S != nullptr)
23495 SemaRef.PushDeclContext(S, DRD);
23496 else
23497 SemaRef.CurContext = DRD;
23498
23499 SemaRef.PushExpressionEvaluationContext(
23501
23502 QualType ReductionType = DRD->getType();
23503 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
23504 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
23505 // uses semantics of argument handles by value, but it should be passed by
23506 // reference. C lang does not support references, so pass all parameters as
23507 // pointers.
23508 // Create 'T omp_in;' variable.
23509 VarDecl *OmpInParm =
23510 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in");
23511 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
23512 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
23513 // uses semantics of argument handles by value, but it should be passed by
23514 // reference. C lang does not support references, so pass all parameters as
23515 // pointers.
23516 // Create 'T omp_out;' variable.
23517 VarDecl *OmpOutParm =
23518 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out");
23519 if (S != nullptr) {
23520 SemaRef.PushOnScopeChains(OmpInParm, S);
23521 SemaRef.PushOnScopeChains(OmpOutParm, S);
23522 } else {
23523 DRD->addDecl(OmpInParm);
23524 DRD->addDecl(OmpOutParm);
23525 }
23526 Expr *InE =
23527 ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation());
23528 Expr *OutE =
23529 ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation());
23530 DRD->setCombinerData(InE, OutE);
23531}
23532
23534 Expr *Combiner) {
23535 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23536 SemaRef.DiscardCleanupsInEvaluationContext();
23537 SemaRef.PopExpressionEvaluationContext();
23538
23539 SemaRef.PopDeclContext();
23540 SemaRef.PopFunctionScopeInfo();
23541
23542 if (Combiner != nullptr)
23543 DRD->setCombiner(Combiner);
23544 else
23545 DRD->setInvalidDecl();
23546}
23547
23549 Decl *D) {
23550 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23551
23552 // Enter new function scope.
23553 SemaRef.PushFunctionScope();
23554 SemaRef.setFunctionHasBranchProtectedScope();
23555
23556 if (S != nullptr)
23557 SemaRef.PushDeclContext(S, DRD);
23558 else
23559 SemaRef.CurContext = DRD;
23560
23561 SemaRef.PushExpressionEvaluationContext(
23563
23564 QualType ReductionType = DRD->getType();
23565 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
23566 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
23567 // uses semantics of argument handles by value, but it should be passed by
23568 // reference. C lang does not support references, so pass all parameters as
23569 // pointers.
23570 // Create 'T omp_priv;' variable.
23571 VarDecl *OmpPrivParm =
23572 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv");
23573 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
23574 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
23575 // uses semantics of argument handles by value, but it should be passed by
23576 // reference. C lang does not support references, so pass all parameters as
23577 // pointers.
23578 // Create 'T omp_orig;' variable.
23579 VarDecl *OmpOrigParm =
23580 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig");
23581 if (S != nullptr) {
23582 SemaRef.PushOnScopeChains(OmpPrivParm, S);
23583 SemaRef.PushOnScopeChains(OmpOrigParm, S);
23584 } else {
23585 DRD->addDecl(OmpPrivParm);
23586 DRD->addDecl(OmpOrigParm);
23587 }
23588 Expr *OrigE =
23589 ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation());
23590 Expr *PrivE =
23591 ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation());
23592 DRD->setInitializerData(OrigE, PrivE);
23593 return OmpPrivParm;
23594}
23595
23597 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
23598 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23599 SemaRef.DiscardCleanupsInEvaluationContext();
23600 SemaRef.PopExpressionEvaluationContext();
23601
23602 SemaRef.PopDeclContext();
23603 SemaRef.PopFunctionScopeInfo();
23604
23605 if (Initializer != nullptr) {
23606 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
23607 } else if (OmpPrivParm->hasInit()) {
23608 DRD->setInitializer(OmpPrivParm->getInit(),
23609 OmpPrivParm->isDirectInit()
23612 } else {
23613 DRD->setInvalidDecl();
23614 }
23615}
23616
23618 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
23619 for (Decl *D : DeclReductions.get()) {
23620 if (IsValid) {
23621 if (S)
23622 SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
23623 /*AddToContext=*/false);
23624 } else {
23625 D->setInvalidDecl();
23626 }
23627 }
23628 return DeclReductions;
23629}
23630
23632 Declarator &D) {
23633 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
23634 QualType T = TInfo->getType();
23635 if (D.isInvalidType())
23636 return true;
23637
23638 if (getLangOpts().CPlusPlus) {
23639 // Check that there are no default arguments (C++ only).
23640 SemaRef.CheckExtraCXXDefaultArguments(D);
23641 }
23642
23643 return SemaRef.CreateParsedType(T, TInfo);
23644}
23645
23648 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
23649
23650 QualType MapperType = SemaRef.GetTypeFromParser(ParsedType.get());
23651 assert(!MapperType.isNull() && "Expect valid mapper type");
23652
23653 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
23654 // The type must be of struct, union or class type in C and C++
23655 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
23656 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
23657 return QualType();
23658 }
23659 return MapperType;
23660}
23661
23663 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
23665 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
23666 LookupResult Lookup(SemaRef, Name, SourceLocation(),
23668 SemaRef.forRedeclarationInCurContext());
23669 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
23670 // A mapper-identifier may not be redeclared in the current scope for the
23671 // same type or for a type that is compatible according to the base language
23672 // rules.
23673 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
23674 OMPDeclareMapperDecl *PrevDMD = nullptr;
23675 bool InCompoundScope = true;
23676 if (S != nullptr) {
23677 // Find previous declaration with the same name not referenced in other
23678 // declarations.
23679 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
23680 InCompoundScope =
23681 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
23682 SemaRef.LookupName(Lookup, S);
23683 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
23684 /*AllowInlineNamespace=*/false);
23685 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
23686 LookupResult::Filter Filter = Lookup.makeFilter();
23687 while (Filter.hasNext()) {
23688 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
23689 if (InCompoundScope) {
23690 UsedAsPrevious.try_emplace(PrevDecl, false);
23691 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
23692 UsedAsPrevious[D] = true;
23693 }
23694 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
23695 PrevDecl->getLocation();
23696 }
23697 Filter.done();
23698 if (InCompoundScope) {
23699 for (const auto &PrevData : UsedAsPrevious) {
23700 if (!PrevData.second) {
23701 PrevDMD = PrevData.first;
23702 break;
23703 }
23704 }
23705 }
23706 } else if (PrevDeclInScope) {
23707 auto *PrevDMDInScope = PrevDMD =
23708 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
23709 do {
23710 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
23711 PrevDMDInScope->getLocation();
23712 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
23713 } while (PrevDMDInScope != nullptr);
23714 }
23715 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
23716 bool Invalid = false;
23717 if (I != PreviousRedeclTypes.end()) {
23718 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
23719 << MapperType << Name;
23720 Diag(I->second, diag::note_previous_definition);
23721 Invalid = true;
23722 }
23723 // Build expressions for implicit maps of data members with 'default'
23724 // mappers.
23725 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
23726 if (getLangOpts().OpenMP >= 50)
23728 ClausesWithImplicit);
23729 auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name,
23730 MapperType, VN, ClausesWithImplicit,
23731 PrevDMD);
23732 if (S)
23733 SemaRef.PushOnScopeChains(DMD, S);
23734 else
23735 DC->addDecl(DMD);
23736 DMD->setAccess(AS);
23737 if (Invalid)
23738 DMD->setInvalidDecl();
23739
23740 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
23741 VD->setDeclContext(DMD);
23742 VD->setLexicalDeclContext(DMD);
23743 DMD->addDecl(VD);
23744 DMD->setMapperVarRef(MapperVarRef);
23745
23747}
23748
23750 Scope *S, QualType MapperType, SourceLocation StartLoc,
23751 DeclarationName VN) {
23752 TypeSourceInfo *TInfo =
23753 getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc);
23754 auto *VD = VarDecl::Create(
23755 getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc,
23756 StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None);
23757 if (S)
23758 SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false);
23759 Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc);
23760 DSAStack->addDeclareMapperVarRef(E);
23761 return E;
23762}
23763
23765 bool IsGlobalVar =
23767 if (DSAStack->getDeclareMapperVarRef()) {
23768 if (IsGlobalVar)
23769 SemaRef.Consumer.HandleTopLevelDecl(DeclGroupRef(VD));
23770 DSAStack->addIteratorVarDecl(VD);
23771 } else {
23772 // Currently, only declare mapper handles global-scope iterator vars.
23773 assert(!IsGlobalVar && "Only declare mapper handles TU-scope iterators.");
23774 }
23775}
23776
23778 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
23779 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
23780 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
23781 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
23782 return true;
23784 return true;
23785 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
23786 return true;
23787 return false;
23788 }
23789 return true;
23790}
23791
23793 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
23794 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
23795}
23796
23798 SourceLocation StartLoc,
23799 SourceLocation LParenLoc,
23800 SourceLocation EndLoc) {
23801 if (VarList.empty())
23802 return nullptr;
23803
23804 for (Expr *ValExpr : VarList) {
23805 // OpenMP [teams Constrcut, Restrictions]
23806 // The num_teams expression must evaluate to a positive integer value.
23807 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams,
23808 /*StrictlyPositive=*/true))
23809 return nullptr;
23810 }
23811
23812 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23814 DKind, OMPC_num_teams, getLangOpts().OpenMP);
23815 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
23816 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
23817 LParenLoc, EndLoc, VarList,
23818 /*PreInit=*/nullptr);
23819
23820 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23822 for (Expr *ValExpr : VarList) {
23823 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23824 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23825 Vars.push_back(ValExpr);
23826 }
23827
23828 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
23829 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
23830 LParenLoc, EndLoc, Vars, PreInit);
23831}
23832
23834 SourceLocation StartLoc,
23835 SourceLocation LParenLoc,
23836 SourceLocation EndLoc) {
23837 if (VarList.empty())
23838 return nullptr;
23839
23840 for (Expr *ValExpr : VarList) {
23841 // OpenMP [teams Constrcut, Restrictions]
23842 // The thread_limit expression must evaluate to a positive integer value.
23843 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit,
23844 /*StrictlyPositive=*/true))
23845 return nullptr;
23846 }
23847
23848 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23850 DKind, OMPC_thread_limit, getLangOpts().OpenMP);
23851 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
23852 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion,
23853 StartLoc, LParenLoc, EndLoc, VarList,
23854 /*PreInit=*/nullptr);
23855
23856 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23858 for (Expr *ValExpr : VarList) {
23859 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23860 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23861 Vars.push_back(ValExpr);
23862 }
23863
23864 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
23865 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion, StartLoc,
23866 LParenLoc, EndLoc, Vars, PreInit);
23867}
23868
23870 SourceLocation StartLoc,
23871 SourceLocation LParenLoc,
23872 SourceLocation EndLoc) {
23873 Expr *ValExpr = Priority;
23874 Stmt *HelperValStmt = nullptr;
23875 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23876
23877 // OpenMP [2.9.1, task Constrcut]
23878 // The priority-value is a non-negative numerical scalar expression.
23880 ValExpr, SemaRef, OMPC_priority,
23881 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
23882 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23883 return nullptr;
23884
23885 return new (getASTContext()) OMPPriorityClause(
23886 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23887}
23888
23890 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
23891 SourceLocation StartLoc, SourceLocation LParenLoc,
23892 SourceLocation ModifierLoc, SourceLocation EndLoc) {
23893 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
23894 "Unexpected grainsize modifier in OpenMP < 51.");
23895
23896 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
23897 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
23899 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23900 << Values << getOpenMPClauseNameForDiag(OMPC_grainsize);
23901 return nullptr;
23902 }
23903
23904 Expr *ValExpr = Grainsize;
23905 Stmt *HelperValStmt = nullptr;
23906 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23907
23908 // OpenMP [2.9.2, taskloop Constrcut]
23909 // The parameter of the grainsize clause must be a positive integer
23910 // expression.
23911 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize,
23912 /*StrictlyPositive=*/true,
23913 /*BuildCapture=*/true,
23914 DSAStack->getCurrentDirective(),
23915 &CaptureRegion, &HelperValStmt))
23916 return nullptr;
23917
23918 return new (getASTContext())
23919 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
23920 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23921}
23922
23924 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
23925 SourceLocation StartLoc, SourceLocation LParenLoc,
23926 SourceLocation ModifierLoc, SourceLocation EndLoc) {
23927 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
23928 "Unexpected num_tasks modifier in OpenMP < 51.");
23929
23930 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
23931 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
23933 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23934 << Values << getOpenMPClauseNameForDiag(OMPC_num_tasks);
23935 return nullptr;
23936 }
23937
23938 Expr *ValExpr = NumTasks;
23939 Stmt *HelperValStmt = nullptr;
23940 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23941
23942 // OpenMP [2.9.2, taskloop Constrcut]
23943 // The parameter of the num_tasks clause must be a positive integer
23944 // expression.
23946 ValExpr, SemaRef, OMPC_num_tasks,
23947 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
23948 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23949 return nullptr;
23950
23951 return new (getASTContext())
23952 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
23953 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23954}
23955
23957 SourceLocation StartLoc,
23958 SourceLocation LParenLoc,
23959 SourceLocation EndLoc) {
23960 // OpenMP [2.13.2, critical construct, Description]
23961 // ... where hint-expression is an integer constant expression that evaluates
23962 // to a valid lock hint.
23963 ExprResult HintExpr =
23964 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
23965 if (HintExpr.isInvalid())
23966 return nullptr;
23967 return new (getASTContext())
23968 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
23969}
23970
23971/// Tries to find omp_event_handle_t type.
23973 DSAStackTy *Stack) {
23974 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
23975 if (!OMPEventHandleT.isNull())
23976 return true;
23977 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
23978 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
23979 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23980 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
23981 return false;
23982 }
23983 Stack->setOMPEventHandleT(PT.get());
23984 return true;
23985}
23986
23988 SourceLocation StartLoc,
23989 SourceLocation LParenLoc,
23990 SourceLocation EndLoc) {
23991 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
23992 !Evt->isInstantiationDependent() &&
23995 return nullptr;
23996 // OpenMP 5.0, 2.10.1 task Construct.
23997 // event-handle is a variable of the omp_event_handle_t type.
23998 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
23999 if (!Ref) {
24000 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
24001 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
24002 return nullptr;
24003 }
24004 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
24005 if (!VD) {
24006 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
24007 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
24008 return nullptr;
24009 }
24010 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
24011 VD->getType()) ||
24012 VD->getType().isConstant(getASTContext())) {
24013 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
24014 << "omp_event_handle_t" << 1 << VD->getType()
24015 << Evt->getSourceRange();
24016 return nullptr;
24017 }
24018 // OpenMP 5.0, 2.10.1 task Construct
24019 // [detach clause]... The event-handle will be considered as if it was
24020 // specified on a firstprivate clause.
24021 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
24022 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
24023 DVar.RefExpr) {
24024 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
24025 << getOpenMPClauseNameForDiag(DVar.CKind)
24026 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
24028 return nullptr;
24029 }
24030 }
24031
24032 return new (getASTContext())
24033 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
24034}
24035
24037 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
24038 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
24039 SourceLocation EndLoc) {
24040 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
24041 std::string Values;
24042 Values += "'";
24043 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
24044 Values += "'";
24045 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24046 << Values << getOpenMPClauseNameForDiag(OMPC_dist_schedule);
24047 return nullptr;
24048 }
24049 Expr *ValExpr = ChunkSize;
24050 Stmt *HelperValStmt = nullptr;
24051 if (ChunkSize) {
24052 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
24053 !ChunkSize->isInstantiationDependent() &&
24054 !ChunkSize->containsUnexpandedParameterPack()) {
24055 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
24056 ExprResult Val =
24057 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
24058 if (Val.isInvalid())
24059 return nullptr;
24060
24061 ValExpr = Val.get();
24062
24063 // OpenMP [2.7.1, Restrictions]
24064 // chunk_size must be a loop invariant integer expression with a positive
24065 // value.
24066 if (std::optional<llvm::APSInt> Result =
24068 if (Result->isSigned() && !Result->isStrictlyPositive()) {
24069 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
24070 << "dist_schedule" << /*strictly positive*/ 1
24071 << ChunkSize->getSourceRange();
24072 return nullptr;
24073 }
24075 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
24076 getLangOpts().OpenMP) != OMPD_unknown &&
24077 !SemaRef.CurContext->isDependentContext()) {
24078 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
24079 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24080 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
24081 HelperValStmt = buildPreInits(getASTContext(), Captures);
24082 }
24083 }
24084 }
24085
24086 return new (getASTContext())
24087 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
24088 Kind, ValExpr, HelperValStmt);
24089}
24090
24093 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
24094 SourceLocation KindLoc, SourceLocation EndLoc) {
24095 if (getLangOpts().OpenMP < 50) {
24096 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
24097 Kind != OMPC_DEFAULTMAP_scalar) {
24098 std::string Value;
24099 SourceLocation Loc;
24100 Value += "'";
24101 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
24102 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
24103 OMPC_DEFAULTMAP_MODIFIER_tofrom);
24104 Loc = MLoc;
24105 } else {
24106 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
24107 OMPC_DEFAULTMAP_scalar);
24108 Loc = KindLoc;
24109 }
24110 Value += "'";
24111 Diag(Loc, diag::err_omp_unexpected_clause_value)
24112 << Value << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24113 return nullptr;
24114 }
24115 } else {
24116 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
24117 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
24118 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
24119 if (!isDefaultmapKind || !isDefaultmapModifier) {
24120 StringRef KindValue = getLangOpts().OpenMP < 52
24121 ? "'scalar', 'aggregate', 'pointer'"
24122 : "'scalar', 'aggregate', 'pointer', 'all'";
24123 if (getLangOpts().OpenMP == 50) {
24124 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
24125 "'firstprivate', 'none', 'default'";
24126 if (!isDefaultmapKind && isDefaultmapModifier) {
24127 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24128 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24129 } else if (isDefaultmapKind && !isDefaultmapModifier) {
24130 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24131 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24132 } else {
24133 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24134 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24135 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24136 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24137 }
24138 } else {
24139 StringRef ModifierValue =
24140 getLangOpts().OpenMP < 60
24141 ? "'alloc', 'from', 'to', 'tofrom', "
24142 "'firstprivate', 'none', 'default', 'present'"
24143 : "'storage', 'from', 'to', 'tofrom', "
24144 "'firstprivate', 'private', 'none', 'default', 'present'";
24145 if (!isDefaultmapKind && isDefaultmapModifier) {
24146 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24147 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24148 } else if (isDefaultmapKind && !isDefaultmapModifier) {
24149 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24150 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24151 } else {
24152 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24153 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24154 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24155 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24156 }
24157 }
24158 return nullptr;
24159 }
24160
24161 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
24162 // At most one defaultmap clause for each category can appear on the
24163 // directive.
24164 if (DSAStack->checkDefaultmapCategory(Kind)) {
24165 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
24166 return nullptr;
24167 }
24168 }
24169 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
24170 // Variable category is not specified - mark all categories.
24171 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
24172 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
24173 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
24174 } else {
24175 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
24176 }
24177
24178 return new (getASTContext())
24179 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
24180}
24181
24184 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
24185 if (!CurLexicalContext->isFileContext() &&
24186 !CurLexicalContext->isExternCContext() &&
24187 !CurLexicalContext->isExternCXXContext() &&
24188 !isa<CXXRecordDecl>(CurLexicalContext) &&
24189 !isa<ClassTemplateDecl>(CurLexicalContext) &&
24190 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
24191 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
24192 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
24193 return false;
24194 }
24195
24196 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
24197 if (getLangOpts().HIP)
24198 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
24199
24200 DeclareTargetNesting.push_back(DTCI);
24201 return true;
24202}
24203
24206 assert(!DeclareTargetNesting.empty() &&
24207 "check isInOpenMPDeclareTargetContext() first!");
24208 return DeclareTargetNesting.pop_back_val();
24209}
24210
24213 for (auto &It : DTCI.ExplicitlyMapped)
24214 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
24215}
24216
24218 if (DeclareTargetNesting.empty())
24219 return;
24220 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
24221 unsigned OMPVersion = getLangOpts().OpenMP;
24222 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
24223 << getOpenMPDirectiveName(DTCI.Kind, OMPVersion);
24224}
24225
24227 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
24229 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
24230 /*ObjectType=*/QualType(),
24231 /*AllowBuiltinCreation=*/true);
24232
24233 if (Lookup.isAmbiguous())
24234 return nullptr;
24235 Lookup.suppressDiagnostics();
24236
24237 if (!Lookup.isSingleResult()) {
24238 VarOrFuncDeclFilterCCC CCC(SemaRef);
24239 if (TypoCorrection Corrected =
24240 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
24242 SemaRef.diagnoseTypo(Corrected,
24243 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
24244 << Id.getName());
24245 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
24246 return nullptr;
24247 }
24248
24249 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
24250 return nullptr;
24251 }
24252
24253 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
24254 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
24256 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
24257 return nullptr;
24258 }
24259 return ND;
24260}
24261
24263 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
24265 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
24267 "Expected variable, function or function template.");
24268
24269 if (auto *VD = dyn_cast<VarDecl>(ND)) {
24270 // Only global variables can be marked as declare target.
24271 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24272 !VD->isStaticDataMember()) {
24273 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
24274 << VD->getNameAsString();
24275 return;
24276 }
24277 }
24278 // Diagnose marking after use as it may lead to incorrect diagnosis and
24279 // codegen.
24280 if (getLangOpts().OpenMP >= 50 &&
24281 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
24282 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
24283
24284 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
24285 if (getLangOpts().HIP)
24286 Diag(Loc, diag::warn_hip_omp_target_directives);
24287
24288 // Explicit declare target lists have precedence.
24289 const unsigned Level = -1;
24290
24291 auto *VD = cast<ValueDecl>(ND);
24292 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24293 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24294 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
24295 (*ActiveAttr)->getLevel() == Level) {
24296 Diag(Loc, diag::err_omp_device_type_mismatch)
24297 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
24298 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
24299 (*ActiveAttr)->getDevType());
24300 return;
24301 }
24302 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
24303 (*ActiveAttr)->getLevel() == Level) {
24304 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
24305 return;
24306 }
24307
24308 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
24309 return;
24310
24311 Expr *IndirectE = nullptr;
24312 bool IsIndirect = false;
24313 if (DTCI.Indirect) {
24314 IndirectE = *DTCI.Indirect;
24315 if (!IndirectE)
24316 IsIndirect = true;
24317 }
24318 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
24319 getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level,
24320 SourceRange(Loc, Loc));
24321 ND->addAttr(A);
24322 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
24323 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
24324 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
24325 if (auto *VD = dyn_cast<VarDecl>(ND);
24326 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
24327 VD->hasGlobalStorage())
24329}
24330
24332 Sema &SemaRef, Decl *D) {
24333 if (!D || !isa<VarDecl>(D))
24334 return;
24335 auto *VD = cast<VarDecl>(D);
24336 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
24337 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
24338 if (SemaRef.LangOpts.OpenMP >= 50 &&
24339 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
24340 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
24341 VD->hasGlobalStorage()) {
24342 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
24343 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
24344 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
24345 // If a lambda declaration and definition appears between a
24346 // declare target directive and the matching end declare target
24347 // directive, all variables that are captured by the lambda
24348 // expression must also appear in a to clause.
24349 SemaRef.Diag(VD->getLocation(),
24350 diag::err_omp_lambda_capture_in_declare_target_not_to);
24351 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
24352 << VD << 0 << SR;
24353 return;
24354 }
24355 }
24356 if (MapTy)
24357 return;
24358 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
24359 SemaRef.Diag(SL, diag::note_used_here) << SR;
24360}
24361
24363 Sema &SemaRef, DSAStackTy *Stack,
24364 ValueDecl *VD) {
24365 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
24366 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
24367 /*FullCheck=*/false);
24368}
24369
24371 SourceLocation IdLoc) {
24372 if (!D || D->isInvalidDecl())
24373 return;
24374 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
24375 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
24376 if (auto *VD = dyn_cast<VarDecl>(D)) {
24377 // Only global variables can be marked as declare target.
24378 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24379 !VD->isStaticDataMember())
24380 return;
24381 // 2.10.6: threadprivate variable cannot appear in a declare target
24382 // directive.
24383 if (DSAStack->isThreadPrivate(VD)) {
24384 Diag(SL, diag::err_omp_threadprivate_in_target);
24385 reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false));
24386 return;
24387 }
24388 }
24389 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
24390 D = FTD->getTemplatedDecl();
24391 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
24392 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
24393 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
24394 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
24395 Diag(IdLoc, diag::err_omp_function_in_link_clause);
24396 Diag(FD->getLocation(), diag::note_defined_here) << FD;
24397 return;
24398 }
24399 }
24400 if (auto *VD = dyn_cast<ValueDecl>(D)) {
24401 // Problem if any with var declared with incomplete type will be reported
24402 // as normal, so no need to check it here.
24403 if ((E || !VD->getType()->isIncompleteType()) &&
24405 return;
24406 if (!E && isInOpenMPDeclareTargetContext()) {
24407 // Checking declaration inside declare target region.
24408 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
24410 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24411 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24412 unsigned Level = DeclareTargetNesting.size();
24413 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
24414 return;
24415 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
24416 Expr *IndirectE = nullptr;
24417 bool IsIndirect = false;
24418 if (DTCI.Indirect) {
24419 IndirectE = *DTCI.Indirect;
24420 if (!IndirectE)
24421 IsIndirect = true;
24422 }
24423 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
24424 getASTContext(),
24425 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
24426 : OMPDeclareTargetDeclAttr::MT_To,
24427 DTCI.DT, IndirectE, IsIndirect, Level,
24428 SourceRange(DTCI.Loc, DTCI.Loc));
24429 D->addAttr(A);
24430 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
24431 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
24432 }
24433 return;
24434 }
24435 }
24436 if (!E)
24437 return;
24439}
24440
24441/// This class visits every VarDecl that the initializer references and adds
24442/// OMPDeclareTargetDeclAttr to each of them.
24443class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
24444 SmallVector<VarDecl *> DeclVector;
24445 Attr *A;
24446
24447public:
24448 /// A StmtVisitor class function that visits all DeclRefExpr and adds
24449 /// OMPDeclareTargetDeclAttr to them.
24451 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
24452 VD->addAttr(A);
24453 DeclVector.push_back(VD);
24454 }
24455 }
24456 /// A function that iterates across each of the Expr's children.
24457 void VisitExpr(Expr *Ex) {
24458 for (auto *Child : Ex->children()) {
24459 Visit(Child);
24460 }
24461 }
24462 /// A function that keeps a record of all the Decls that are variables, has
24463 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
24464 /// each Decl one at a time and use the inherited 'visit' functions to look
24465 /// for DeclRefExpr.
24467 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
24468 DeclVector.push_back(cast<VarDecl>(TD));
24469 llvm::SmallDenseSet<Decl *> Visited;
24470 while (!DeclVector.empty()) {
24471 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
24472 if (!Visited.insert(TargetVarDecl).second)
24473 continue;
24474
24475 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
24476 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
24477 if (Expr *Ex = TargetVarDecl->getInit())
24478 Visit(Ex);
24479 }
24480 }
24481 }
24482};
24483
24484/// Adding OMPDeclareTargetDeclAttr to variables with static storage
24485/// duration that are referenced in the initializer expression list of
24486/// variables with static storage duration in declare target directive.
24488 GlobalDeclRefChecker Checker;
24489 if (isa<VarDecl>(TargetDecl))
24490 Checker.declareTargetInitializer(TargetDecl);
24491}
24492
24494 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
24495 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
24496 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
24497 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
24498 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
24503
24504 // Process motion-modifiers, flag errors for duplicate modifiers.
24505 unsigned Count = 0;
24506 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
24507 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
24508 llvm::is_contained(Modifiers, MotionModifiers[I])) {
24509 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
24510 continue;
24511 }
24512 assert(Count < NumberOfOMPMotionModifiers &&
24513 "Modifiers exceed the allowed number of motion modifiers");
24514 Modifiers[Count] = MotionModifiers[I];
24515 ModifiersLoc[Count] = MotionModifiersLoc[I];
24516 ++Count;
24517 }
24518
24519 MappableVarListInfo MVLI(VarList);
24521 MapperIdScopeSpec, MapperId, UnresolvedMappers);
24522 if (MVLI.ProcessedVarList.empty())
24523 return nullptr;
24524 if (IteratorExpr)
24525 if (auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
24526 if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
24527 DSAStack->addIteratorVarDecl(VD);
24528 return OMPToClause::Create(
24529 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24530 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
24531 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
24532 MapperId);
24533}
24534
24536 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
24537 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
24538 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
24539 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
24540 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
24545
24546 // Process motion-modifiers, flag errors for duplicate modifiers.
24547 unsigned Count = 0;
24548 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
24549 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
24550 llvm::is_contained(Modifiers, MotionModifiers[I])) {
24551 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
24552 continue;
24553 }
24554 assert(Count < NumberOfOMPMotionModifiers &&
24555 "Modifiers exceed the allowed number of motion modifiers");
24556 Modifiers[Count] = MotionModifiers[I];
24557 ModifiersLoc[Count] = MotionModifiersLoc[I];
24558 ++Count;
24559 }
24560
24561 MappableVarListInfo MVLI(VarList);
24562 checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
24563 MapperIdScopeSpec, MapperId, UnresolvedMappers);
24564 if (MVLI.ProcessedVarList.empty())
24565 return nullptr;
24566 if (IteratorExpr)
24567 if (auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
24568 if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
24569 DSAStack->addIteratorVarDecl(VD);
24570 return OMPFromClause::Create(
24571 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24572 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
24573 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
24574 MapperId);
24575}
24576
24577OMPClause *
24579 const OMPVarListLocTy &Locs) {
24580 MappableVarListInfo MVLI(VarList);
24581 SmallVector<Expr *, 8> PrivateCopies;
24583
24584 for (Expr *RefExpr : VarList) {
24585 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
24586 SourceLocation ELoc;
24587 SourceRange ERange;
24588 Expr *SimpleRefExpr = RefExpr;
24589 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24590 if (Res.second) {
24591 // It will be analyzed later.
24592 MVLI.ProcessedVarList.push_back(RefExpr);
24593 PrivateCopies.push_back(nullptr);
24594 Inits.push_back(nullptr);
24595 }
24596 ValueDecl *D = Res.first;
24597 if (!D)
24598 continue;
24599
24600 QualType Type = D->getType();
24601 Type = Type.getNonReferenceType().getUnqualifiedType();
24602
24603 auto *VD = dyn_cast<VarDecl>(D);
24604
24605 // Item should be a pointer or reference to pointer.
24606 if (!Type->isPointerType()) {
24607 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
24608 << 0 << RefExpr->getSourceRange();
24609 continue;
24610 }
24611
24612 // Build the private variable and the expression that refers to it.
24613 auto VDPrivate =
24614 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
24615 D->hasAttrs() ? &D->getAttrs() : nullptr,
24616 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
24617 if (VDPrivate->isInvalidDecl())
24618 continue;
24619
24620 SemaRef.CurContext->addDecl(VDPrivate);
24621 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
24622 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
24623
24624 // Add temporary variable to initialize the private copy of the pointer.
24625 VarDecl *VDInit =
24626 buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp");
24627 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
24628 SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
24629 SemaRef.AddInitializerToDecl(
24630 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
24631 /*DirectInit=*/false);
24632
24633 // If required, build a capture to implement the privatization initialized
24634 // with the current list item value.
24635 DeclRefExpr *Ref = nullptr;
24636 if (!VD)
24637 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
24638 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
24639 PrivateCopies.push_back(VDPrivateRefExpr);
24640 Inits.push_back(VDInitRefExpr);
24641
24642 // We need to add a data sharing attribute for this variable to make sure it
24643 // is correctly captured. A variable that shows up in a use_device_ptr has
24644 // similar properties of a first private variable.
24645 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24646
24647 // Create a mappable component for the list item. List items in this clause
24648 // only need a component.
24649 MVLI.VarBaseDeclarations.push_back(D);
24650 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24651 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
24652 /*IsNonContiguous=*/false);
24653 }
24654
24655 if (MVLI.ProcessedVarList.empty())
24656 return nullptr;
24657
24659 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
24660 MVLI.VarBaseDeclarations, MVLI.VarComponents);
24661}
24662
24663OMPClause *
24665 const OMPVarListLocTy &Locs) {
24666 MappableVarListInfo MVLI(VarList);
24667
24668 for (Expr *RefExpr : VarList) {
24669 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
24670 SourceLocation ELoc;
24671 SourceRange ERange;
24672 Expr *SimpleRefExpr = RefExpr;
24673 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24674 /*AllowArraySection=*/true,
24675 /*AllowAssumedSizeArray=*/true);
24676 if (Res.second) {
24677 // It will be analyzed later.
24678 MVLI.ProcessedVarList.push_back(RefExpr);
24679 }
24680 ValueDecl *D = Res.first;
24681 if (!D)
24682 continue;
24683 auto *VD = dyn_cast<VarDecl>(D);
24684
24685 // If required, build a capture to implement the privatization initialized
24686 // with the current list item value.
24687 DeclRefExpr *Ref = nullptr;
24688 if (!VD)
24689 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
24690 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
24691
24692 // We need to add a data sharing attribute for this variable to make sure it
24693 // is correctly captured. A variable that shows up in a use_device_addr has
24694 // similar properties of a first private variable.
24695 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24696
24697 // Use the map-like approach to fully populate VarComponents
24699
24701 SemaRef, RefExpr, CurComponents, OMPC_use_device_addr,
24702 DSAStack->getCurrentDirective(),
24703 /*NoDiagnose=*/false);
24704
24705 if (!BE)
24706 continue;
24707
24708 assert(!CurComponents.empty() &&
24709 "use_device_addr clause expression with no components!");
24710
24711 // OpenMP use_device_addr: If a list item is an array section, the array
24712 // base must be a base language identifier. We caught the cases where
24713 // the array-section has a base-variable in getPrivateItem. e.g.
24714 // struct S {
24715 // int a[10];
24716 // }; S s1;
24717 // ... use_device_addr(s1.a[0]) // not ok, caught already
24718 //
24719 // But we still neeed to verify that the base-pointer is also a
24720 // base-language identifier, and catch cases like:
24721 // int *pa[10]; *p;
24722 // ... use_device_addr(pa[1][2]) // not ok, base-pointer is pa[1]
24723 // ... use_device_addr(p[1]) // ok
24724 // ... use_device_addr(this->p[1]) // ok
24726 CurComponents, DSAStack->getCurrentDirective());
24727 const Expr *AttachPtrExpr = AttachPtrResult.first;
24728
24729 if (AttachPtrExpr) {
24730 const Expr *BaseExpr = AttachPtrExpr->IgnoreParenImpCasts();
24731 bool IsValidBase = false;
24732
24733 if (isa<DeclRefExpr>(BaseExpr))
24734 IsValidBase = true;
24735 else if (const auto *ME = dyn_cast<MemberExpr>(BaseExpr);
24737 IsValidBase = true;
24738
24739 if (!IsValidBase) {
24740 SemaRef.Diag(ELoc,
24741 diag::err_omp_expected_base_pointer_var_name_member_expr)
24742 << (SemaRef.getCurrentThisType().isNull() ? 0 : 1)
24743 << AttachPtrExpr->getSourceRange();
24744 continue;
24745 }
24746 }
24747
24748 // Get the declaration from the components
24749 ValueDecl *CurDeclaration = CurComponents.back().getAssociatedDeclaration();
24750 assert(isa<CXXThisExpr>(BE) ||
24751 CurDeclaration &&
24752 "Unexpected null decl for use_device_addr clause.");
24753
24754 MVLI.VarBaseDeclarations.push_back(CurDeclaration);
24755 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24756 MVLI.VarComponents.back().append(CurComponents.begin(),
24757 CurComponents.end());
24758 }
24759
24760 if (MVLI.ProcessedVarList.empty())
24761 return nullptr;
24762
24764 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24765 MVLI.VarComponents);
24766}
24767
24768OMPClause *
24770 const OMPVarListLocTy &Locs) {
24771 MappableVarListInfo MVLI(VarList);
24772 for (Expr *RefExpr : VarList) {
24773 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
24774 SourceLocation ELoc;
24775 SourceRange ERange;
24776 Expr *SimpleRefExpr = RefExpr;
24777 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24778 if (Res.second) {
24779 // It will be analyzed later.
24780 MVLI.ProcessedVarList.push_back(RefExpr);
24781 }
24782 ValueDecl *D = Res.first;
24783 if (!D)
24784 continue;
24785
24786 QualType Type = D->getType();
24787 // item should be a pointer or array or reference to pointer or array
24788 if (!Type.getNonReferenceType()->isPointerType() &&
24789 !Type.getNonReferenceType()->isArrayType()) {
24790 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
24791 << 0 << RefExpr->getSourceRange();
24792 continue;
24793 }
24794
24795 // Check if the declaration in the clause does not show up in any data
24796 // sharing attribute.
24797 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
24798 if (isOpenMPPrivate(DVar.CKind)) {
24799 unsigned OMPVersion = getLangOpts().OpenMP;
24800 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24801 << getOpenMPClauseNameForDiag(DVar.CKind)
24802 << getOpenMPClauseNameForDiag(OMPC_is_device_ptr)
24803 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
24804 OMPVersion);
24806 continue;
24807 }
24808
24809 const Expr *ConflictExpr;
24810 if (DSAStack->checkMappableExprComponentListsForDecl(
24811 D, /*CurrentRegionOnly=*/true,
24812 [&ConflictExpr](
24814 OpenMPClauseKind) -> bool {
24815 ConflictExpr = R.front().getAssociatedExpression();
24816 return true;
24817 })) {
24818 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24819 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
24820 << ConflictExpr->getSourceRange();
24821 continue;
24822 }
24823
24824 // Store the components in the stack so that they can be used to check
24825 // against other clauses later on.
24827 SimpleRefExpr, D, /*IsNonContiguous=*/false);
24828 DSAStack->addMappableExpressionComponents(
24829 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
24830
24831 // Record the expression we've just processed.
24832 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
24833
24834 // Create a mappable component for the list item. List items in this clause
24835 // only need a component. We use a null declaration to signal fields in
24836 // 'this'.
24837 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
24838 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
24839 "Unexpected device pointer expression!");
24840 MVLI.VarBaseDeclarations.push_back(
24841 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
24842 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24843 MVLI.VarComponents.back().push_back(MC);
24844 }
24845
24846 if (MVLI.ProcessedVarList.empty())
24847 return nullptr;
24848
24850 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24851 MVLI.VarComponents);
24852}
24853
24854OMPClause *
24856 const OMPVarListLocTy &Locs) {
24857 MappableVarListInfo MVLI(VarList);
24858 for (Expr *RefExpr : VarList) {
24859 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
24860 SourceLocation ELoc;
24861 SourceRange ERange;
24862 Expr *SimpleRefExpr = RefExpr;
24863 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24864 /*AllowArraySection=*/true);
24865 if (Res.second) {
24866 // It will be analyzed later.
24867 MVLI.ProcessedVarList.push_back(RefExpr);
24868 }
24869 ValueDecl *D = Res.first;
24870 if (!D)
24871 continue;
24872
24873 // Check if the declaration in the clause does not show up in any data
24874 // sharing attribute.
24875 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
24876 if (isOpenMPPrivate(DVar.CKind)) {
24877 unsigned OMPVersion = getLangOpts().OpenMP;
24878 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24879 << getOpenMPClauseNameForDiag(DVar.CKind)
24880 << getOpenMPClauseNameForDiag(OMPC_has_device_addr)
24881 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
24882 OMPVersion);
24884 continue;
24885 }
24886
24887 const Expr *ConflictExpr;
24888 if (DSAStack->checkMappableExprComponentListsForDecl(
24889 D, /*CurrentRegionOnly=*/true,
24890 [&ConflictExpr](
24892 OpenMPClauseKind) -> bool {
24893 ConflictExpr = R.front().getAssociatedExpression();
24894 return true;
24895 })) {
24896 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24897 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
24898 << ConflictExpr->getSourceRange();
24899 continue;
24900 }
24901
24902 // Store the components in the stack so that they can be used to check
24903 // against other clauses later on.
24904 Expr *Component = SimpleRefExpr;
24905 auto *VD = dyn_cast<VarDecl>(D);
24906 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
24907 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
24908 Component =
24909 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
24911 Component, D, /*IsNonContiguous=*/false);
24912 DSAStack->addMappableExpressionComponents(
24913 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
24914
24915 // Record the expression we've just processed.
24916 if (!VD && !SemaRef.CurContext->isDependentContext()) {
24917 DeclRefExpr *Ref =
24918 buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
24919 assert(Ref && "has_device_addr capture failed");
24920 MVLI.ProcessedVarList.push_back(Ref);
24921 } else
24922 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
24923
24924 // Create a mappable component for the list item. List items in this clause
24925 // only need a component. We use a null declaration to signal fields in
24926 // 'this'.
24927 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
24928 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
24929 "Unexpected device pointer expression!");
24930 MVLI.VarBaseDeclarations.push_back(
24931 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
24932 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24933 MVLI.VarComponents.back().push_back(MC);
24934 }
24935
24936 if (MVLI.ProcessedVarList.empty())
24937 return nullptr;
24938
24940 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24941 MVLI.VarComponents);
24942}
24943
24945 Expr *Allocator, Expr *Alignment,
24946 OpenMPAllocateClauseModifier FirstAllocateModifier,
24947 SourceLocation FirstAllocateModifierLoc,
24948 OpenMPAllocateClauseModifier SecondAllocateModifier,
24949 SourceLocation SecondAllocateModifierLoc, ArrayRef<Expr *> VarList,
24950 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
24951 SourceLocation EndLoc) {
24952 if (Allocator) {
24953 // Allocator expression is dependent - skip it for now and build the
24954 // allocator when instantiated.
24955 bool AllocDependent =
24956 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
24957 Allocator->isInstantiationDependent() ||
24958 Allocator->containsUnexpandedParameterPack());
24959 if (!AllocDependent) {
24960 // OpenMP [2.11.4 allocate Clause, Description]
24961 // allocator is an expression of omp_allocator_handle_t type.
24963 return nullptr;
24964
24965 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
24966 if (AllocatorRes.isInvalid())
24967 return nullptr;
24968 AllocatorRes = SemaRef.PerformImplicitConversion(
24969 AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
24971 /*AllowExplicit=*/true);
24972 if (AllocatorRes.isInvalid())
24973 return nullptr;
24974 Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr;
24975 }
24976 } else {
24977 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
24978 // allocate clauses that appear on a target construct or on constructs in a
24979 // target region must specify an allocator expression unless a requires
24980 // directive with the dynamic_allocators clause is present in the same
24981 // compilation unit.
24982 if (getLangOpts().OpenMPIsTargetDevice &&
24983 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
24984 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
24985 }
24986 if (Alignment) {
24987 bool AlignmentDependent = Alignment->isTypeDependent() ||
24988 Alignment->isValueDependent() ||
24989 Alignment->isInstantiationDependent() ||
24991 if (!AlignmentDependent) {
24992 ExprResult AlignResult =
24993 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_allocate);
24994 Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr;
24995 }
24996 }
24997 // Analyze and build list of variables.
24999 for (Expr *RefExpr : VarList) {
25000 assert(RefExpr && "NULL expr in OpenMP allocate clause.");
25001 SourceLocation ELoc;
25002 SourceRange ERange;
25003 Expr *SimpleRefExpr = RefExpr;
25004 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
25005 if (Res.second) {
25006 // It will be analyzed later.
25007 Vars.push_back(RefExpr);
25008 }
25009 ValueDecl *D = Res.first;
25010 if (!D)
25011 continue;
25012
25013 auto *VD = dyn_cast<VarDecl>(D);
25014 DeclRefExpr *Ref = nullptr;
25015 if (!VD && !SemaRef.CurContext->isDependentContext())
25016 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
25017 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
25018 ? RefExpr->IgnoreParens()
25019 : Ref);
25020 }
25021
25022 if (Vars.empty())
25023 return nullptr;
25024
25025 if (Allocator)
25026 DSAStack->addInnerAllocatorExpr(Allocator);
25027
25029 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
25030 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
25031 SecondAllocateModifierLoc, EndLoc, Vars);
25032}
25033
25035 SourceLocation StartLoc,
25036 SourceLocation LParenLoc,
25037 SourceLocation EndLoc) {
25039 for (Expr *RefExpr : VarList) {
25040 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
25041 SourceLocation ELoc;
25042 SourceRange ERange;
25043 Expr *SimpleRefExpr = RefExpr;
25044 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
25045 if (Res.second)
25046 // It will be analyzed later.
25047 Vars.push_back(RefExpr);
25048 ValueDecl *D = Res.first;
25049 if (!D)
25050 continue;
25051
25052 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
25053 // A list-item cannot appear in more than one nontemporal clause.
25054 if (const Expr *PrevRef =
25055 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
25056 Diag(ELoc, diag::err_omp_used_in_clause_twice)
25057 << 0 << getOpenMPClauseNameForDiag(OMPC_nontemporal) << ERange;
25058 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
25059 << getOpenMPClauseNameForDiag(OMPC_nontemporal);
25060 continue;
25061 }
25062
25063 Vars.push_back(RefExpr);
25064 }
25065
25066 if (Vars.empty())
25067 return nullptr;
25068
25069 return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc,
25070 EndLoc, Vars);
25071}
25072
25074 Stmt *AStmt,
25075 SourceLocation StartLoc,
25076 SourceLocation EndLoc) {
25077 if (!AStmt)
25078 return StmtError();
25079
25080 SemaRef.setFunctionHasBranchProtectedScope();
25081
25082 return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
25083 AStmt);
25084}
25085
25087 SourceLocation StartLoc,
25088 SourceLocation LParenLoc,
25089 SourceLocation EndLoc) {
25091 for (Expr *RefExpr : VarList) {
25092 assert(RefExpr && "NULL expr in OpenMP inclusive clause.");
25093 SourceLocation ELoc;
25094 SourceRange ERange;
25095 Expr *SimpleRefExpr = RefExpr;
25096 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
25097 /*AllowArraySection=*/true);
25098 if (Res.second)
25099 // It will be analyzed later.
25100 Vars.push_back(RefExpr);
25101 ValueDecl *D = Res.first;
25102 if (!D)
25103 continue;
25104
25105 const DSAStackTy::DSAVarData DVar =
25106 DSAStack->getTopDSA(D, /*FromParent=*/true);
25107 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
25108 // A list item that appears in the inclusive or exclusive clause must appear
25109 // in a reduction clause with the inscan modifier on the enclosing
25110 // worksharing-loop, worksharing-loop SIMD, or simd construct.
25111 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
25112 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
25113 << RefExpr->getSourceRange();
25114
25115 if (DSAStack->getParentDirective() != OMPD_unknown)
25116 DSAStack->markDeclAsUsedInScanDirective(D);
25117 Vars.push_back(RefExpr);
25118 }
25119
25120 if (Vars.empty())
25121 return nullptr;
25122
25123 return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
25124 EndLoc, Vars);
25125}
25126
25128 SourceLocation StartLoc,
25129 SourceLocation LParenLoc,
25130 SourceLocation EndLoc) {
25132 for (Expr *RefExpr : VarList) {
25133 assert(RefExpr && "NULL expr in OpenMP exclusive clause.");
25134 SourceLocation ELoc;
25135 SourceRange ERange;
25136 Expr *SimpleRefExpr = RefExpr;
25137 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
25138 /*AllowArraySection=*/true);
25139 if (Res.second)
25140 // It will be analyzed later.
25141 Vars.push_back(RefExpr);
25142 ValueDecl *D = Res.first;
25143 if (!D)
25144 continue;
25145
25146 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
25147 DSAStackTy::DSAVarData DVar;
25148 if (ParentDirective != OMPD_unknown)
25149 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
25150 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
25151 // A list item that appears in the inclusive or exclusive clause must appear
25152 // in a reduction clause with the inscan modifier on the enclosing
25153 // worksharing-loop, worksharing-loop SIMD, or simd construct.
25154 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
25155 DVar.Modifier != OMPC_REDUCTION_inscan) {
25156 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
25157 << RefExpr->getSourceRange();
25158 } else {
25159 DSAStack->markDeclAsUsedInScanDirective(D);
25160 }
25161 Vars.push_back(RefExpr);
25162 }
25163
25164 if (Vars.empty())
25165 return nullptr;
25166
25167 return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
25168 EndLoc, Vars);
25169}
25170
25171/// Tries to find omp_alloctrait_t type.
25172static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
25173 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
25174 if (!OMPAlloctraitT.isNull())
25175 return true;
25176 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
25177 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
25178 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
25179 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
25180 return false;
25181 }
25182 Stack->setOMPAlloctraitT(PT.get());
25183 return true;
25184}
25185
25187 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
25189 ASTContext &Context = getASTContext();
25190 // OpenMP [2.12.5, target Construct]
25191 // allocator is an identifier of omp_allocator_handle_t type.
25192 if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack))
25193 return nullptr;
25194 // OpenMP [2.12.5, target Construct]
25195 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
25196 if (llvm::any_of(
25197 Data,
25198 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
25199 !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack))
25200 return nullptr;
25201 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
25202 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
25203 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
25204 StringRef Allocator =
25205 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
25206 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
25207 PredefinedAllocators.insert(SemaRef.LookupSingleName(
25208 SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
25209 }
25210
25212 for (const UsesAllocatorsData &D : Data) {
25213 Expr *AllocatorExpr = nullptr;
25214 // Check allocator expression.
25215 if (D.Allocator->isTypeDependent()) {
25216 AllocatorExpr = D.Allocator;
25217 } else {
25218 // Traits were specified - need to assign new allocator to the specified
25219 // allocator, so it must be an lvalue.
25220 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
25221 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
25222 bool IsPredefinedAllocator = false;
25223 if (DRE) {
25224 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
25225 getAllocatorKind(SemaRef, DSAStack, AllocatorExpr);
25226 IsPredefinedAllocator =
25227 AllocatorTy !=
25228 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
25229 }
25230 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
25231 QualType AllocatorExprType = AllocatorExpr->getType();
25232 bool IsTypeCompatible = IsPredefinedAllocator;
25233 IsTypeCompatible = IsTypeCompatible ||
25234 Context.hasSameUnqualifiedType(AllocatorExprType,
25235 OMPAllocatorHandleT);
25236 IsTypeCompatible =
25237 IsTypeCompatible ||
25238 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
25239 bool IsNonConstantLValue =
25240 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
25241 if (!DRE || !IsTypeCompatible ||
25242 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
25243 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
25244 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
25245 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
25246 continue;
25247 }
25248 // OpenMP [2.12.5, target Construct]
25249 // Predefined allocators appearing in a uses_allocators clause cannot have
25250 // traits specified.
25251 if (IsPredefinedAllocator && D.AllocatorTraits) {
25253 diag::err_omp_predefined_allocator_with_traits)
25255 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
25256 << cast<NamedDecl>(DRE->getDecl())->getName()
25257 << D.Allocator->getSourceRange();
25258 continue;
25259 }
25260 // OpenMP [2.12.5, target Construct]
25261 // Non-predefined allocators appearing in a uses_allocators clause must
25262 // have traits specified.
25263 if (getLangOpts().OpenMP < 52) {
25264 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
25266 diag::err_omp_nonpredefined_allocator_without_traits);
25267 continue;
25268 }
25269 }
25270 // No allocator traits - just convert it to rvalue.
25271 if (!D.AllocatorTraits)
25272 AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
25273 DSAStack->addUsesAllocatorsDecl(
25274 DRE->getDecl(),
25275 IsPredefinedAllocator
25276 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
25277 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
25278 }
25279 Expr *AllocatorTraitsExpr = nullptr;
25280 if (D.AllocatorTraits) {
25282 AllocatorTraitsExpr = D.AllocatorTraits;
25283 } else {
25284 // OpenMP [2.12.5, target Construct]
25285 // Arrays that contain allocator traits that appear in a uses_allocators
25286 // clause must be constant arrays, have constant values and be defined
25287 // in the same scope as the construct in which the clause appears.
25288 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
25289 // Check that traits expr is a constant array.
25290 QualType TraitTy;
25291 if (const ArrayType *Ty =
25292 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
25293 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
25294 TraitTy = ConstArrayTy->getElementType();
25295 if (TraitTy.isNull() ||
25296 !(Context.hasSameUnqualifiedType(TraitTy,
25297 DSAStack->getOMPAlloctraitT()) ||
25298 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
25299 /*CompareUnqualified=*/true))) {
25301 diag::err_omp_expected_array_alloctraits)
25302 << AllocatorTraitsExpr->getType();
25303 continue;
25304 }
25305 // Do not map by default allocator traits if it is a standalone
25306 // variable.
25307 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
25308 DSAStack->addUsesAllocatorsDecl(
25309 DRE->getDecl(),
25310 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
25311 }
25312 }
25313 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
25314 NewD.Allocator = AllocatorExpr;
25315 NewD.AllocatorTraits = AllocatorTraitsExpr;
25316 NewD.LParenLoc = D.LParenLoc;
25317 NewD.RParenLoc = D.RParenLoc;
25318 }
25319 return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc,
25320 EndLoc, NewData);
25321}
25322
25324 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
25325 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
25327 for (Expr *RefExpr : Locators) {
25328 assert(RefExpr && "NULL expr in OpenMP affinity clause.");
25329 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
25330 // It will be analyzed later.
25331 Vars.push_back(RefExpr);
25332 continue;
25333 }
25334
25335 SourceLocation ELoc = RefExpr->getExprLoc();
25336 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
25337
25338 if (!SimpleExpr->isLValue()) {
25339 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
25340 << 1 << 0 << RefExpr->getSourceRange();
25341 continue;
25342 }
25343
25344 ExprResult Res;
25345 {
25347 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
25348 }
25349 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
25351 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
25352 << 1 << 0 << RefExpr->getSourceRange();
25353 continue;
25354 }
25355 Vars.push_back(SimpleExpr);
25356 }
25357
25358 return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc,
25359 ColonLoc, EndLoc, Modifier, Vars);
25360}
25361
25363 SourceLocation KindLoc,
25364 SourceLocation StartLoc,
25365 SourceLocation LParenLoc,
25366 SourceLocation EndLoc) {
25367 if (Kind == OMPC_BIND_unknown) {
25368 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
25369 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
25370 /*Last=*/unsigned(OMPC_BIND_unknown))
25371 << getOpenMPClauseNameForDiag(OMPC_bind);
25372 return nullptr;
25373 }
25374
25375 return OMPBindClause::Create(getASTContext(), Kind, KindLoc, StartLoc,
25376 LParenLoc, EndLoc);
25377}
25378
25380 SourceLocation StartLoc,
25381 SourceLocation LParenLoc,
25382 SourceLocation EndLoc) {
25383 Expr *ValExpr = Size;
25384 Stmt *HelperValStmt = nullptr;
25385
25386 // OpenMP [2.5, Restrictions]
25387 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
25388 // value.
25389 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem,
25390 /*StrictlyPositive=*/false))
25391 return nullptr;
25392
25393 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
25395 DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP);
25396 if (CaptureRegion != OMPD_unknown &&
25397 !SemaRef.CurContext->isDependentContext()) {
25398 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
25399 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
25400 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
25401 HelperValStmt = buildPreInits(getASTContext(), Captures);
25402 }
25403
25405 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
25406}
25407
25411 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc,
25412 SourceLocation M2Loc, SourceLocation EndLoc) {
25413
25414 if ((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ||
25416 std::string Values = getListOfPossibleValues(
25417 OMPC_dyn_groupprivate, /*First=*/0, OMPC_DYN_GROUPPRIVATE_unknown);
25418 Diag((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ? M1Loc
25419 : M2Loc,
25420 diag::err_omp_unexpected_clause_value)
25421 << Values << getOpenMPClauseName(OMPC_dyn_groupprivate);
25422 return nullptr;
25423 }
25424
25425 Expr *ValExpr = Size;
25426 Stmt *HelperValStmt = nullptr;
25427
25428 // OpenMP [2.5, Restrictions]
25429 // The dyn_groupprivate expression must evaluate to a positive integer
25430 // value.
25431 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_dyn_groupprivate,
25432 /*StrictlyPositive=*/false))
25433 return nullptr;
25434
25435 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
25437 DKind, OMPC_dyn_groupprivate, getLangOpts().OpenMP);
25438 if (CaptureRegion != OMPD_unknown &&
25439 !SemaRef.CurContext->isDependentContext()) {
25440 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
25441 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
25442 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
25443 HelperValStmt = buildPreInits(getASTContext(), Captures);
25444 }
25445
25447 StartLoc, LParenLoc, EndLoc, ValExpr, HelperValStmt, CaptureRegion, M1,
25448 M1Loc, M2, M2Loc);
25449}
25450
25453 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
25454 SourceLocation LParenLoc, SourceLocation EndLoc) {
25455
25456 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
25457 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
25458 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
25459 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
25460 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
25461 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_doacross);
25462 return nullptr;
25463 }
25464
25466 DSAStackTy::OperatorOffsetTy OpsOffs;
25467 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
25468 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
25469 SemaRef,
25470 DepType == OMPC_DOACROSS_source ||
25471 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
25472 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
25473 VarList, DSAStack, EndLoc);
25474 Vars = VarOffset.Vars;
25475 OpsOffs = VarOffset.OpsOffs;
25476 TotalDepCount = VarOffset.TotalDepCount;
25477 auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc,
25478 EndLoc, DepType, DepLoc, ColonLoc, Vars,
25479 TotalDepCount.getZExtValue());
25480 if (DSAStack->isParentOrderedRegion())
25481 DSAStack->addDoacrossDependClause(C, OpsOffs);
25482 return C;
25483}
25484
25486 SourceLocation StartLoc,
25487 SourceLocation LParenLoc,
25488 SourceLocation EndLoc) {
25489 return new (getASTContext())
25490 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
25491}
25492
25494 SourceLocation EndLoc) {
25495 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
25496}
25497
25499 SourceLocation LParenLoc,
25500 SourceLocation EndLoc) {
25501 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
25502}
25503
25507 switch (CK) {
25508 case OMPC_absent:
25509 return OMPAbsentClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
25510 case OMPC_contains:
25511 return OMPContainsClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
25512 default:
25513 llvm_unreachable("Unexpected OpenMP clause");
25514 }
25515}
25516
25518 SourceLocation Loc,
25519 SourceLocation RLoc) {
25520 switch (CK) {
25521 case OMPC_no_openmp:
25522 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
25523 case OMPC_no_openmp_routines:
25524 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
25525 case OMPC_no_parallelism:
25526 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
25527 case OMPC_no_openmp_constructs:
25528 return new (getASTContext()) OMPNoOpenMPConstructsClause(Loc, RLoc);
25529 default:
25530 llvm_unreachable("Unexpected OpenMP clause");
25531 }
25532}
25533
25535 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
25536 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
25537 Expr *Stride, SourceLocation RBLoc) {
25538 ASTContext &Context = getASTContext();
25539 if (Base->hasPlaceholderType() &&
25540 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
25541 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
25542 if (Result.isInvalid())
25543 return ExprError();
25544 Base = Result.get();
25545 }
25546 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
25547 ExprResult Result = SemaRef.CheckPlaceholderExpr(LowerBound);
25548 if (Result.isInvalid())
25549 return ExprError();
25550 Result = SemaRef.DefaultLvalueConversion(Result.get());
25551 if (Result.isInvalid())
25552 return ExprError();
25553 LowerBound = Result.get();
25554 }
25555 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
25556 ExprResult Result = SemaRef.CheckPlaceholderExpr(Length);
25557 if (Result.isInvalid())
25558 return ExprError();
25559 Result = SemaRef.DefaultLvalueConversion(Result.get());
25560 if (Result.isInvalid())
25561 return ExprError();
25562 Length = Result.get();
25563 }
25564 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
25565 ExprResult Result = SemaRef.CheckPlaceholderExpr(Stride);
25566 if (Result.isInvalid())
25567 return ExprError();
25568 Result = SemaRef.DefaultLvalueConversion(Result.get());
25569 if (Result.isInvalid())
25570 return ExprError();
25571 Stride = Result.get();
25572 }
25573
25574 // Build an unanalyzed expression if either operand is type-dependent.
25575 if (Base->isTypeDependent() ||
25576 (LowerBound &&
25577 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
25578 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
25579 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
25580 return new (Context) ArraySectionExpr(
25581 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
25582 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
25583 }
25584
25585 // Perform default conversions.
25587 QualType ResultTy;
25588 if (OriginalTy->isAnyPointerType()) {
25589 ResultTy = OriginalTy->getPointeeType();
25590 } else if (OriginalTy->isArrayType()) {
25591 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
25592 } else {
25593 return ExprError(
25594 Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
25595 << Base->getSourceRange());
25596 }
25597 // C99 6.5.2.1p1
25598 if (LowerBound) {
25599 auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
25600 LowerBound);
25601 if (Res.isInvalid())
25602 return ExprError(Diag(LowerBound->getExprLoc(),
25603 diag::err_omp_typecheck_section_not_integer)
25604 << 0 << LowerBound->getSourceRange());
25605 LowerBound = Res.get();
25606
25607 if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25608 LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25609 Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
25610 << 0 << LowerBound->getSourceRange();
25611 }
25612 if (Length) {
25613 auto Res =
25614 PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
25615 if (Res.isInvalid())
25616 return ExprError(Diag(Length->getExprLoc(),
25617 diag::err_omp_typecheck_section_not_integer)
25618 << 1 << Length->getSourceRange());
25619 Length = Res.get();
25620
25621 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25622 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25623 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
25624 << 1 << Length->getSourceRange();
25625 }
25626 if (Stride) {
25627 ExprResult Res =
25629 if (Res.isInvalid())
25630 return ExprError(Diag(Stride->getExprLoc(),
25631 diag::err_omp_typecheck_section_not_integer)
25632 << 1 << Stride->getSourceRange());
25633 Stride = Res.get();
25634
25635 if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25636 Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25637 Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
25638 << 1 << Stride->getSourceRange();
25639 }
25640
25641 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
25642 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
25643 // type. Note that functions are not objects, and that (in C99 parlance)
25644 // incomplete types are not object types.
25645 if (ResultTy->isFunctionType()) {
25646 Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
25647 << ResultTy << Base->getSourceRange();
25648 return ExprError();
25649 }
25650
25651 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
25652 diag::err_omp_section_incomplete_type, Base))
25653 return ExprError();
25654
25655 if (LowerBound && !OriginalTy->isAnyPointerType()) {
25657 if (LowerBound->EvaluateAsInt(Result, Context)) {
25658 // OpenMP 5.0, [2.1.5 Array Sections]
25659 // The array section must be a subset of the original array.
25660 llvm::APSInt LowerBoundValue = Result.Val.getInt();
25661 if (LowerBoundValue.isNegative()) {
25662 Diag(LowerBound->getExprLoc(),
25663 diag::err_omp_section_not_subset_of_array)
25664 << LowerBound->getSourceRange();
25665 return ExprError();
25666 }
25667 }
25668 }
25669
25670 if (Length) {
25672 if (Length->EvaluateAsInt(Result, Context)) {
25673 // OpenMP 5.0, [2.1.5 Array Sections]
25674 // The length must evaluate to non-negative integers.
25675 llvm::APSInt LengthValue = Result.Val.getInt();
25676 if (LengthValue.isNegative()) {
25677 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
25678 << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
25679 << Length->getSourceRange();
25680 return ExprError();
25681 }
25682 }
25683 } else if (SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.isValid() &&
25684 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
25685 !OriginalTy->isVariableArrayType()))) {
25686 // OpenMP 5.0, [2.1.5 Array Sections]
25687 // When the size of the array dimension is not known, the length must be
25688 // specified explicitly.
25689 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
25690 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
25691 return ExprError();
25692 }
25693
25694 if (Stride) {
25696 if (Stride->EvaluateAsInt(Result, Context)) {
25697 // OpenMP 5.0, [2.1.5 Array Sections]
25698 // The stride must evaluate to a positive integer.
25699 llvm::APSInt StrideValue = Result.Val.getInt();
25700 if (!StrideValue.isStrictlyPositive()) {
25701 Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
25702 << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
25703 << Stride->getSourceRange();
25704 return ExprError();
25705 }
25706 }
25707 }
25708
25709 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
25710 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(Base);
25711 if (Result.isInvalid())
25712 return ExprError();
25713 Base = Result.get();
25714 }
25715 return new (Context) ArraySectionExpr(
25716 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
25717 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
25718}
25719
25721 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
25722 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
25723 ASTContext &Context = getASTContext();
25724 if (Base->hasPlaceholderType()) {
25725 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
25726 if (Result.isInvalid())
25727 return ExprError();
25728 Result = SemaRef.DefaultLvalueConversion(Result.get());
25729 if (Result.isInvalid())
25730 return ExprError();
25731 Base = Result.get();
25732 }
25733 QualType BaseTy = Base->getType();
25734 // Delay analysis of the types/expressions if instantiation/specialization is
25735 // required.
25736 if (!BaseTy->isPointerType() && Base->isTypeDependent())
25737 return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
25738 LParenLoc, RParenLoc, Dims, Brackets);
25739 if (!BaseTy->isPointerType() ||
25740 (!Base->isTypeDependent() &&
25741 BaseTy->getPointeeType()->isIncompleteType()))
25742 return ExprError(Diag(Base->getExprLoc(),
25743 diag::err_omp_non_pointer_type_array_shaping_base)
25744 << Base->getSourceRange());
25745
25746 SmallVector<Expr *, 4> NewDims;
25747 bool ErrorFound = false;
25748 for (Expr *Dim : Dims) {
25749 if (Dim->hasPlaceholderType()) {
25750 ExprResult Result = SemaRef.CheckPlaceholderExpr(Dim);
25751 if (Result.isInvalid()) {
25752 ErrorFound = true;
25753 continue;
25754 }
25755 Result = SemaRef.DefaultLvalueConversion(Result.get());
25756 if (Result.isInvalid()) {
25757 ErrorFound = true;
25758 continue;
25759 }
25760 Dim = Result.get();
25761 }
25762 if (!Dim->isTypeDependent()) {
25765 if (Result.isInvalid()) {
25766 ErrorFound = true;
25767 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
25768 << Dim->getSourceRange();
25769 continue;
25770 }
25771 Dim = Result.get();
25772 Expr::EvalResult EvResult;
25773 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
25774 // OpenMP 5.0, [2.1.4 Array Shaping]
25775 // Each si is an integral type expression that must evaluate to a
25776 // positive integer.
25777 llvm::APSInt Value = EvResult.Val.getInt();
25778 if (!Value.isStrictlyPositive()) {
25779 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
25780 << toString(Value, /*Radix=*/10, /*Signed=*/true)
25781 << Dim->getSourceRange();
25782 ErrorFound = true;
25783 continue;
25784 }
25785 }
25786 }
25787 NewDims.push_back(Dim);
25788 }
25789 if (ErrorFound)
25790 return ExprError();
25791 return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
25792 LParenLoc, RParenLoc, NewDims, Brackets);
25793}
25794
25796 SourceLocation IteratorKwLoc,
25797 SourceLocation LLoc,
25798 SourceLocation RLoc,
25800 ASTContext &Context = getASTContext();
25802 bool IsCorrect = true;
25803 for (const OMPIteratorData &D : Data) {
25804 TypeSourceInfo *TInfo = nullptr;
25805 SourceLocation StartLoc;
25806 QualType DeclTy;
25807 if (!D.Type.getAsOpaquePtr()) {
25808 // OpenMP 5.0, 2.1.6 Iterators
25809 // In an iterator-specifier, if the iterator-type is not specified then
25810 // the type of that iterator is of int type.
25811 DeclTy = Context.IntTy;
25812 StartLoc = D.DeclIdentLoc;
25813 } else {
25814 DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo);
25815 StartLoc = TInfo->getTypeLoc().getBeginLoc();
25816 }
25817
25818 bool IsDeclTyDependent = DeclTy->isDependentType() ||
25819 DeclTy->containsUnexpandedParameterPack() ||
25820 DeclTy->isInstantiationDependentType();
25821 if (!IsDeclTyDependent) {
25822 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
25823 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
25824 // The iterator-type must be an integral or pointer type.
25825 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25826 << DeclTy;
25827 IsCorrect = false;
25828 continue;
25829 }
25830 if (DeclTy.isConstant(Context)) {
25831 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
25832 // The iterator-type must not be const qualified.
25833 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25834 << DeclTy;
25835 IsCorrect = false;
25836 continue;
25837 }
25838 }
25839
25840 // Iterator declaration.
25841 assert(D.DeclIdent && "Identifier expected.");
25842 // Always try to create iterator declarator to avoid extra error messages
25843 // about unknown declarations use.
25844 auto *VD =
25845 VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc,
25846 D.DeclIdent, DeclTy, TInfo, SC_None);
25847 VD->setImplicit();
25848 if (S) {
25849 // Check for conflicting previous declaration.
25850 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
25853 Previous.suppressDiagnostics();
25854 SemaRef.LookupName(Previous, S);
25855
25856 SemaRef.FilterLookupForScope(Previous, SemaRef.CurContext, S,
25857 /*ConsiderLinkage=*/false,
25858 /*AllowInlineNamespace=*/false);
25859 if (!Previous.empty()) {
25860 NamedDecl *Old = Previous.getRepresentativeDecl();
25861 Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
25862 Diag(Old->getLocation(), diag::note_previous_definition);
25863 } else {
25864 SemaRef.PushOnScopeChains(VD, S);
25865 }
25866 } else {
25867 SemaRef.CurContext->addDecl(VD);
25868 }
25869
25870 /// Act on the iterator variable declaration.
25872
25873 Expr *Begin = D.Range.Begin;
25874 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
25875 ExprResult BeginRes = SemaRef.PerformImplicitConversion(
25876 Begin, DeclTy, AssignmentAction::Converting);
25877 Begin = BeginRes.get();
25878 }
25879 Expr *End = D.Range.End;
25880 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
25881 ExprResult EndRes = SemaRef.PerformImplicitConversion(
25882 End, DeclTy, AssignmentAction::Converting);
25883 End = EndRes.get();
25884 }
25885 Expr *Step = D.Range.Step;
25886 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
25887 if (!Step->getType()->isIntegralType(Context)) {
25888 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
25889 << Step << Step->getSourceRange();
25890 IsCorrect = false;
25891 continue;
25892 }
25893 std::optional<llvm::APSInt> Result =
25894 Step->getIntegerConstantExpr(Context);
25895 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
25896 // If the step expression of a range-specification equals zero, the
25897 // behavior is unspecified.
25898 if (Result && Result->isZero()) {
25899 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
25900 << Step << Step->getSourceRange();
25901 IsCorrect = false;
25902 continue;
25903 }
25904 }
25905 if (!Begin || !End || !IsCorrect) {
25906 IsCorrect = false;
25907 continue;
25908 }
25909 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
25910 IDElem.IteratorDecl = VD;
25911 IDElem.AssignmentLoc = D.AssignLoc;
25912 IDElem.Range.Begin = Begin;
25913 IDElem.Range.End = End;
25914 IDElem.Range.Step = Step;
25915 IDElem.ColonLoc = D.ColonLoc;
25916 IDElem.SecondColonLoc = D.SecColonLoc;
25917 }
25918 if (!IsCorrect) {
25919 // Invalidate all created iterator declarations if error is found.
25920 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
25921 if (Decl *ID = D.IteratorDecl)
25922 ID->setInvalidDecl();
25923 }
25924 return ExprError();
25925 }
25927 if (!SemaRef.CurContext->isDependentContext()) {
25928 // Build number of ityeration for each iteration range.
25929 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
25930 // ((Begini-Stepi-1-Endi) / -Stepi);
25932 // (Endi - Begini)
25933 ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub,
25934 D.Range.End, D.Range.Begin);
25935 if (!Res.isUsable()) {
25936 IsCorrect = false;
25937 continue;
25938 }
25939 ExprResult St, St1;
25940 if (D.Range.Step) {
25941 St = D.Range.Step;
25942 // (Endi - Begini) + Stepi
25943 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(),
25944 St.get());
25945 if (!Res.isUsable()) {
25946 IsCorrect = false;
25947 continue;
25948 }
25949 // (Endi - Begini) + Stepi - 1
25950 Res = SemaRef.CreateBuiltinBinOp(
25951 D.AssignmentLoc, BO_Sub, Res.get(),
25952 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
25953 if (!Res.isUsable()) {
25954 IsCorrect = false;
25955 continue;
25956 }
25957 // ((Endi - Begini) + Stepi - 1) / Stepi
25958 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(),
25959 St.get());
25960 if (!Res.isUsable()) {
25961 IsCorrect = false;
25962 continue;
25963 }
25964 St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
25965 D.Range.Step);
25966 // (Begini - Endi)
25967 ExprResult Res1 = SemaRef.CreateBuiltinBinOp(
25968 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
25969 if (!Res1.isUsable()) {
25970 IsCorrect = false;
25971 continue;
25972 }
25973 // (Begini - Endi) - Stepi
25974 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(),
25975 St1.get());
25976 if (!Res1.isUsable()) {
25977 IsCorrect = false;
25978 continue;
25979 }
25980 // (Begini - Endi) - Stepi - 1
25981 Res1 = SemaRef.CreateBuiltinBinOp(
25982 D.AssignmentLoc, BO_Sub, Res1.get(),
25983 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
25984 if (!Res1.isUsable()) {
25985 IsCorrect = false;
25986 continue;
25987 }
25988 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
25989 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(),
25990 St1.get());
25991 if (!Res1.isUsable()) {
25992 IsCorrect = false;
25993 continue;
25994 }
25995 // Stepi > 0.
25996 ExprResult CmpRes = SemaRef.CreateBuiltinBinOp(
25997 D.AssignmentLoc, BO_GT, D.Range.Step,
25998 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
25999 if (!CmpRes.isUsable()) {
26000 IsCorrect = false;
26001 continue;
26002 }
26003 Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
26004 CmpRes.get(), Res.get(), Res1.get());
26005 if (!Res.isUsable()) {
26006 IsCorrect = false;
26007 continue;
26008 }
26009 }
26010 Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false);
26011 if (!Res.isUsable()) {
26012 IsCorrect = false;
26013 continue;
26014 }
26015
26016 // Build counter update.
26017 // Build counter.
26018 auto *CounterVD = VarDecl::Create(Context, SemaRef.CurContext,
26019 D.IteratorDecl->getBeginLoc(),
26020 D.IteratorDecl->getBeginLoc(), nullptr,
26021 Res.get()->getType(), nullptr, SC_None);
26022 CounterVD->setImplicit();
26023 ExprResult RefRes =
26024 SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue,
26025 D.IteratorDecl->getBeginLoc());
26026 // Build counter update.
26027 // I = Begini + counter * Stepi;
26028 ExprResult UpdateRes;
26029 if (D.Range.Step) {
26030 UpdateRes = SemaRef.CreateBuiltinBinOp(
26031 D.AssignmentLoc, BO_Mul,
26032 SemaRef.DefaultLvalueConversion(RefRes.get()).get(), St.get());
26033 } else {
26034 UpdateRes = SemaRef.DefaultLvalueConversion(RefRes.get());
26035 }
26036 if (!UpdateRes.isUsable()) {
26037 IsCorrect = false;
26038 continue;
26039 }
26040 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
26041 D.Range.Begin, UpdateRes.get());
26042 if (!UpdateRes.isUsable()) {
26043 IsCorrect = false;
26044 continue;
26045 }
26046 ExprResult VDRes =
26047 SemaRef.BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl),
26048 cast<VarDecl>(D.IteratorDecl)->getType(),
26049 VK_LValue, D.IteratorDecl->getBeginLoc());
26050 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
26051 VDRes.get(), UpdateRes.get());
26052 if (!UpdateRes.isUsable()) {
26053 IsCorrect = false;
26054 continue;
26055 }
26056 UpdateRes =
26057 SemaRef.ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true);
26058 if (!UpdateRes.isUsable()) {
26059 IsCorrect = false;
26060 continue;
26061 }
26062 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
26063 D.AssignmentLoc, UO_PreInc, RefRes.get());
26064 if (!CounterUpdateRes.isUsable()) {
26065 IsCorrect = false;
26066 continue;
26067 }
26068 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(CounterUpdateRes.get(),
26069 /*DiscardedValue=*/true);
26070 if (!CounterUpdateRes.isUsable()) {
26071 IsCorrect = false;
26072 continue;
26073 }
26074 OMPIteratorHelperData &HD = Helpers.emplace_back();
26075 HD.CounterVD = CounterVD;
26076 HD.Upper = Res.get();
26077 HD.Update = UpdateRes.get();
26078 HD.CounterUpdate = CounterUpdateRes.get();
26079 }
26080 } else {
26081 Helpers.assign(ID.size(), {});
26082 }
26083 if (!IsCorrect) {
26084 // Invalidate all created iterator declarations if error is found.
26085 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
26086 if (Decl *ID = D.IteratorDecl)
26087 ID->setInvalidDecl();
26088 }
26089 return ExprError();
26090 }
26091 return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc,
26092 LLoc, RLoc, ID, Helpers);
26093}
26094
26095/// Check if \p AssumptionStr is a known assumption and warn if not.
26097 StringRef AssumptionStr) {
26098 if (llvm::getKnownAssumptionStrings().count(AssumptionStr))
26099 return;
26100
26101 unsigned BestEditDistance = 3;
26102 StringRef Suggestion;
26103 for (const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) {
26104 unsigned EditDistance =
26105 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
26106 if (EditDistance < BestEditDistance) {
26107 Suggestion = KnownAssumptionIt.getKey();
26108 BestEditDistance = EditDistance;
26109 }
26110 }
26111
26112 if (!Suggestion.empty())
26113 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
26114 << AssumptionStr << Suggestion;
26115 else
26116 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
26117 << AssumptionStr;
26118}
26119
26121 // Handle the case where the attribute has a text message.
26122 StringRef Str;
26123 SourceLocation AttrStrLoc;
26124 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
26125 return;
26126
26127 checkOMPAssumeAttr(SemaRef, AttrStrLoc, Str);
26128
26129 D->addAttr(::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
26130}
26131
26133 : 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:794
QualType getUnsignedPointerDiffType() const
Return the unique unsigned counterpart of "ptrdiff_t" integer type.
ASTMutationListener * getASTMutationListener() const
Retrieve a pointer to the AST mutation listener associated with this AST context, if any.
CanQualType VoidPtrTy
void Deallocate(void *Ptr) const
Definition ASTContext.h:870
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
IdentifierTable & Idents
Definition ASTContext.h:790
QualType getUIntPtrType() const
Return a type compatible with "uintptr_t" (C99 7.18.1.4), as defined by the target.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
CanQualType BoolTy
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
CharUnits getAlignOfGlobalVarInChars(QualType T, const VarDecl *VD) const
Return the alignment in characters that should be given to a global variable with type T.
QualType getVariableArrayType(QualType EltTy, Expr *NumElts, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return a non-unique reference to the type for a variable array of the specified element type.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType VoidTy
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:909
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
An abstract interface that should be implemented by listeners that want to be notified when an AST en...
bool isUnset() const
Definition Ownership.h:168
PtrTy get() const
Definition Ownership.h:171
bool isInvalid() const
Definition Ownership.h:167
bool isUsable() const
Definition Ownership.h:169
This class represents BOTH the OpenMP Array Section and OpenACC 'subarray', with a boolean differenti...
Definition Expr.h:7171
Expr * getBase()
Get base of the array section.
Definition Expr.h:7249
Expr * getLength()
Get length of array section.
Definition Expr.h:7259
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition Expr.cpp:5270
Expr * getLowerBound()
Get lower bound of array section.
Definition Expr.h:7253
SourceLocation getColonLocFirst() const
Definition Expr.h:7280
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3723
QualType getElementType() const
Definition TypeBase.h:3735
Attr - This represents one attribute.
Definition Attr.h:45
Represents an attribute applied to a statement.
Definition Stmt.h:2194
static AttributedStmt * Create(const ASTContext &C, SourceLocation Loc, ArrayRef< const Attr * > Attrs, Stmt *SubStmt)
Definition Stmt.cpp:436
SourceLocation getBeginLoc() const
Definition Stmt.h:2233
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4038
Expr * getLHS() const
Definition Expr.h:4088
static bool isRelationalOp(Opcode Opc)
Definition Expr.h:4132
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition Expr.cpp:2179
static Opcode getOpForCompoundAssignment(Opcode Opc)
Definition Expr.h:4185
SourceLocation getOperatorLoc() const
Definition Expr.h:4080
SourceLocation getExprLoc() const
Definition Expr.h:4079
static Opcode reverseComparisonOp(Opcode Opc)
Definition Expr.h:4157
Expr * getRHS() const
Definition Expr.h:4090
Opcode getOpcode() const
Definition Expr.h:4083
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition Expr.cpp:2141
BinaryOperatorKind Opcode
Definition Expr.h:4043
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
CXXBasePath & front()
bool isAmbiguous(CanQualType BaseType) const
Determine whether the path from the most-derived type to the given base type is ambiguous (i....
Represents a C++ constructor within a class.
Definition DeclCXX.h:2604
Represents a C++ conversion function within a class.
Definition DeclCXX.h:2939
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
Definition StmtCXX.h:135
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool hasMutableFields() const
Determine whether this class, or any of its class subobjects, contains a mutable field.
Definition DeclCXX.h:1233
bool hasDefinition() const
Definition DeclCXX.h:561
Represents a C++ nested-name-specifier or a global scope specifier.
Definition DeclSpec.h:73
bool isValid() const
A scope specifier is present, and it refers to a real scope.
Definition DeclSpec.h:185
SourceLocation getBeginLoc() const
Definition DeclSpec.h:83
bool isSet() const
Deprecated.
Definition DeclSpec.h:198
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const
Retrieve a nested-name-specifier with location information, copied into the given AST context.
Definition DeclSpec.cpp:123
bool isInvalid() const
An error occurred during parsing of the scope specifier.
Definition DeclSpec.h:183
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2943
SourceLocation getBeginLoc() const
Definition Expr.h:3277
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
Definition Expr.cpp:1516
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3126
Expr * getCallee()
Definition Expr.h:3090
arg_range arguments()
Definition Expr.h:3195
A wrapper class around a pointer that always points to its canonical declaration.
Represents the body of a CapturedStmt, and serves as its DeclContext.
Definition Decl.h:4940
unsigned getNumParams() const
Definition Decl.h:4978
void setNothrow(bool Nothrow=true)
Definition Decl.cpp:5636
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:5632
ImplicitParamDecl * getParam(unsigned i) const
Definition Decl.h:4980
This captures a statement into a function.
Definition Stmt.h:3918
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
Definition Stmt.cpp:1455
SourceRange getSourceRange() const LLVM_READONLY
Definition Stmt.h:4121
Stmt * getCapturedStmt()
Retrieve the statement being captured.
Definition Stmt.h:4022
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:4113
capture_range captures()
Definition Stmt.h:4056
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3676
Declaration of a class template.
Complex values, per C99 6.2.5p11.
Definition TypeBase.h:3276
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition Stmt.h:1731
SourceLocation getBeginLoc() const
Definition Stmt.h:1845
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
Definition Stmt.cpp:394
ConditionalOperator - The ?
Definition Expr.h:4391
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1449
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2109
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
Definition DeclBase.h:2238
bool isFileContext() const
Definition DeclBase.h:2180
DeclContextLookupResult lookup_result
Definition DeclBase.h:2577
ASTContext & getParentASTContext() const
Definition DeclBase.h:2138
bool isExternCXXContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
bool isNamespace() const
Definition DeclBase.h:2198
bool isTranslationUnit() const
Definition DeclBase.h:2185
void addDecl(Decl *D)
Add the declaration D into this context.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition DeclBase.h:2373
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
bool Encloses(const DeclContext *DC) const
Determine whether this declaration context semantically encloses the declaration context DC.
void addHiddenDecl(Decl *D)
Add the declaration D to this context without modifying any lookup tables.
static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls)
Definition DeclGroup.h:64
Decl * getSingleDecl()
Definition DeclGroup.h:79
bool isSingleDecl() const
Definition DeclGroup.h:76
bool isNull() const
Definition DeclGroup.h:75
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1270
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Definition Expr.cpp:487
ValueDecl * getDecl()
Definition Expr.h:1338
NonOdrUseReason isNonOdrUse() const
Is this expression a non-odr-use reference, and if so, why?
Definition Expr.h:1468
SourceLocation getEndLoc() const LLVM_READONLY
Definition Expr.cpp:550
SourceLocation getBeginLoc() const
Definition Expr.h:1349
ConstexprSpecKind getConstexprSpecifier() const
Definition DeclSpec.h:802
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1622
SourceLocation getEndLoc() const
Definition Stmt.h:1645
const DeclGroupRef getDeclGroup() const
Definition Stmt.h:1640
const Decl * getSingleDecl() const
Definition Stmt.h:1637
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.h:1648
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:573
bool hasAttrs() const
Definition DeclBase.h:518
void addAttr(Attr *A)
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition DeclBase.h:593
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Definition DeclBase.cpp:178
void markUsed(ASTContext &C)
Mark the declaration used, in the sense of odr-use.
Definition DeclBase.cpp:590
bool isReferenced() const
Whether any declaration of this entity was referenced.
Definition DeclBase.cpp:600
bool isCanonicalDecl() const
Whether this particular Decl is a canonical one.
Definition DeclBase.h:984
bool isInvalidDecl() const
Definition DeclBase.h:588
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition DeclBase.h:559
void setAccess(AccessSpecifier AS)
Definition DeclBase.h:502
SourceLocation getLocation() const
Definition DeclBase.h:439
void setImplicit(bool I=true)
Definition DeclBase.h:594
void setReferenced(bool R=true)
Definition DeclBase.h:623
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
Definition DeclBase.h:1049
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
Definition DeclBase.cpp:575
DeclContext * getDeclContext()
Definition DeclBase.h:448
AccessSpecifier getAccess() const
Definition DeclBase.h:507
AttrVec & getAttrs()
Definition DeclBase.h:524
void setDeclContext(DeclContext *DC)
setDeclContext - Set both the semantic and lexical DeclContext to DC.
Definition DeclBase.cpp:382
bool hasAttr() const
Definition DeclBase.h:577
void setLexicalDeclContext(DeclContext *DC)
Definition DeclBase.cpp:386
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition DeclBase.h:978
Kind getKind() const
Definition DeclBase.h:442
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:427
DeclarationName getIdentifier(const IdentifierInfo *ID)
Create a declaration name that is a simple identifier.
The name of a declaration.
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
bool isEmpty() const
Evaluates true when this declaration name is empty.
Information about one declarator, including the parsed type information and the identifier.
Definition DeclSpec.h:1874
const DeclSpec & getDeclSpec() const
getDeclSpec - Return the declaration-specifier that this declarator was declared with.
Definition DeclSpec.h:2021
SourceLocation getIdentifierLoc() const
Definition DeclSpec.h:2310
void SetIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc)
Set the name of this declarator to be the given identifier.
Definition DeclSpec.h:2313
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclSpec.h:2057
void setFunctionDefinitionKind(FunctionDefinitionKind Val)
Definition DeclSpec.h:2707
const CXXScopeSpec & getCXXScopeSpec() const
getCXXScopeSpec - Return the C++ scope specifier (global scope or nested-name-specifier) that is part...
Definition DeclSpec.h:2036
bool isInvalidType() const
Definition DeclSpec.h:2688
const IdentifierInfo * getIdentifier() const
Definition DeclSpec.h:2304
virtual bool TraverseStmt(MaybeConst< Stmt > *S)
RAII object that enters a new expression evaluation context.
This represents one expression.
Definition Expr.h:112
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
bool isIntegerConstantExpr(const ASTContext &Ctx) const
bool isGLValue() const
Definition Expr.h:287
@ SE_AllowSideEffects
Allow any unmodeled side effect.
Definition Expr.h:674
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition Expr.cpp:3094
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition Expr.h:177
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition Expr.h:444
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition Expr.h:194
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
Definition Expr.h:241
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Skip past any parentheses and lvalue casts which might surround this expression until reaching a fixe...
Definition Expr.cpp:3106
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:3089
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3077
bool containsErrors() const
Whether this expression contains subexpressions which had errors.
Definition Expr.h:246
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3085
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition Expr.h:284
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition Expr.h:451
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition Expr.h:223
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3069
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:276
QualType getType() const
Definition Expr.h:144
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
Definition Decl.h:3160
bool isBitField() const
Determines whether this field is a bitfield.
Definition Decl.h:3263
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp: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:1075
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition Stmt.h:2879
Stmt * getBody()
Definition Stmt.h:2923
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:5269
One of these records is kept for each identifier that is lexed.
void setMangledOpenMPVariantName(bool I)
Set whether this is the mangled name of an OpenMP variant.
StringRef getName() const
Return the actual identifier string.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IfStmt - This represents an if/then/else.
Definition Stmt.h:2250
Stmt * getThen()
Definition Stmt.h:2339
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:2327
Stmt * getElse()
Definition Stmt.h:2348
SourceLocation getBeginLoc() const
Definition Stmt.h:2462
ImaginaryLiteral - We support imaginary integer and floating point literals, like "1....
Definition Expr.h:1731
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition Expr.cpp:2072
ImplicitConversionSequence - Represents an implicit conversion sequence, which may be a standard conv...
Definition Overload.h:621
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateCopy(SourceLocation InitLoc, SourceLocation EqualLoc, bool AllowExplicitConvs=false)
Create a copy initialization.
Describes the sequence of initializations required to initialize a given object or reference with a s...
ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)
Perform the actual initialization of the given entity based on the computed initialization sequence.
Describes an entity that is being initialized.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Definition Expr.cpp:974
Describes the capture of a variable or of this, or of a C++1y init-capture.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
A class for iterating through a result set and possibly filtering out results.
Definition Lookup.h:677
Represents the results of name lookup.
Definition Lookup.h:147
LLVM_ATTRIBUTE_REINITIALIZES void clear()
Clears out any current state.
Definition Lookup.h:607
DeclClass * getAsSingle() const
Definition Lookup.h:558
bool empty() const
Return true if no decls were found.
Definition Lookup.h:362
Filter makeFilter()
Create a filter for this result set.
Definition Lookup.h:751
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
Definition Lookup.h:569
bool isAmbiguous() const
Definition Lookup.h:324
bool isSingleResult() const
Determines if this names a single result which is not an unresolved value using decl.
Definition Lookup.h:331
NamedDecl * getRepresentativeDecl() const
Fetches a representative decl. Useful for lazy diagnostics.
Definition Lookup.h:576
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
Definition Lookup.h:636
iterator end() const
Definition Lookup.h:359
static bool isVisible(Sema &SemaRef, NamedDecl *D)
Determine whether the given declaration is visible to the program.
iterator begin() const
Definition Lookup.h:358
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition Expr.h:3447
Expr * getBase() const
Definition Expr.h:3441
static MemberExpr * CreateImplicit(const ASTContext &C, Expr *Base, bool IsArrow, ValueDecl *MemberDecl, QualType T, ExprValueKind VK, ExprObjectKind OK)
Create an implicit MemberExpr, with no location, qualifier, template arguments, and so on.
Definition Expr.h:3425
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:3559
This represents a decl that may have a name.
Definition Decl.h:274
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:295
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:340
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
Definition Decl.h:317
virtual void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const
Appends a human-readable name for this declaration into the given stream.
Definition Decl.cpp: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:5378
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 std::pair< const Expr *, std::optional< size_t > > findAttachPtrExpr(MappableExprComponentListRef Components, OpenMPDirectiveKind CurDirKind)
Find the attach pointer expression from a list of mappable expression components.
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:5505
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:5076
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
Definition Type.cpp:2867
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition TypeBase.h:8382
QualType withRestrict() const
Definition TypeBase.h:1175
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
Definition Type.cpp:3556
QualType withConst() const
Definition TypeBase.h:1159
void addConst()
Add the const type qualifier to this QualType.
Definition TypeBase.h:1156
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8293
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:8478
QualType getCanonicalType() const
Definition TypeBase.h:8345
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8387
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:8447
const Type * getTypePtrOrNull() const
Definition TypeBase.h:8297
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:3574
Scope - A scope is a transient data structure that is used while parsing the program.
Definition Scope.h:41
bool isDeclScope(const Decl *D) const
isDeclScope - Return true if this is the scope that the specified decl is declared in.
Definition Scope.h:398
Scope * getBreakParent()
getBreakParent - Return the closest scope that a break statement would be affected by.
Definition Scope.h:322
bool isOpenMPOrderClauseScope() const
Determine whether this scope is some OpenMP directive with order clause which specifies concurrent sc...
Definition Scope.h:558
const Scope * getParent() const
getParent - Return the scope that this is nested in.
Definition Scope.h:287
bool isOpenMPLoopScope() const
Determine whether this scope is a loop having OpenMP loop directive attached.
Definition Scope.h:551
@ OpenMPOrderClauseScope
This is a scope of some OpenMP directive with order clause which specifies concurrent.
Definition Scope.h:150
A generic diagnostic builder for errors which may or may not be deferred.
Definition SemaBase.h:111
SemaBase(Sema &S)
Definition SemaBase.cpp:7
ASTContext & getASTContext() const
Definition SemaBase.cpp:9
Sema & SemaRef
Definition SemaBase.h:40
const LangOptions & getLangOpts() const
Definition SemaBase.cpp:11
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Definition SemaBase.cpp:61
StmtResult ActOnOpenMPTargetParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel for' after parsing of the associated statement.
OMPClause * ActOnOpenMPNocontextClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nocontext' clause.
OMPClause * ActOnOpenMPXDynCGroupMemClause(Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_dyn_cgroup_mem' clause.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid)
Called at the end of 'pragma omp declare reduction'.
bool isInOpenMPTaskUntiedContext() const
Return true if currently in OpenMP task with untied clause context.
OMPClause * ActOnOpenMPUntiedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'untied' clause.
OMPClause * ActOnOpenMPSafelenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'safelen' clause.
OMPClause * ActOnOpenMPThreadsetClause(OpenMPThreadsetKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'threadset' clause.
OMPClause * ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'holds' clause.
StmtResult ActOnOpenMPParallelMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop simd' after parsing of the associated sta...
StmtResult ActOnOpenMPParallelMasterDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel master' after parsing of the associated statement.
StmtResult ActOnOpenMPDispatchDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp dispatch' after parsing of the.
OMPClause * ActOnOpenMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'read' clause.
OMPClause * ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'filter' clause.
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)
Finish current declare reduction construct initializer.
ExprResult ActOnOpenMPCall(ExprResult Call, Scope *Scope, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig)
Given the potential call expression Call, determine if there is a specialization via the OpenMP decla...
void setOpenMPDeviceNum(int Num)
Setter and getter functions for device_num.
OMPClause * ActOnOpenMPFullClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-form 'full' clauses.
StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target enter data' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'detach' clause.
OMPClause * ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'use' clause.
OMPClause * ActOnOpenMPFailClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'fail' clause.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for simd' after parsing of the as...
StmtResult ActOnOpenMPAssumeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Process an OpenMP assume directive.
void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called once a target context is completed, that can be when a 'pragma omp end declare target' was enc...
OMPClause * ActOnOpenMPDirectivePresenceClause(OpenMPClauseKind CK, llvm::ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
Called on well-formed 'absent' or 'contains' clauses.
void tryCaptureOpenMPLambdas(ValueDecl *V)
Function tries to capture lambda's captured variables in the OpenMP region before the original lambda...
StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel masked' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for' after parsing of the associa...
OMPClause * ActOnOpenMPPrivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'private' clause.
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, SourceLocation StartLoc, DeclarationName VN)
Build the mapper variable of 'pragma omp declare mapper'.
OMPClause * ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc, SourceLocation LParenLoc=SourceLocation(), Expr *NumForLoops=nullptr)
Called on well-formed 'ordered' clause.
OMPClause * ActOnOpenMPSelfMapsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'self_maps' clause.
bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, OpenMPLinearClauseKind LinKind, QualType Type, bool IsDeclareSimd=false)
Checks that the specified declaration matches requirements for the linear decls.
OMPClause * ActOnOpenMPIsDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'is_device_ptr' clause.
OMPClause * ActOnOpenMPHasDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'has_device_addr' clause.
StmtResult ActOnOpenMPErrorDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, bool InExContext=true)
Called on well-formed '#pragma omp error'.
OMPClause * ActOnOpenMPPartialClause(Expr *FactorExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'partial' clauses.
StmtResult ActOnOpenMPSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPLastprivateClause(ArrayRef< Expr * > VarList, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'lastprivate' clause.
void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT, DeclareTargetContextInfo &DTCI)
Called on correct id-expression from the 'pragma omp declare target'.
DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef< OMPClause * > ClauseList)
Called on well-formed 'pragma omp requires'.
OMPGroupPrivateDecl * CheckOMPGroupPrivateDecl(SourceLocation Loc, ArrayRef< Expr * > VarList)
Builds a new OpenMPGroupPrivateDecl and checks its correctness.
StmtResult ActOnOpenMPDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPFirstprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'firstprivate' clause.
StmtResult ActOnOpenMPDepobjDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp depobj'.
ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK, ExprObjectKind OK, SourceLocation Loc)
OMPClause * ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'priority' clause.
OMPClause * ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, ArrayRef< unsigned > Arguments, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, ArrayRef< SourceLocation > ArgumentsLoc, SourceLocation DelimLoc, SourceLocation EndLoc)
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< Expr * > AdjustArgsNothing, ArrayRef< Expr * > AdjustArgsNeedDevicePtr, ArrayRef< Expr * > AdjustArgsNeedDeviceAddr, ArrayRef< OMPInteropInfo > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)
Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.
StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target parallel' after parsing of the associated statement.
OMPClause * ActOnOpenMPDistScheduleClause(OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'dist_schedule' clause.
OpenMPClauseKind isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, unsigned CapLevel) const
Check if the specified variable is used in 'private' clause.
OMPClause * ActOnOpenMPLoopRangeClause(Expr *First, Expr *Count, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc)
Called on well-form 'looprange' clause after parsing its arguments.
OMPClause * ActOnOpenMPPermutationClause(ArrayRef< Expr * > PermExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'permutation' clause after parsing its arguments.
OMPClause * ActOnOpenMPNontemporalClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nontemporal' clause.
OMPClause * ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'bind' clause.
OMPClause * ActOnOpenMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'threads' clause.
OMPClause * ActOnOpenMPThreadLimitClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'thread_limit' clause.
OMPClause * ActOnOpenMPSharedClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'shared' clause.
StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target exit data' after parsing of the associated statement.
StmtResult ActOnOpenMPTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPCopyinClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyin' clause.
OMPClause * ActOnOpenMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'mergeable' clause.
void startOpenMPCXXRangeFor()
If the current region is a range loop-based region, mark the start of the loop construct.
OMPClause * ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'destroy' clause.
StmtResult ActOnOpenMPParallelMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop' after parsing of the associated statemen...
OMPClause * ActOnOpenMPAffinityClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Called on well-formed 'affinity' clause.
OMPClause * ActOnOpenMPCompareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'compare' clause.
StmtResult ActOnOpenMPFuseDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp fuse' after parsing of its clauses and the associated statement.
OMPClause * ActOnOpenMPNumTeamsClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_teams' clause.
StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel sections' after parsing of the associated statement.
OMPClause * ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'update' clause.
OMPClause * ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data, Expr *DepModifier, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depend' clause.
OMPClause * ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'doacross' clause.
VarDecl * ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
StmtResult ActOnOpenMPTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for' after parsing of the associated sta...
StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp master' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskgroup'.
VarDecl * isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo=false, unsigned StopAt=0)
Check if the specified variable is used in one of the private clauses (private, firstprivate,...
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:7754
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition Sema.h:12476
Abstract base class used for diagnosing integer constant expression violations.
Definition Sema.h:7705
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:855
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:9315
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
Definition Sema.h:9356
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
Definition Sema.h:9358
@ LookupAnyName
Look up any declaration with any name.
Definition Sema.h:9360
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:4730
@ 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:79
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
Definition SemaExpr.cpp:754
ASTContext & getASTContext() const
Definition Sema.h:926
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:9308
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:919
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:9307
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:15429
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:15384
void setFunctionHasBranchProtectedScope()
Definition Sema.cpp:2498
std::pair< StringRef, QualType > CapturedParamNameType
Definition Sema.h:11208
ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS=nullptr, bool isClassName=false, bool HasTrailingDot=false, ParsedType ObjectType=nullptr, bool IsCtorOrDtorName=false, bool WantNontrivialTypeSourceInfo=false, bool IsClassTemplateDeductionContext=true, ImplicitTypenameContext AllowImplicitTypename=ImplicitTypenameContext::No, IdentifierInfo **CorrectedII=nullptr)
If the identifier refers to a type name within this scope, return the declaration of that type.
Definition SemaDecl.cpp:274
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
@ PotentiallyEvaluated
The current expression is potentially evaluated at run time, which means that code may be generated t...
Definition Sema.h:6727
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
Definition Sema.h:6696
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:7768
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition Sema.h:8643
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:1484
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:8264
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:8275
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:9072
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:8633
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
Definition Type.cpp:2067
bool isArrayType() const
Definition TypeBase.h:8629
bool isArithmeticType() const
Definition Type.cpp:2338
bool isPointerType() const
Definition TypeBase.h:8530
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:8936
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9179
bool isReferenceType() const
Definition TypeBase.h:8554
bool isEnumeralType() const
Definition TypeBase.h:8661
bool isScalarType() const
Definition TypeBase.h:8994
bool isVariableArrayType() const
Definition TypeBase.h:8641
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
Definition Type.cpp:2104
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:753
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
Definition Type.cpp:2292
bool isAnyCharacterType() const
Determine whether this type is any of the built-in character types.
Definition Type.cpp:2169
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
Definition TypeBase.h:8886
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition TypeBase.h:2791
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition TypeBase.h:8861
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition TypeBase.h:2783
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
Definition Type.cpp:2412
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
bool isAnyComplexType() const
Definition TypeBase.h:8665
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
Definition TypeBase.h:2405
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition Type.cpp:2244
bool isFunctionProtoType() const
Definition TypeBase.h:2601
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
Definition TypeBase.h:9035
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2801
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition TypeBase.h:9165
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition Type.cpp:2436
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
Definition TypeBase.h:9129
bool isFunctionType() const
Definition TypeBase.h:8526
bool isStructureOrClassType() const
Definition Type.cpp:707
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2321
bool isFloatingType() const
Definition Type.cpp:2305
bool isAnyPointerType() const
Definition TypeBase.h:8538
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9112
bool isRecordType() const
Definition TypeBase.h:8657
bool isUnionType() const
Definition Type.cpp:719
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:3635
const Expr * getExprStmt() const
Definition Stmt.cpp:415
Represents a variable declaration or definition.
Definition Decl.h:926
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition Decl.cpp: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:666
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:5889
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
Definition OpenMPKinds.h:28
bool isOpenMPNestingDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a distribute directive in the outerm...
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
OpenMPOrderClauseKind
OpenMP attributes for 'order' clause.
@ OMPC_ORDER_unknown
@ Implicit
An implicit conversion.
Definition Sema.h:439
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:5354
llvm::SmallVector< Expr *, 4 > PreferTypes
Iterator definition representation.
Definition ExprOpenMP.h:160
Helper expressions and declaration for OMPIteratorExpr class for each iteration space.
Definition ExprOpenMP.h:111
Expr * CounterUpdate
Updater for the internal counter: ++CounterVD;.
Definition ExprOpenMP.h:121
Expr * Upper
Normalized upper bound.
Definition ExprOpenMP.h:116
Expr * Update
Update expression for the originally specified iteration variable, calculated as VD = Begin + Counter...
Definition ExprOpenMP.h:119
VarDecl * CounterVD
Internal normalized counter.
Definition ExprOpenMP.h:113
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.