clang 23.0.0git
SemaOpenMP.cpp
Go to the documentation of this file.
1//===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ---------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file implements semantic analysis for OpenMP directives and
10/// clauses.
11///
12//===----------------------------------------------------------------------===//
13
16
17#include "TreeTransform.h"
21#include "clang/AST/Decl.h"
22#include "clang/AST/DeclCXX.h"
26#include "clang/AST/StmtCXX.h"
35#include "clang/Sema/Lookup.h"
37#include "clang/Sema/Scope.h"
39#include "clang/Sema/Sema.h"
40#include "llvm/ADT/IndexedMap.h"
41#include "llvm/ADT/PointerEmbeddedInt.h"
42#include "llvm/ADT/STLExtras.h"
43#include "llvm/ADT/Sequence.h"
44#include "llvm/ADT/SetVector.h"
45#include "llvm/ADT/SmallSet.h"
46#include "llvm/ADT/StringExtras.h"
47#include "llvm/Frontend/OpenMP/OMPAssume.h"
48#include "llvm/Frontend/OpenMP/OMPConstants.h"
49#include "llvm/IR/Assumptions.h"
50#include <optional>
51
52using namespace clang;
53using namespace llvm::omp;
54
55//===----------------------------------------------------------------------===//
56// Stack of data-sharing attributes for variables
57//===----------------------------------------------------------------------===//
58
60 Sema &SemaRef, Expr *E,
62 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
63
65
66namespace {
67/// Default data sharing attributes, which can be applied to directive.
68enum DefaultDataSharingAttributes {
69 DSA_unspecified = 0, /// Data sharing attribute not specified.
70 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
71 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
72 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
73 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
74};
75
76/// Variable Category attributes to restrict the modifier of the
77/// default clause (DefaultDataSharingAttributes)
78/// Not mentioning any Variable category attribute indicates
79/// the modifier (DefaultDataSharingAttributes) is for all variables.
80enum DefaultDataSharingVCAttributes {
81 DSA_VC_all = 0, /// for all variables.
82 DSA_VC_aggregate, /// for aggregate variables.
83 DSA_VC_pointer, /// for pointer variables.
84 DSA_VC_scalar, /// for scalar variables.
85};
86
87/// Stack for tracking declarations used in OpenMP directives and
88/// clauses and their data-sharing attributes.
89class DSAStackTy {
90public:
91 struct DSAVarData {
92 OpenMPDirectiveKind DKind = OMPD_unknown;
93 OpenMPClauseKind CKind = OMPC_unknown;
94 unsigned Modifier = 0;
95 const Expr *RefExpr = nullptr;
96 DeclRefExpr *PrivateCopy = nullptr;
97 SourceLocation ImplicitDSALoc;
98 bool AppliedToPointee = false;
99 DSAVarData() = default;
100 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
101 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
102 SourceLocation ImplicitDSALoc, unsigned Modifier,
103 bool AppliedToPointee)
104 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
105 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
106 AppliedToPointee(AppliedToPointee) {}
107 };
108 using OperatorOffsetTy =
109 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
110 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
111 /// Kind of the declaration used in the uses_allocators clauses.
112 enum class UsesAllocatorsDeclKind {
113 /// Predefined allocator
114 PredefinedAllocator,
115 /// User-defined allocator
116 UserDefinedAllocator,
117 /// The declaration that represent allocator trait
118 AllocatorTrait,
119 };
120
121private:
122 struct DSAInfo {
123 OpenMPClauseKind Attributes = OMPC_unknown;
124 unsigned Modifier = 0;
125 /// Pointer to a reference expression and a flag which shows that the
126 /// variable is marked as lastprivate(true) or not (false).
127 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
128 DeclRefExpr *PrivateCopy = nullptr;
129 /// true if the attribute is applied to the pointee, not the variable
130 /// itself.
131 bool AppliedToPointee = false;
132 };
133 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
134 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
135 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
136 using LoopControlVariablesMapTy =
137 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
138 /// Struct that associates a component with the clause kind where they are
139 /// found.
140 struct MappedExprComponentTy {
142 OpenMPClauseKind Kind = OMPC_unknown;
143 };
144 using MappedExprComponentsTy =
145 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
146 using CriticalsWithHintsTy =
147 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
148 struct ReductionData {
149 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
150 SourceRange ReductionRange;
151 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
152 ReductionData() = default;
153 void set(BinaryOperatorKind BO, SourceRange RR) {
154 ReductionRange = RR;
155 ReductionOp = BO;
156 }
157 void set(const Expr *RefExpr, SourceRange RR) {
158 ReductionRange = RR;
159 ReductionOp = RefExpr;
160 }
161 };
162 using DeclReductionMapTy =
163 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
164 struct DefaultmapInfo {
165 OpenMPDefaultmapClauseModifier ImplicitBehavior =
167 SourceLocation SLoc;
168 DefaultmapInfo() = default;
169 DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc)
170 : ImplicitBehavior(M), SLoc(Loc) {}
171 };
172
173 struct SharingMapTy {
174 DeclSAMapTy SharingMap;
175 DeclReductionMapTy ReductionMap;
176 UsedRefMapTy AlignedMap;
177 UsedRefMapTy NontemporalMap;
178 MappedExprComponentsTy MappedExprComponents;
179 LoopControlVariablesMapTy LCVMap;
180 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
181 SourceLocation DefaultAttrLoc;
182 DefaultDataSharingVCAttributes DefaultVCAttr = DSA_VC_all;
183 SourceLocation DefaultAttrVCLoc;
184 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1];
185 OpenMPDirectiveKind Directive = OMPD_unknown;
186 DeclarationNameInfo DirectiveName;
187 Scope *CurScope = nullptr;
188 DeclContext *Context = nullptr;
189 SourceLocation ConstructLoc;
190 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
191 /// get the data (loop counters etc.) about enclosing loop-based construct.
192 /// This data is required during codegen.
193 DoacrossClauseMapTy DoacrossDepends;
194 /// First argument (Expr *) contains optional argument of the
195 /// 'ordered' clause, the second one is true if the regions has 'ordered'
196 /// clause, false otherwise.
197 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
198 bool RegionHasOrderConcurrent = false;
199 unsigned AssociatedLoops = 1;
200 bool HasMutipleLoops = false;
201 const Decl *PossiblyLoopCounter = nullptr;
202 bool NowaitRegion = false;
203 bool UntiedRegion = false;
204 bool CancelRegion = false;
205 bool LoopStart = false;
206 bool BodyComplete = false;
207 SourceLocation PrevScanLocation;
208 SourceLocation PrevOrderedLocation;
209 SourceLocation InnerTeamsRegionLoc;
210 /// Reference to the taskgroup task_reduction reference expression.
211 Expr *TaskgroupReductionRef = nullptr;
212 llvm::DenseSet<QualType> MappedClassesQualTypes;
213 SmallVector<Expr *, 4> InnerUsedAllocators;
214 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
215 /// List of globals marked as declare target link in this target region
216 /// (isOpenMPTargetExecutionDirective(Directive) == true).
217 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
218 /// List of decls used in inclusive/exclusive clauses of the scan directive.
219 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
220 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
221 UsesAllocatorsDecls;
222 /// Data is required on creating capture fields for implicit
223 /// default first|private clause.
224 struct ImplicitDefaultFDInfoTy {
225 /// Field decl.
226 const FieldDecl *FD = nullptr;
227 /// Nesting stack level
228 size_t StackLevel = 0;
229 /// Capture variable decl.
230 VarDecl *VD = nullptr;
231 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
232 VarDecl *VD)
233 : FD(FD), StackLevel(StackLevel), VD(VD) {}
234 };
235 /// List of captured fields
236 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
237 ImplicitDefaultFirstprivateFDs;
238 Expr *DeclareMapperVar = nullptr;
239 SmallVector<VarDecl *, 16> IteratorVarDecls;
240 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
241 Scope *CurScope, SourceLocation Loc)
242 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
243 ConstructLoc(Loc) {}
244 SharingMapTy() = default;
245 };
246
247 using StackTy = SmallVector<SharingMapTy, 4>;
248
249 /// Stack of used declaration and their data-sharing attributes.
250 DeclSAMapTy Threadprivates;
251 DeclSAMapTy Groupprivates;
252 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
253 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
254 /// true, if check for DSA must be from parent directive, false, if
255 /// from current directive.
256 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
257 Sema &SemaRef;
258 bool ForceCapturing = false;
259 /// true if all the variables in the target executable directives must be
260 /// captured by reference.
261 bool ForceCaptureByReferenceInTargetExecutable = false;
262 CriticalsWithHintsTy Criticals;
263 unsigned IgnoredStackElements = 0;
264
265 /// Iterators over the stack iterate in order from innermost to outermost
266 /// directive.
267 using const_iterator = StackTy::const_reverse_iterator;
268 const_iterator begin() const {
269 return Stack.empty() ? const_iterator()
270 : Stack.back().first.rbegin() + IgnoredStackElements;
271 }
272 const_iterator end() const {
273 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
274 }
275 using iterator = StackTy::reverse_iterator;
276 iterator begin() {
277 return Stack.empty() ? iterator()
278 : Stack.back().first.rbegin() + IgnoredStackElements;
279 }
280 iterator end() {
281 return Stack.empty() ? iterator() : Stack.back().first.rend();
282 }
283
284 // Convenience operations to get at the elements of the stack.
285
286 bool isStackEmpty() const {
287 return Stack.empty() ||
288 Stack.back().second != CurrentNonCapturingFunctionScope ||
289 Stack.back().first.size() <= IgnoredStackElements;
290 }
291 size_t getStackSize() const {
292 return isStackEmpty() ? 0
293 : Stack.back().first.size() - IgnoredStackElements;
294 }
295
296 SharingMapTy *getTopOfStackOrNull() {
297 size_t Size = getStackSize();
298 if (Size == 0)
299 return nullptr;
300 return &Stack.back().first[Size - 1];
301 }
302 const SharingMapTy *getTopOfStackOrNull() const {
303 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
304 }
305 SharingMapTy &getTopOfStack() {
306 assert(!isStackEmpty() && "no current directive");
307 return *getTopOfStackOrNull();
308 }
309 const SharingMapTy &getTopOfStack() const {
310 return const_cast<DSAStackTy &>(*this).getTopOfStack();
311 }
312
313 SharingMapTy *getSecondOnStackOrNull() {
314 size_t Size = getStackSize();
315 if (Size <= 1)
316 return nullptr;
317 return &Stack.back().first[Size - 2];
318 }
319 const SharingMapTy *getSecondOnStackOrNull() const {
320 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
321 }
322
323 /// Get the stack element at a certain level (previously returned by
324 /// \c getNestingLevel).
325 ///
326 /// Note that nesting levels count from outermost to innermost, and this is
327 /// the reverse of our iteration order where new inner levels are pushed at
328 /// the front of the stack.
329 SharingMapTy &getStackElemAtLevel(unsigned Level) {
330 assert(Level < getStackSize() && "no such stack element");
331 return Stack.back().first[Level];
332 }
333 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
334 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
335 }
336
337 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
338
339 /// Checks if the variable is a local for OpenMP region.
340 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
341
342 /// Vector of previously declared requires directives
343 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
344 /// omp_allocator_handle_t type.
345 QualType OMPAllocatorHandleT;
346 /// omp_depend_t type.
347 QualType OMPDependT;
348 /// omp_event_handle_t type.
349 QualType OMPEventHandleT;
350 /// omp_alloctrait_t type.
351 QualType OMPAlloctraitT;
352 /// Expression for the predefined allocators.
353 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
354 nullptr};
355 /// Vector of previously encountered target directives
356 SmallVector<SourceLocation, 2> TargetLocations;
357 SourceLocation AtomicLocation;
358 /// Vector of declare variant construct traits.
359 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
360
361public:
362 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
363
364 /// Sets omp_allocator_handle_t type.
365 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
366 /// Gets omp_allocator_handle_t type.
367 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
368 /// Sets omp_alloctrait_t type.
369 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
370 /// Gets omp_alloctrait_t type.
371 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
372 /// Sets the given default allocator.
373 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
374 Expr *Allocator) {
375 OMPPredefinedAllocators[AllocatorKind] = Allocator;
376 }
377 /// Returns the specified default allocator.
378 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
379 return OMPPredefinedAllocators[AllocatorKind];
380 }
381 /// Sets omp_depend_t type.
382 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
383 /// Gets omp_depend_t type.
384 QualType getOMPDependT() const { return OMPDependT; }
385
386 /// Sets omp_event_handle_t type.
387 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
388 /// Gets omp_event_handle_t type.
389 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
390
391 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
392 OpenMPClauseKind getClauseParsingMode() const {
393 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
394 return ClauseKindMode;
395 }
396 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
397
398 bool isBodyComplete() const {
399 const SharingMapTy *Top = getTopOfStackOrNull();
400 return Top && Top->BodyComplete;
401 }
402 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
403
404 bool isForceVarCapturing() const { return ForceCapturing; }
405 void setForceVarCapturing(bool V) { ForceCapturing = V; }
406
407 void setForceCaptureByReferenceInTargetExecutable(bool V) {
408 ForceCaptureByReferenceInTargetExecutable = V;
409 }
410 bool isForceCaptureByReferenceInTargetExecutable() const {
411 return ForceCaptureByReferenceInTargetExecutable;
412 }
413
414 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
415 Scope *CurScope, SourceLocation Loc) {
416 assert(!IgnoredStackElements &&
417 "cannot change stack while ignoring elements");
418 if (Stack.empty() ||
419 Stack.back().second != CurrentNonCapturingFunctionScope)
420 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
421 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
422 Stack.back().first.back().DefaultAttrLoc = Loc;
423 }
424
425 void pop() {
426 assert(!IgnoredStackElements &&
427 "cannot change stack while ignoring elements");
428 assert(!Stack.back().first.empty() &&
429 "Data-sharing attributes stack is empty!");
430 Stack.back().first.pop_back();
431 }
432
433 /// RAII object to temporarily leave the scope of a directive when we want to
434 /// logically operate in its parent.
435 class ParentDirectiveScope {
436 DSAStackTy &Self;
437 bool Active;
438
439 public:
440 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
441 : Self(Self), Active(false) {
442 if (Activate)
443 enable();
444 }
445 ~ParentDirectiveScope() { disable(); }
446 void disable() {
447 if (Active) {
448 --Self.IgnoredStackElements;
449 Active = false;
450 }
451 }
452 void enable() {
453 if (!Active) {
454 ++Self.IgnoredStackElements;
455 Active = true;
456 }
457 }
458 };
459
460 /// Marks that we're started loop parsing.
461 void loopInit() {
462 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
463 "Expected loop-based directive.");
464 getTopOfStack().LoopStart = true;
465 }
466 /// Start capturing of the variables in the loop context.
467 void loopStart() {
468 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
469 "Expected loop-based directive.");
470 getTopOfStack().LoopStart = false;
471 }
472 /// true, if variables are captured, false otherwise.
473 bool isLoopStarted() const {
474 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
475 "Expected loop-based directive.");
476 return !getTopOfStack().LoopStart;
477 }
478 /// Marks (or clears) declaration as possibly loop counter.
479 void resetPossibleLoopCounter(const Decl *D = nullptr) {
480 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
481 }
482 /// Gets the possible loop counter decl.
483 const Decl *getPossiblyLoopCounter() const {
484 return getTopOfStack().PossiblyLoopCounter;
485 }
486 /// Start new OpenMP region stack in new non-capturing function.
487 void pushFunction() {
488 assert(!IgnoredStackElements &&
489 "cannot change stack while ignoring elements");
490 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
491 assert(!isa<CapturingScopeInfo>(CurFnScope));
492 CurrentNonCapturingFunctionScope = CurFnScope;
493 }
494 /// Pop region stack for non-capturing function.
495 void popFunction(const FunctionScopeInfo *OldFSI) {
496 assert(!IgnoredStackElements &&
497 "cannot change stack while ignoring elements");
498 if (!Stack.empty() && Stack.back().second == OldFSI) {
499 assert(Stack.back().first.empty());
500 Stack.pop_back();
501 }
502 CurrentNonCapturingFunctionScope = nullptr;
503 for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
504 if (!isa<CapturingScopeInfo>(FSI)) {
505 CurrentNonCapturingFunctionScope = FSI;
506 break;
507 }
508 }
509 }
510
511 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
512 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
513 }
514 std::pair<const OMPCriticalDirective *, llvm::APSInt>
515 getCriticalWithHint(const DeclarationNameInfo &Name) const {
516 auto I = Criticals.find(Name.getAsString());
517 if (I != Criticals.end())
518 return I->second;
519 return std::make_pair(nullptr, llvm::APSInt());
520 }
521 /// If 'aligned' declaration for given variable \a D was not seen yet,
522 /// add it and return NULL; otherwise return previous occurrence's expression
523 /// for diagnostics.
524 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
525 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
526 /// add it and return NULL; otherwise return previous occurrence's expression
527 /// for diagnostics.
528 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
529
530 /// Register specified variable as loop control variable.
531 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
532 /// Check if the specified variable is a loop control variable for
533 /// current region.
534 /// \return The index of the loop control variable in the list of associated
535 /// for-loops (from outer to inner).
536 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
537 /// Check if the specified variable is a loop control variable for
538 /// parent region.
539 /// \return The index of the loop control variable in the list of associated
540 /// for-loops (from outer to inner).
541 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
542 /// Check if the specified variable is a loop control variable for
543 /// current region.
544 /// \return The index of the loop control variable in the list of associated
545 /// for-loops (from outer to inner).
546 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
547 unsigned Level) const;
548 /// Get the loop control variable for the I-th loop (or nullptr) in
549 /// parent directive.
550 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
551
552 /// Marks the specified decl \p D as used in scan directive.
553 void markDeclAsUsedInScanDirective(ValueDecl *D) {
554 if (SharingMapTy *Stack = getSecondOnStackOrNull())
555 Stack->UsedInScanDirective.insert(D);
556 }
557
558 /// Checks if the specified declaration was used in the inner scan directive.
559 bool isUsedInScanDirective(ValueDecl *D) const {
560 if (const SharingMapTy *Stack = getTopOfStackOrNull())
561 return Stack->UsedInScanDirective.contains(D);
562 return false;
563 }
564
565 /// Adds explicit data sharing attribute to the specified declaration.
566 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
567 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
568 bool AppliedToPointee = false);
569
570 /// Adds additional information for the reduction items with the reduction id
571 /// represented as an operator.
572 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
574 /// Adds additional information for the reduction items with the reduction id
575 /// represented as reduction identifier.
576 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
577 const Expr *ReductionRef);
578 /// Returns the location and reduction operation from the innermost parent
579 /// region for the given \p D.
580 const DSAVarData
581 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
583 Expr *&TaskgroupDescriptor) const;
584 /// Returns the location and reduction operation from the innermost parent
585 /// region for the given \p D.
586 const DSAVarData
587 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
588 const Expr *&ReductionRef,
589 Expr *&TaskgroupDescriptor) const;
590 /// Return reduction reference expression for the current taskgroup or
591 /// parallel/worksharing directives with task reductions.
592 Expr *getTaskgroupReductionRef() const {
593 assert((getTopOfStack().Directive == OMPD_taskgroup ||
594 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
595 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
596 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
597 "taskgroup reference expression requested for non taskgroup or "
598 "parallel/worksharing directive.");
599 return getTopOfStack().TaskgroupReductionRef;
600 }
601 /// Checks if the given \p VD declaration is actually a taskgroup reduction
602 /// descriptor variable at the \p Level of OpenMP regions.
603 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
604 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
605 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
606 ->getDecl() == VD;
607 }
608
609 /// Returns data sharing attributes from top of the stack for the
610 /// specified declaration.
611 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
612 /// Returns data-sharing attributes for the specified declaration.
613 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
614 /// Returns data-sharing attributes for the specified declaration.
615 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
616 /// Checks if the specified variables has data-sharing attributes which
617 /// match specified \a CPred predicate in any directive which matches \a DPred
618 /// predicate.
619 const DSAVarData
620 hasDSA(ValueDecl *D,
621 const llvm::function_ref<bool(OpenMPClauseKind, bool,
622 DefaultDataSharingAttributes)>
623 CPred,
624 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
625 bool FromParent) const;
626 /// Checks if the specified variables has data-sharing attributes which
627 /// match specified \a CPred predicate in any innermost directive which
628 /// matches \a DPred predicate.
629 const DSAVarData
630 hasInnermostDSA(ValueDecl *D,
631 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
632 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
633 bool FromParent) const;
634 /// Checks if the specified variables has explicit data-sharing
635 /// attributes which match specified \a CPred predicate at the specified
636 /// OpenMP region.
637 bool
638 hasExplicitDSA(const ValueDecl *D,
639 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
640 unsigned Level, bool NotLastprivate = false) const;
641
642 /// Returns true if the directive at level \Level matches in the
643 /// specified \a DPred predicate.
644 bool hasExplicitDirective(
645 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
646 unsigned Level) const;
647
648 /// Finds a directive which matches specified \a DPred predicate.
649 bool hasDirective(
650 const llvm::function_ref<bool(
651 OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)>
652 DPred,
653 bool FromParent) const;
654
655 /// Returns currently analyzed directive.
656 OpenMPDirectiveKind getCurrentDirective() const {
657 const SharingMapTy *Top = getTopOfStackOrNull();
658 return Top ? Top->Directive : OMPD_unknown;
659 }
660 /// Returns directive kind at specified level.
661 OpenMPDirectiveKind getDirective(unsigned Level) const {
662 assert(!isStackEmpty() && "No directive at specified level.");
663 return getStackElemAtLevel(Level).Directive;
664 }
665 /// Returns the capture region at the specified level.
666 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
667 unsigned OpenMPCaptureLevel) const {
668 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
669 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
670 return CaptureRegions[OpenMPCaptureLevel];
671 }
672 /// Returns parent directive.
673 OpenMPDirectiveKind getParentDirective() const {
674 const SharingMapTy *Parent = getSecondOnStackOrNull();
675 return Parent ? Parent->Directive : OMPD_unknown;
676 }
677
678 /// Add requires decl to internal vector
679 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
680
681 /// Checks if the defined 'requires' directive has specified type of clause.
682 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
683 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
684 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
685 return isa<ClauseType>(C);
686 });
687 });
688 }
689
690 /// Checks for a duplicate clause amongst previously declared requires
691 /// directives
692 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
693 bool IsDuplicate = false;
694 for (OMPClause *CNew : ClauseList) {
695 for (const OMPRequiresDecl *D : RequiresDecls) {
696 for (const OMPClause *CPrev : D->clauselists()) {
697 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
698 SemaRef.Diag(CNew->getBeginLoc(),
699 diag::err_omp_requires_clause_redeclaration)
700 << getOpenMPClauseNameForDiag(CNew->getClauseKind());
701 SemaRef.Diag(CPrev->getBeginLoc(),
702 diag::note_omp_requires_previous_clause)
703 << getOpenMPClauseNameForDiag(CPrev->getClauseKind());
704 IsDuplicate = true;
705 }
706 }
707 }
708 }
709 return IsDuplicate;
710 }
711
712 /// Add location of previously encountered target to internal vector
713 void addTargetDirLocation(SourceLocation LocStart) {
714 TargetLocations.push_back(LocStart);
715 }
716
717 /// Add location for the first encountered atomic directive.
718 void addAtomicDirectiveLoc(SourceLocation Loc) {
719 if (AtomicLocation.isInvalid())
720 AtomicLocation = Loc;
721 }
722
723 /// Returns the location of the first encountered atomic directive in the
724 /// module.
725 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
726
727 // Return previously encountered target region locations.
728 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
729 return TargetLocations;
730 }
731
732 /// Set default data sharing attribute to none.
733 void setDefaultDSANone(SourceLocation Loc) {
734 getTopOfStack().DefaultAttr = DSA_none;
735 getTopOfStack().DefaultAttrLoc = Loc;
736 }
737 /// Set default data sharing attribute to shared.
738 void setDefaultDSAShared(SourceLocation Loc) {
739 getTopOfStack().DefaultAttr = DSA_shared;
740 getTopOfStack().DefaultAttrLoc = Loc;
741 }
742 /// Set default data sharing attribute to private.
743 void setDefaultDSAPrivate(SourceLocation Loc) {
744 getTopOfStack().DefaultAttr = DSA_private;
745 getTopOfStack().DefaultAttrLoc = Loc;
746 }
747 /// Set default data sharing attribute to firstprivate.
748 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
749 getTopOfStack().DefaultAttr = DSA_firstprivate;
750 getTopOfStack().DefaultAttrLoc = Loc;
751 }
752 /// Set default data sharing variable category attribute to aggregate.
753 void setDefaultDSAVCAggregate(SourceLocation VCLoc) {
754 getTopOfStack().DefaultVCAttr = DSA_VC_aggregate;
755 getTopOfStack().DefaultAttrVCLoc = VCLoc;
756 }
757 /// Set default data sharing variable category attribute to all.
758 void setDefaultDSAVCAll(SourceLocation VCLoc) {
759 getTopOfStack().DefaultVCAttr = DSA_VC_all;
760 getTopOfStack().DefaultAttrVCLoc = VCLoc;
761 }
762 /// Set default data sharing variable category attribute to pointer.
763 void setDefaultDSAVCPointer(SourceLocation VCLoc) {
764 getTopOfStack().DefaultVCAttr = DSA_VC_pointer;
765 getTopOfStack().DefaultAttrVCLoc = VCLoc;
766 }
767 /// Set default data sharing variable category attribute to scalar.
768 void setDefaultDSAVCScalar(SourceLocation VCLoc) {
769 getTopOfStack().DefaultVCAttr = DSA_VC_scalar;
770 getTopOfStack().DefaultAttrVCLoc = VCLoc;
771 }
772 /// Set default data mapping attribute to Modifier:Kind
773 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
774 OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) {
775 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
776 DMI.ImplicitBehavior = M;
777 DMI.SLoc = Loc;
778 }
779 /// Check whether the implicit-behavior has been set in defaultmap
780 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
781 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
782 return getTopOfStack()
783 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
784 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
785 getTopOfStack()
786 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
787 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
788 getTopOfStack()
789 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
790 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
791 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
793 }
794
795 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
796 return ConstructTraits;
797 }
798 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
799 bool ScopeEntry) {
800 if (ScopeEntry)
801 ConstructTraits.append(Traits.begin(), Traits.end());
802 else
803 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
804 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
805 assert(Top == Trait && "Something left a trait on the stack!");
806 (void)Trait;
807 (void)Top;
808 }
809 }
810
811 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
812 return getStackSize() <= Level ? DSA_unspecified
813 : getStackElemAtLevel(Level).DefaultAttr;
814 }
815 DefaultDataSharingAttributes getDefaultDSA() const {
816 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
817 }
818 SourceLocation getDefaultDSALocation() const {
819 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
820 }
822 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
823 return isStackEmpty()
825 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
826 }
828 getDefaultmapModifierAtLevel(unsigned Level,
829 OpenMPDefaultmapClauseKind Kind) const {
830 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
831 }
832 bool isDefaultmapCapturedByRef(unsigned Level,
833 OpenMPDefaultmapClauseKind Kind) const {
835 getDefaultmapModifierAtLevel(Level, Kind);
836 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
837 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
838 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
839 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
840 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
841 (M == OMPC_DEFAULTMAP_MODIFIER_present) ||
842 (M == OMPC_DEFAULTMAP_MODIFIER_storage);
843 }
844 return true;
845 }
846 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
848 switch (Kind) {
849 case OMPC_DEFAULTMAP_scalar:
850 case OMPC_DEFAULTMAP_pointer:
851 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
852 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
853 (M == OMPC_DEFAULTMAP_MODIFIER_default);
854 case OMPC_DEFAULTMAP_aggregate:
855 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
856 default:
857 break;
858 }
859 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
860 }
861 bool mustBeFirstprivateAtLevel(unsigned Level,
862 OpenMPDefaultmapClauseKind Kind) const {
864 getDefaultmapModifierAtLevel(Level, Kind);
865 return mustBeFirstprivateBase(M, Kind);
866 }
867 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
868 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
869 return mustBeFirstprivateBase(M, Kind);
870 }
871
872 /// Checks if the specified variable is a threadprivate.
873 bool isThreadPrivate(VarDecl *D) {
874 const DSAVarData DVar = getTopDSA(D, false);
875 return isOpenMPThreadPrivate(DVar.CKind);
876 }
877
878 /// Marks current region as ordered (it has an 'ordered' clause).
879 void setOrderedRegion(bool IsOrdered, const Expr *Param,
880 OMPOrderedClause *Clause) {
881 if (IsOrdered)
882 getTopOfStack().OrderedRegion.emplace(Param, Clause);
883 else
884 getTopOfStack().OrderedRegion.reset();
885 }
886 /// Returns true, if region is ordered (has associated 'ordered' clause),
887 /// false - otherwise.
888 bool isOrderedRegion() const {
889 if (const SharingMapTy *Top = getTopOfStackOrNull())
890 return Top->OrderedRegion.has_value();
891 return false;
892 }
893 /// Returns optional parameter for the ordered region.
894 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
895 if (const SharingMapTy *Top = getTopOfStackOrNull())
896 if (Top->OrderedRegion)
897 return *Top->OrderedRegion;
898 return std::make_pair(nullptr, nullptr);
899 }
900 /// Returns true, if parent region is ordered (has associated
901 /// 'ordered' clause), false - otherwise.
902 bool isParentOrderedRegion() const {
903 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
904 return Parent->OrderedRegion.has_value();
905 return false;
906 }
907 /// Returns optional parameter for the ordered region.
908 std::pair<const Expr *, OMPOrderedClause *>
909 getParentOrderedRegionParam() const {
910 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
911 if (Parent->OrderedRegion)
912 return *Parent->OrderedRegion;
913 return std::make_pair(nullptr, nullptr);
914 }
915 /// Marks current region as having an 'order' clause.
916 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
917 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
918 }
919 /// Returns true, if parent region is order (has associated
920 /// 'order' clause), false - otherwise.
921 bool isParentOrderConcurrent() const {
922 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
923 return Parent->RegionHasOrderConcurrent;
924 return false;
925 }
926 /// Marks current region as nowait (it has a 'nowait' clause).
927 void setNowaitRegion(bool IsNowait = true) {
928 getTopOfStack().NowaitRegion = IsNowait;
929 }
930 /// Returns true, if parent region is nowait (has associated
931 /// 'nowait' clause), false - otherwise.
932 bool isParentNowaitRegion() const {
933 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
934 return Parent->NowaitRegion;
935 return false;
936 }
937 /// Marks current region as untied (it has a 'untied' clause).
938 void setUntiedRegion(bool IsUntied = true) {
939 getTopOfStack().UntiedRegion = IsUntied;
940 }
941 /// Return true if current region is untied.
942 bool isUntiedRegion() const {
943 const SharingMapTy *Top = getTopOfStackOrNull();
944 return Top ? Top->UntiedRegion : false;
945 }
946 /// Marks parent region as cancel region.
947 void setParentCancelRegion(bool Cancel = true) {
948 if (SharingMapTy *Parent = getSecondOnStackOrNull())
949 Parent->CancelRegion |= Cancel;
950 }
951 /// Return true if current region has inner cancel construct.
952 bool isCancelRegion() const {
953 const SharingMapTy *Top = getTopOfStackOrNull();
954 return Top ? Top->CancelRegion : false;
955 }
956
957 /// Mark that parent region already has scan directive.
958 void setParentHasScanDirective(SourceLocation Loc) {
959 if (SharingMapTy *Parent = getSecondOnStackOrNull())
960 Parent->PrevScanLocation = Loc;
961 }
962 /// Return true if current region has inner cancel construct.
963 bool doesParentHasScanDirective() const {
964 const SharingMapTy *Top = getSecondOnStackOrNull();
965 return Top ? Top->PrevScanLocation.isValid() : false;
966 }
967 /// Return true if current region has inner cancel construct.
968 SourceLocation getParentScanDirectiveLoc() const {
969 const SharingMapTy *Top = getSecondOnStackOrNull();
970 return Top ? Top->PrevScanLocation : SourceLocation();
971 }
972 /// Mark that parent region already has ordered directive.
973 void setParentHasOrderedDirective(SourceLocation Loc) {
974 if (SharingMapTy *Parent = getSecondOnStackOrNull())
975 Parent->PrevOrderedLocation = Loc;
976 }
977 /// Return true if current region has inner ordered construct.
978 bool doesParentHasOrderedDirective() const {
979 const SharingMapTy *Top = getSecondOnStackOrNull();
980 return Top ? Top->PrevOrderedLocation.isValid() : false;
981 }
982 /// Returns the location of the previously specified ordered directive.
983 SourceLocation getParentOrderedDirectiveLoc() const {
984 const SharingMapTy *Top = getSecondOnStackOrNull();
985 return Top ? Top->PrevOrderedLocation : SourceLocation();
986 }
987
988 /// Set collapse value for the region.
989 void setAssociatedLoops(unsigned Val) {
990 getTopOfStack().AssociatedLoops = Val;
991 if (Val > 1)
992 getTopOfStack().HasMutipleLoops = true;
993 }
994 /// Return collapse value for region.
995 unsigned getAssociatedLoops() const {
996 const SharingMapTy *Top = getTopOfStackOrNull();
997 return Top ? Top->AssociatedLoops : 0;
998 }
999 /// Returns true if the construct is associated with multiple loops.
1000 bool hasMutipleLoops() const {
1001 const SharingMapTy *Top = getTopOfStackOrNull();
1002 return Top ? Top->HasMutipleLoops : false;
1003 }
1004
1005 /// Marks current target region as one with closely nested teams
1006 /// region.
1007 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
1008 if (SharingMapTy *Parent = getSecondOnStackOrNull())
1009 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
1010 }
1011 /// Returns true, if current region has closely nested teams region.
1012 bool hasInnerTeamsRegion() const {
1013 return getInnerTeamsRegionLoc().isValid();
1014 }
1015 /// Returns location of the nested teams region (if any).
1016 SourceLocation getInnerTeamsRegionLoc() const {
1017 const SharingMapTy *Top = getTopOfStackOrNull();
1018 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
1019 }
1020
1021 Scope *getCurScope() const {
1022 const SharingMapTy *Top = getTopOfStackOrNull();
1023 return Top ? Top->CurScope : nullptr;
1024 }
1025 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
1026 SourceLocation getConstructLoc() const {
1027 const SharingMapTy *Top = getTopOfStackOrNull();
1028 return Top ? Top->ConstructLoc : SourceLocation();
1029 }
1030
1031 /// Do the check specified in \a Check to all component lists and return true
1032 /// if any issue is found.
1033 bool checkMappableExprComponentListsForDecl(
1034 const ValueDecl *VD, bool CurrentRegionOnly,
1035 const llvm::function_ref<
1038 Check) const {
1039 if (isStackEmpty())
1040 return false;
1041 auto SI = begin();
1042 auto SE = end();
1043
1044 if (SI == SE)
1045 return false;
1046
1047 if (CurrentRegionOnly)
1048 SE = std::next(SI);
1049 else
1050 std::advance(SI, 1);
1051
1052 for (; SI != SE; ++SI) {
1053 auto MI = SI->MappedExprComponents.find(VD);
1054 if (MI != SI->MappedExprComponents.end())
1056 MI->second.Components)
1057 if (Check(L, MI->second.Kind))
1058 return true;
1059 }
1060 return false;
1061 }
1062
1063 /// Do the check specified in \a Check to all component lists at a given level
1064 /// and return true if any issue is found.
1065 bool checkMappableExprComponentListsForDeclAtLevel(
1066 const ValueDecl *VD, unsigned Level,
1067 const llvm::function_ref<
1070 Check) const {
1071 if (getStackSize() <= Level)
1072 return false;
1073
1074 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1075 auto MI = StackElem.MappedExprComponents.find(VD);
1076 if (MI != StackElem.MappedExprComponents.end())
1078 MI->second.Components)
1079 if (Check(L, MI->second.Kind))
1080 return true;
1081 return false;
1082 }
1083
1084 /// Create a new mappable expression component list associated with a given
1085 /// declaration and initialize it with the provided list of components.
1086 void addMappableExpressionComponents(
1087 const ValueDecl *VD,
1089 OpenMPClauseKind WhereFoundClauseKind) {
1090 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1091 // Create new entry and append the new components there.
1092 MEC.Components.resize(MEC.Components.size() + 1);
1093 MEC.Components.back().append(Components.begin(), Components.end());
1094 MEC.Kind = WhereFoundClauseKind;
1095 }
1096
1097 unsigned getNestingLevel() const {
1098 assert(!isStackEmpty());
1099 return getStackSize() - 1;
1100 }
1101 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1102 SharingMapTy *Parent = getSecondOnStackOrNull();
1103 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1104 Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1105 }
1106 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1107 getDoacrossDependClauses() const {
1108 const SharingMapTy &StackElem = getTopOfStack();
1109 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1110 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1111 return llvm::make_range(Ref.begin(), Ref.end());
1112 }
1113 return llvm::make_range(StackElem.DoacrossDepends.end(),
1114 StackElem.DoacrossDepends.end());
1115 }
1116
1117 // Store types of classes which have been explicitly mapped
1118 void addMappedClassesQualTypes(QualType QT) {
1119 SharingMapTy &StackElem = getTopOfStack();
1120 StackElem.MappedClassesQualTypes.insert(QT);
1121 }
1122
1123 // Return set of mapped classes types
1124 bool isClassPreviouslyMapped(QualType QT) const {
1125 const SharingMapTy &StackElem = getTopOfStack();
1126 return StackElem.MappedClassesQualTypes.contains(QT);
1127 }
1128
1129 /// Adds global declare target to the parent target region.
1130 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1131 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1132 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1133 "Expected declare target link global.");
1134 for (auto &Elem : *this) {
1135 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1136 Elem.DeclareTargetLinkVarDecls.push_back(E);
1137 return;
1138 }
1139 }
1140 }
1141
1142 /// Returns the list of globals with declare target link if current directive
1143 /// is target.
1144 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1145 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1146 "Expected target executable directive.");
1147 return getTopOfStack().DeclareTargetLinkVarDecls;
1148 }
1149
1150 /// Adds list of allocators expressions.
1151 void addInnerAllocatorExpr(Expr *E) {
1152 getTopOfStack().InnerUsedAllocators.push_back(E);
1153 }
1154 /// Return list of used allocators.
1155 ArrayRef<Expr *> getInnerAllocators() const {
1156 return getTopOfStack().InnerUsedAllocators;
1157 }
1158 /// Marks the declaration as implicitly firstprivate nin the task-based
1159 /// regions.
1160 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1161 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1162 }
1163 /// Checks if the decl is implicitly firstprivate in the task-based region.
1164 bool isImplicitTaskFirstprivate(Decl *D) const {
1165 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1166 }
1167
1168 /// Marks decl as used in uses_allocators clause as the allocator.
1169 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1170 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1171 }
1172 /// Checks if specified decl is used in uses allocator clause as the
1173 /// allocator.
1174 std::optional<UsesAllocatorsDeclKind>
1175 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1176 const SharingMapTy &StackElem = getTopOfStack();
1177 auto I = StackElem.UsesAllocatorsDecls.find(D);
1178 if (I == StackElem.UsesAllocatorsDecls.end())
1179 return std::nullopt;
1180 return I->getSecond();
1181 }
1182 std::optional<UsesAllocatorsDeclKind>
1183 isUsesAllocatorsDecl(const Decl *D) const {
1184 const SharingMapTy &StackElem = getTopOfStack();
1185 auto I = StackElem.UsesAllocatorsDecls.find(D);
1186 if (I == StackElem.UsesAllocatorsDecls.end())
1187 return std::nullopt;
1188 return I->getSecond();
1189 }
1190
1191 void addDeclareMapperVarRef(Expr *Ref) {
1192 SharingMapTy &StackElem = getTopOfStack();
1193 StackElem.DeclareMapperVar = Ref;
1194 }
1195 const Expr *getDeclareMapperVarRef() const {
1196 const SharingMapTy *Top = getTopOfStackOrNull();
1197 return Top ? Top->DeclareMapperVar : nullptr;
1198 }
1199
1200 /// Add a new iterator variable.
1201 void addIteratorVarDecl(VarDecl *VD) {
1202 SharingMapTy &StackElem = getTopOfStack();
1203 StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl());
1204 }
1205 /// Check if variable declaration is an iterator VarDecl.
1206 bool isIteratorVarDecl(const VarDecl *VD) const {
1207 const SharingMapTy *Top = getTopOfStackOrNull();
1208 if (!Top)
1209 return false;
1210
1211 return llvm::is_contained(Top->IteratorVarDecls, VD->getCanonicalDecl());
1212 }
1213 /// get captured field from ImplicitDefaultFirstprivateFDs
1214 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1215 const_iterator I = begin();
1216 const_iterator EndI = end();
1217 size_t StackLevel = getStackSize();
1218 for (; I != EndI; ++I) {
1219 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1220 break;
1221 StackLevel--;
1222 }
1223 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1224 if (I == EndI)
1225 return nullptr;
1226 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1227 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1228 return IFD.VD;
1229 return nullptr;
1230 }
1231 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1232 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1233 const_iterator I = begin();
1234 const_iterator EndI = end();
1235 for (; I != EndI; ++I)
1236 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1237 break;
1238 if (I == EndI)
1239 return false;
1240 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1241 if (IFD.VD == VD)
1242 return true;
1243 return false;
1244 }
1245 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1246 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1247 iterator I = begin();
1248 const_iterator EndI = end();
1249 size_t StackLevel = getStackSize();
1250 for (; I != EndI; ++I) {
1251 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1252 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1253 break;
1254 }
1255 StackLevel--;
1256 }
1257 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1258 }
1259};
1260
1261bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1262 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1263}
1264
1265bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1266 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1267 DKind == OMPD_unknown;
1268}
1269
1270} // namespace
1271
1272static const Expr *getExprAsWritten(const Expr *E) {
1273 if (const auto *FE = dyn_cast<FullExpr>(E))
1274 E = FE->getSubExpr();
1275
1276 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1277 E = MTE->getSubExpr();
1278
1279 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1280 E = Binder->getSubExpr();
1281
1282 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1283 E = ICE->getSubExprAsWritten();
1284 return E->IgnoreParens();
1285}
1286
1288 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1289}
1290
1291static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1292 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1293 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1294 D = ME->getMemberDecl();
1295
1297 return D;
1298}
1299
1301 return const_cast<ValueDecl *>(
1302 getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1303}
1304
1306 if (C == OMPC_threadprivate)
1307 return getOpenMPClauseName(C).str() + " or thread local";
1308 return getOpenMPClauseName(C).str();
1309}
1310
1311DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1312 ValueDecl *D) const {
1313 D = getCanonicalDecl(D);
1314 auto *VD = dyn_cast<VarDecl>(D);
1315 const auto *FD = dyn_cast<FieldDecl>(D);
1316 DSAVarData DVar;
1317 if (Iter == end()) {
1318 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1319 // in a region but not in construct]
1320 // File-scope or namespace-scope variables referenced in called routines
1321 // in the region are shared unless they appear in a threadprivate
1322 // directive.
1323 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1324 DVar.CKind = OMPC_shared;
1325
1326 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1327 // in a region but not in construct]
1328 // Variables with static storage duration that are declared in called
1329 // routines in the region are shared.
1330 if (VD && VD->hasGlobalStorage())
1331 DVar.CKind = OMPC_shared;
1332
1333 // Non-static data members are shared by default.
1334 if (FD)
1335 DVar.CKind = OMPC_shared;
1336
1337 return DVar;
1338 }
1339
1340 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1341 // in a Construct, C/C++, predetermined, p.1]
1342 // Variables with automatic storage duration that are declared in a scope
1343 // inside the construct are private.
1344 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1345 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1346 DVar.CKind = OMPC_private;
1347 return DVar;
1348 }
1349
1350 DVar.DKind = Iter->Directive;
1351 // Explicitly specified attributes and local variables with predetermined
1352 // attributes.
1353 if (Iter->SharingMap.count(D)) {
1354 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1355 DVar.RefExpr = Data.RefExpr.getPointer();
1356 DVar.PrivateCopy = Data.PrivateCopy;
1357 DVar.CKind = Data.Attributes;
1358 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1359 DVar.Modifier = Data.Modifier;
1360 DVar.AppliedToPointee = Data.AppliedToPointee;
1361 return DVar;
1362 }
1363
1364 DefaultDataSharingAttributes IterDA = Iter->DefaultAttr;
1365 switch (Iter->DefaultVCAttr) {
1366 case DSA_VC_aggregate:
1367 if (!D->getType()->isAggregateType())
1368 IterDA = DSA_none;
1369 break;
1370 case DSA_VC_pointer:
1371 if (!D->getType()->isPointerType())
1372 IterDA = DSA_none;
1373 break;
1374 case DSA_VC_scalar:
1375 if (!D->getType()->isScalarType())
1376 IterDA = DSA_none;
1377 break;
1378 case DSA_VC_all:
1379 break;
1380 }
1381
1382 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1383 // in a Construct, C/C++, implicitly determined, p.1]
1384 // In a parallel or task construct, the data-sharing attributes of these
1385 // variables are determined by the default clause, if present.
1386 switch (IterDA) {
1387 case DSA_shared:
1388 DVar.CKind = OMPC_shared;
1389 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1390 return DVar;
1391 case DSA_none:
1392 return DVar;
1393 case DSA_firstprivate:
1394 if (VD && VD->getStorageDuration() == SD_Static &&
1395 VD->getDeclContext()->isFileContext()) {
1396 DVar.CKind = OMPC_unknown;
1397 } else {
1398 DVar.CKind = OMPC_firstprivate;
1399 }
1400 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1401 return DVar;
1402 case DSA_private:
1403 // each variable with static storage duration that is declared
1404 // in a namespace or global scope and referenced in the construct,
1405 // and that does not have a predetermined data-sharing attribute
1406 if (VD && VD->getStorageDuration() == SD_Static &&
1407 VD->getDeclContext()->isFileContext()) {
1408 DVar.CKind = OMPC_unknown;
1409 } else {
1410 DVar.CKind = OMPC_private;
1411 }
1412 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1413 return DVar;
1414 case DSA_unspecified:
1415 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1416 // in a Construct, implicitly determined, p.2]
1417 // In a parallel construct, if no default clause is present, these
1418 // variables are shared.
1419 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1420 if ((isOpenMPParallelDirective(DVar.DKind) &&
1421 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1422 isOpenMPTeamsDirective(DVar.DKind)) {
1423 DVar.CKind = OMPC_shared;
1424 return DVar;
1425 }
1426
1427 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1428 // in a Construct, implicitly determined, p.4]
1429 // In a task construct, if no default clause is present, a variable that in
1430 // the enclosing context is determined to be shared by all implicit tasks
1431 // bound to the current team is shared.
1432 if (isOpenMPTaskingDirective(DVar.DKind)) {
1433 DSAVarData DVarTemp;
1434 const_iterator I = Iter, E = end();
1435 do {
1436 ++I;
1437 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1438 // Referenced in a Construct, implicitly determined, p.6]
1439 // In a task construct, if no default clause is present, a variable
1440 // whose data-sharing attribute is not determined by the rules above is
1441 // firstprivate.
1442 DVarTemp = getDSA(I, D);
1443 if (DVarTemp.CKind != OMPC_shared) {
1444 DVar.RefExpr = nullptr;
1445 DVar.CKind = OMPC_firstprivate;
1446 return DVar;
1447 }
1448 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1449 DVar.CKind =
1450 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1451 return DVar;
1452 }
1453 }
1454 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1455 // in a Construct, implicitly determined, p.3]
1456 // For constructs other than task, if no default clause is present, these
1457 // variables inherit their data-sharing attributes from the enclosing
1458 // context.
1459 return getDSA(++Iter, D);
1460}
1461
1462const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1463 const Expr *NewDE) {
1464 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1465 D = getCanonicalDecl(D);
1466 SharingMapTy &StackElem = getTopOfStack();
1467 auto [It, Inserted] = StackElem.AlignedMap.try_emplace(D, NewDE);
1468 if (Inserted) {
1469 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1470 return nullptr;
1471 }
1472 assert(It->second && "Unexpected nullptr expr in the aligned map");
1473 return It->second;
1474}
1475
1476const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1477 const Expr *NewDE) {
1478 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1479 D = getCanonicalDecl(D);
1480 SharingMapTy &StackElem = getTopOfStack();
1481 auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(D, NewDE);
1482 if (Inserted) {
1483 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1484 return nullptr;
1485 }
1486 assert(It->second && "Unexpected nullptr expr in the aligned map");
1487 return It->second;
1488}
1489
1490void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1491 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1492 D = getCanonicalDecl(D);
1493 SharingMapTy &StackElem = getTopOfStack();
1494 StackElem.LCVMap.try_emplace(
1495 D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1496}
1497
1498const DSAStackTy::LCDeclInfo
1499DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1500 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1501 D = getCanonicalDecl(D);
1502 const SharingMapTy &StackElem = getTopOfStack();
1503 auto It = StackElem.LCVMap.find(D);
1504 if (It != StackElem.LCVMap.end())
1505 return It->second;
1506 return {0, nullptr};
1507}
1508
1509const DSAStackTy::LCDeclInfo
1510DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1511 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1512 D = getCanonicalDecl(D);
1513 for (unsigned I = Level + 1; I > 0; --I) {
1514 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1515 auto It = StackElem.LCVMap.find(D);
1516 if (It != StackElem.LCVMap.end())
1517 return It->second;
1518 }
1519 return {0, nullptr};
1520}
1521
1522const DSAStackTy::LCDeclInfo
1523DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1524 const SharingMapTy *Parent = getSecondOnStackOrNull();
1525 assert(Parent && "Data-sharing attributes stack is empty");
1526 D = getCanonicalDecl(D);
1527 auto It = Parent->LCVMap.find(D);
1528 if (It != Parent->LCVMap.end())
1529 return It->second;
1530 return {0, nullptr};
1531}
1532
1533const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1534 const SharingMapTy *Parent = getSecondOnStackOrNull();
1535 assert(Parent && "Data-sharing attributes stack is empty");
1536 if (Parent->LCVMap.size() < I)
1537 return nullptr;
1538 for (const auto &Pair : Parent->LCVMap)
1539 if (Pair.second.first == I)
1540 return Pair.first;
1541 return nullptr;
1542}
1543
1544void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1545 DeclRefExpr *PrivateCopy, unsigned Modifier,
1546 bool AppliedToPointee) {
1547 D = getCanonicalDecl(D);
1548 if (A == OMPC_threadprivate) {
1549 DSAInfo &Data = Threadprivates[D];
1550 Data.Attributes = A;
1551 Data.RefExpr.setPointer(E);
1552 Data.PrivateCopy = nullptr;
1553 Data.Modifier = Modifier;
1554 } else if (A == OMPC_groupprivate) {
1555 DSAInfo &Data = Groupprivates[D];
1556 Data.Attributes = A;
1557 Data.RefExpr.setPointer(E);
1558 Data.PrivateCopy = nullptr;
1559 Data.Modifier = Modifier;
1560 } else {
1561 DSAInfo &Data = getTopOfStack().SharingMap[D];
1562 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1563 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1564 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1565 (isLoopControlVariable(D).first && A == OMPC_private));
1566 Data.Modifier = Modifier;
1567 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1568 Data.RefExpr.setInt(/*IntVal=*/true);
1569 return;
1570 }
1571 const bool IsLastprivate =
1572 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1573 Data.Attributes = A;
1574 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1575 Data.PrivateCopy = PrivateCopy;
1576 Data.AppliedToPointee = AppliedToPointee;
1577 if (PrivateCopy) {
1578 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1579 Data.Modifier = Modifier;
1580 Data.Attributes = A;
1581 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1582 Data.PrivateCopy = nullptr;
1583 Data.AppliedToPointee = AppliedToPointee;
1584 }
1585 }
1586}
1587
1588/// Build a variable declaration for OpenMP loop iteration variable.
1590 StringRef Name, const AttrVec *Attrs = nullptr,
1591 DeclRefExpr *OrigRef = nullptr) {
1592 DeclContext *DC = SemaRef.CurContext;
1593 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1594 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
1595 auto *Decl =
1596 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
1597 if (Attrs) {
1598 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1599 I != E; ++I)
1600 Decl->addAttr(*I);
1601 }
1602 Decl->setImplicit();
1603 if (OrigRef) {
1604 Decl->addAttr(
1605 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1606 }
1607 return Decl;
1608}
1609
1611 SourceLocation Loc,
1612 bool RefersToCapture = false) {
1613 D->setReferenced();
1614 D->markUsed(S.Context);
1616 SourceLocation(), D, RefersToCapture, Loc, Ty,
1617 VK_LValue);
1618}
1619
1620void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1621 BinaryOperatorKind BOK) {
1622 D = getCanonicalDecl(D);
1623 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1624 assert(
1625 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1626 "Additional reduction info may be specified only for reduction items.");
1627 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1628 assert(ReductionData.ReductionRange.isInvalid() &&
1629 (getTopOfStack().Directive == OMPD_taskgroup ||
1630 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1631 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1632 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1633 "Additional reduction info may be specified only once for reduction "
1634 "items.");
1635 ReductionData.set(BOK, SR);
1636 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1637 if (!TaskgroupReductionRef) {
1638 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1639 SemaRef.Context.VoidPtrTy, ".task_red.");
1640 TaskgroupReductionRef =
1641 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1642 }
1643}
1644
1645void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1646 const Expr *ReductionRef) {
1647 D = getCanonicalDecl(D);
1648 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1649 assert(
1650 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1651 "Additional reduction info may be specified only for reduction items.");
1652 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1653 assert(ReductionData.ReductionRange.isInvalid() &&
1654 (getTopOfStack().Directive == OMPD_taskgroup ||
1655 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1656 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1657 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1658 "Additional reduction info may be specified only once for reduction "
1659 "items.");
1660 ReductionData.set(ReductionRef, SR);
1661 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1662 if (!TaskgroupReductionRef) {
1663 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1664 SemaRef.Context.VoidPtrTy, ".task_red.");
1665 TaskgroupReductionRef =
1666 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1667 }
1668}
1669
1670const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1671 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1672 Expr *&TaskgroupDescriptor) const {
1673 D = getCanonicalDecl(D);
1674 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1675 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1676 const DSAInfo &Data = I->SharingMap.lookup(D);
1677 if (Data.Attributes != OMPC_reduction ||
1678 Data.Modifier != OMPC_REDUCTION_task)
1679 continue;
1680 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1681 if (!ReductionData.ReductionOp ||
1682 isa<const Expr *>(ReductionData.ReductionOp))
1683 return DSAVarData();
1684 SR = ReductionData.ReductionRange;
1685 BOK = cast<ReductionData::BOKPtrType>(ReductionData.ReductionOp);
1686 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1687 "expression for the descriptor is not "
1688 "set.");
1689 TaskgroupDescriptor = I->TaskgroupReductionRef;
1690 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1691 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1692 /*AppliedToPointee=*/false);
1693 }
1694 return DSAVarData();
1695}
1696
1697const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1698 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1699 Expr *&TaskgroupDescriptor) const {
1700 D = getCanonicalDecl(D);
1701 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1702 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1703 const DSAInfo &Data = I->SharingMap.lookup(D);
1704 if (Data.Attributes != OMPC_reduction ||
1705 Data.Modifier != OMPC_REDUCTION_task)
1706 continue;
1707 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1708 if (!ReductionData.ReductionOp ||
1709 !isa<const Expr *>(ReductionData.ReductionOp))
1710 return DSAVarData();
1711 SR = ReductionData.ReductionRange;
1712 ReductionRef = cast<const Expr *>(ReductionData.ReductionOp);
1713 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1714 "expression for the descriptor is not "
1715 "set.");
1716 TaskgroupDescriptor = I->TaskgroupReductionRef;
1717 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1718 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1719 /*AppliedToPointee=*/false);
1720 }
1721 return DSAVarData();
1722}
1723
1724bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1725 D = D->getCanonicalDecl();
1726 for (const_iterator E = end(); I != E; ++I) {
1727 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1728 isOpenMPTargetExecutionDirective(I->Directive)) {
1729 if (I->CurScope) {
1730 Scope *TopScope = I->CurScope->getParent();
1731 Scope *CurScope = getCurScope();
1732 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1733 CurScope = CurScope->getParent();
1734 return CurScope != TopScope;
1735 }
1736 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1737 if (I->Context == DC)
1738 return true;
1739 return false;
1740 }
1741 }
1742 return false;
1743}
1744
1746 bool AcceptIfMutable = true,
1747 bool *IsClassType = nullptr) {
1748 ASTContext &Context = SemaRef.getASTContext();
1749 Type = Type.getNonReferenceType().getCanonicalType();
1750 bool IsConstant = Type.isConstant(Context);
1751 Type = Context.getBaseElementType(Type);
1752 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1754 : nullptr;
1755 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1756 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1757 RD = CTD->getTemplatedDecl();
1758 if (IsClassType)
1759 *IsClassType = RD;
1760 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1761 RD->hasDefinition() && RD->hasMutableFields());
1762}
1763
1764static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1766 SourceLocation ELoc,
1767 bool AcceptIfMutable = true,
1768 bool ListItemNotVar = false) {
1769 ASTContext &Context = SemaRef.getASTContext();
1770 bool IsClassType;
1771 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
1772 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1773 : IsClassType ? diag::err_omp_const_not_mutable_variable
1774 : diag::err_omp_const_variable;
1775 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseNameForDiag(CKind);
1776 if (!ListItemNotVar && D) {
1777 const VarDecl *VD = dyn_cast<VarDecl>(D);
1778 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1780 SemaRef.Diag(D->getLocation(),
1781 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1782 << D;
1783 }
1784 return true;
1785 }
1786 return false;
1787}
1788
1789const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1790 bool FromParent) {
1791 D = getCanonicalDecl(D);
1792 DSAVarData DVar;
1793
1794 auto *VD = dyn_cast<VarDecl>(D);
1795 auto TI = Threadprivates.find(D);
1796 if (TI != Threadprivates.end()) {
1797 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1798 DVar.CKind = OMPC_threadprivate;
1799 DVar.Modifier = TI->getSecond().Modifier;
1800 return DVar;
1801 }
1802 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1803 DVar.RefExpr = buildDeclRefExpr(
1804 SemaRef, VD, D->getType().getNonReferenceType(),
1805 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1806 DVar.CKind = OMPC_threadprivate;
1807 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1808 return DVar;
1809 }
1810 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1811 // in a Construct, C/C++, predetermined, p.1]
1812 // Variables appearing in threadprivate directives are threadprivate.
1813 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1814 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1815 SemaRef.getLangOpts().OpenMPUseTLS &&
1816 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1817 (VD && VD->getStorageClass() == SC_Register &&
1818 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1819 DVar.RefExpr = buildDeclRefExpr(
1820 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1821 DVar.CKind = OMPC_threadprivate;
1822 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1823 return DVar;
1824 }
1825 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1826 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1827 !isLoopControlVariable(D).first) {
1828 const_iterator IterTarget =
1829 std::find_if(begin(), end(), [](const SharingMapTy &Data) {
1830 return isOpenMPTargetExecutionDirective(Data.Directive);
1831 });
1832 if (IterTarget != end()) {
1833 const_iterator ParentIterTarget = IterTarget + 1;
1834 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1835 if (isOpenMPLocal(VD, Iter)) {
1836 DVar.RefExpr =
1837 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1838 D->getLocation());
1839 DVar.CKind = OMPC_threadprivate;
1840 return DVar;
1841 }
1842 }
1843 if (!isClauseParsingMode() || IterTarget != begin()) {
1844 auto DSAIter = IterTarget->SharingMap.find(D);
1845 if (DSAIter != IterTarget->SharingMap.end() &&
1846 isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1847 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1848 DVar.CKind = OMPC_threadprivate;
1849 return DVar;
1850 }
1851 const_iterator End = end();
1852 if (!SemaRef.OpenMP().isOpenMPCapturedByRef(
1853 D, std::distance(ParentIterTarget, End),
1854 /*OpenMPCaptureLevel=*/0)) {
1855 DVar.RefExpr =
1856 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1857 IterTarget->ConstructLoc);
1858 DVar.CKind = OMPC_threadprivate;
1859 return DVar;
1860 }
1861 }
1862 }
1863 }
1864
1865 if (isStackEmpty())
1866 // Not in OpenMP execution region and top scope was already checked.
1867 return DVar;
1868
1869 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1870 // in a Construct, C/C++, predetermined, p.4]
1871 // Static data members are shared.
1872 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1873 // in a Construct, C/C++, predetermined, p.7]
1874 // Variables with static storage duration that are declared in a scope
1875 // inside the construct are shared.
1876 if (VD && VD->isStaticDataMember()) {
1877 // Check for explicitly specified attributes.
1878 const_iterator I = begin();
1879 const_iterator EndI = end();
1880 if (FromParent && I != EndI)
1881 ++I;
1882 if (I != EndI) {
1883 auto It = I->SharingMap.find(D);
1884 if (It != I->SharingMap.end()) {
1885 const DSAInfo &Data = It->getSecond();
1886 DVar.RefExpr = Data.RefExpr.getPointer();
1887 DVar.PrivateCopy = Data.PrivateCopy;
1888 DVar.CKind = Data.Attributes;
1889 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1890 DVar.DKind = I->Directive;
1891 DVar.Modifier = Data.Modifier;
1892 DVar.AppliedToPointee = Data.AppliedToPointee;
1893 return DVar;
1894 }
1895 }
1896
1897 DVar.CKind = OMPC_shared;
1898 return DVar;
1899 }
1900
1901 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1902 // The predetermined shared attribute for const-qualified types having no
1903 // mutable members was removed after OpenMP 3.1.
1904 if (SemaRef.LangOpts.OpenMP <= 31) {
1905 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1906 // in a Construct, C/C++, predetermined, p.6]
1907 // Variables with const qualified type having no mutable member are
1908 // shared.
1909 if (isConstNotMutableType(SemaRef, D->getType())) {
1910 // Variables with const-qualified type having no mutable member may be
1911 // listed in a firstprivate clause, even if they are static data members.
1912 DSAVarData DVarTemp = hasInnermostDSA(
1913 D,
1914 [](OpenMPClauseKind C, bool) {
1915 return C == OMPC_firstprivate || C == OMPC_shared;
1916 },
1917 MatchesAlways, FromParent);
1918 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1919 return DVarTemp;
1920
1921 DVar.CKind = OMPC_shared;
1922 return DVar;
1923 }
1924 }
1925
1926 // Explicitly specified attributes and local variables with predetermined
1927 // attributes.
1928 const_iterator I = begin();
1929 const_iterator EndI = end();
1930 if (FromParent && I != EndI)
1931 ++I;
1932 if (I == EndI)
1933 return DVar;
1934 auto It = I->SharingMap.find(D);
1935 if (It != I->SharingMap.end()) {
1936 const DSAInfo &Data = It->getSecond();
1937 DVar.RefExpr = Data.RefExpr.getPointer();
1938 DVar.PrivateCopy = Data.PrivateCopy;
1939 DVar.CKind = Data.Attributes;
1940 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1941 DVar.DKind = I->Directive;
1942 DVar.Modifier = Data.Modifier;
1943 DVar.AppliedToPointee = Data.AppliedToPointee;
1944 }
1945
1946 return DVar;
1947}
1948
1949const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1950 bool FromParent) const {
1951 if (isStackEmpty()) {
1952 const_iterator I;
1953 return getDSA(I, D);
1954 }
1955 D = getCanonicalDecl(D);
1956 const_iterator StartI = begin();
1957 const_iterator EndI = end();
1958 if (FromParent && StartI != EndI)
1959 ++StartI;
1960 return getDSA(StartI, D);
1961}
1962
1963const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1964 unsigned Level) const {
1965 if (getStackSize() <= Level)
1966 return DSAVarData();
1967 D = getCanonicalDecl(D);
1968 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1969 return getDSA(StartI, D);
1970}
1971
1972const DSAStackTy::DSAVarData
1973DSAStackTy::hasDSA(ValueDecl *D,
1974 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1975 DefaultDataSharingAttributes)>
1976 CPred,
1977 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1978 bool FromParent) const {
1979 if (isStackEmpty())
1980 return {};
1981 D = getCanonicalDecl(D);
1982 const_iterator I = begin();
1983 const_iterator EndI = end();
1984 if (FromParent && I != EndI)
1985 ++I;
1986 for (; I != EndI; ++I) {
1987 if (!DPred(I->Directive) &&
1988 !isImplicitOrExplicitTaskingRegion(I->Directive))
1989 continue;
1990 const_iterator NewI = I;
1991 DSAVarData DVar = getDSA(NewI, D);
1992 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1993 return DVar;
1994 }
1995 return {};
1996}
1997
1998const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1999 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
2000 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2001 bool FromParent) const {
2002 if (isStackEmpty())
2003 return {};
2004 D = getCanonicalDecl(D);
2005 const_iterator StartI = begin();
2006 const_iterator EndI = end();
2007 if (FromParent && StartI != EndI)
2008 ++StartI;
2009 if (StartI == EndI || !DPred(StartI->Directive))
2010 return {};
2011 const_iterator NewI = StartI;
2012 DSAVarData DVar = getDSA(NewI, D);
2013 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
2014 ? DVar
2015 : DSAVarData();
2016}
2017
2018bool DSAStackTy::hasExplicitDSA(
2019 const ValueDecl *D,
2020 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
2021 unsigned Level, bool NotLastprivate) const {
2022 if (getStackSize() <= Level)
2023 return false;
2024 D = getCanonicalDecl(D);
2025 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2026 auto I = StackElem.SharingMap.find(D);
2027 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
2028 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
2029 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
2030 return true;
2031 // Check predetermined rules for the loop control variables.
2032 auto LI = StackElem.LCVMap.find(D);
2033 if (LI != StackElem.LCVMap.end())
2034 return CPred(OMPC_private, /*AppliedToPointee=*/false);
2035 return false;
2036}
2037
2038bool DSAStackTy::hasExplicitDirective(
2039 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2040 unsigned Level) const {
2041 if (getStackSize() <= Level)
2042 return false;
2043 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2044 return DPred(StackElem.Directive);
2045}
2046
2047bool DSAStackTy::hasDirective(
2048 const llvm::function_ref<bool(OpenMPDirectiveKind,
2049 const DeclarationNameInfo &, SourceLocation)>
2050 DPred,
2051 bool FromParent) const {
2052 // We look only in the enclosing region.
2053 size_t Skip = FromParent ? 2 : 1;
2054 for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
2055 I != E; ++I) {
2056 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2057 return true;
2058 }
2059 return false;
2060}
2061
2062void SemaOpenMP::InitDataSharingAttributesStack() {
2063 VarDataSharingAttributesStack = new DSAStackTy(SemaRef);
2064}
2065
2066#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2067
2068void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2069
2070void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2071 DSAStack->popFunction(OldFSI);
2072}
2073
2075 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2076 "Expected OpenMP device compilation.");
2078}
2079
2080namespace {
2081/// Status of the function emission on the host/device.
2082enum class FunctionEmissionStatus {
2083 Emitted,
2084 Discarded,
2085 Unknown,
2086};
2087} // anonymous namespace
2088
2089SemaBase::SemaDiagnosticBuilder
2091 const FunctionDecl *FD) {
2092 assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&
2093 "Expected OpenMP device compilation.");
2094
2095 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2096 if (FD) {
2097 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(FD);
2098 switch (FES) {
2100 Kind = SemaDiagnosticBuilder::K_Immediate;
2101 break;
2103 // TODO: We should always delay diagnostics here in case a target
2104 // region is in a function we do not emit. However, as the
2105 // current diagnostics are associated with the function containing
2106 // the target region and we do not emit that one, we would miss out
2107 // on diagnostics for the target region itself. We need to anchor
2108 // the diagnostics with the new generated function *or* ensure we
2109 // emit diagnostics associated with the surrounding function.
2111 ? SemaDiagnosticBuilder::K_Deferred
2112 : SemaDiagnosticBuilder::K_Immediate;
2113 break;
2116 Kind = SemaDiagnosticBuilder::K_Nop;
2117 break;
2119 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2120 break;
2121 }
2122 }
2123
2124 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2125}
2126
2129 const FunctionDecl *FD) {
2130 assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice &&
2131 "Expected OpenMP host compilation.");
2132
2133 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2134 if (FD) {
2135 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(FD);
2136 switch (FES) {
2138 Kind = SemaDiagnosticBuilder::K_Immediate;
2139 break;
2141 Kind = SemaDiagnosticBuilder::K_Deferred;
2142 break;
2146 Kind = SemaDiagnosticBuilder::K_Nop;
2147 break;
2148 }
2149 }
2150
2151 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2152}
2153
2156 if (LO.OpenMP <= 45) {
2158 return OMPC_DEFAULTMAP_scalar;
2159 return OMPC_DEFAULTMAP_aggregate;
2160 }
2162 return OMPC_DEFAULTMAP_pointer;
2164 return OMPC_DEFAULTMAP_scalar;
2165 return OMPC_DEFAULTMAP_aggregate;
2166}
2167
2168bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2169 unsigned OpenMPCaptureLevel) const {
2170 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2171
2172 ASTContext &Ctx = getASTContext();
2173 bool IsByRef = true;
2174
2175 // Find the directive that is associated with the provided scope.
2177 QualType Ty = D->getType();
2178
2179 bool IsVariableUsedInMapClause = false;
2180 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2181 // This table summarizes how a given variable should be passed to the device
2182 // given its type and the clauses where it appears. This table is based on
2183 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2184 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2185 //
2186 // =========================================================================
2187 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2188 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2189 // =========================================================================
2190 // | scl | | | | - | | bycopy|
2191 // | scl | | - | x | - | - | bycopy|
2192 // | scl | | x | - | - | - | null |
2193 // | scl | x | | | - | | byref |
2194 // | scl | x | - | x | - | - | bycopy|
2195 // | scl | x | x | - | - | - | null |
2196 // | scl | | - | - | - | x | byref |
2197 // | scl | x | - | - | - | x | byref |
2198 //
2199 // | agg | n.a. | | | - | | byref |
2200 // | agg | n.a. | - | x | - | - | byref |
2201 // | agg | n.a. | x | - | - | - | null |
2202 // | agg | n.a. | - | - | - | x | byref |
2203 // | agg | n.a. | - | - | - | x[] | byref |
2204 //
2205 // | ptr | n.a. | | | - | | bycopy|
2206 // | ptr | n.a. | - | x | - | - | bycopy|
2207 // | ptr | n.a. | x | - | - | - | null |
2208 // | ptr | n.a. | - | - | - | x | byref |
2209 // | ptr | n.a. | - | - | - | x, x[] | bycopy|
2210 // | ptr | n.a. | - | - | - | x[] | bycopy|
2211 // | ptr | n.a. | - | - | x | | bycopy|
2212 // | ptr | n.a. | - | - | x | x | bycopy|
2213 // | ptr | n.a. | - | - | x | x[] | bycopy|
2214 // =========================================================================
2215 // Legend:
2216 // scl - scalar
2217 // ptr - pointer
2218 // agg - aggregate
2219 // x - applies
2220 // - - invalid in this combination
2221 // [] - mapped with an array section
2222 // byref - should be mapped by reference
2223 // byval - should be mapped by value
2224 // null - initialize a local variable to null on the device
2225 //
2226 // Observations:
2227 // - All scalar declarations that show up in a map clause have to be passed
2228 // by reference, because they may have been mapped in the enclosing data
2229 // environment.
2230 // - If the scalar value does not fit the size of uintptr, it has to be
2231 // passed by reference, regardless the result in the table above.
2232 // - For pointers mapped by value that have either an implicit map or an
2233 // array section, the runtime library may pass the NULL value to the
2234 // device instead of the value passed to it by the compiler.
2235 // - If both a pointer and a dereference of it are mapped, then the pointer
2236 // should be passed by reference.
2237
2238 if (Ty->isReferenceType())
2239 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2240
2241 // Locate map clauses and see if the variable being captured is mapped by
2242 // itself, or referred to, in any of those clauses. Here we only care about
2243 // variables, not fields, because fields are part of aggregates.
2244 bool IsVariableAssociatedWithSection = false;
2245 bool IsVariableItselfMapped = false;
2246
2247 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2248 D, Level,
2249 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2250 &IsVariableItselfMapped,
2252 MapExprComponents,
2253 OpenMPClauseKind WhereFoundClauseKind) {
2254 // Both map and has_device_addr clauses information influences how a
2255 // variable is captured. E.g. is_device_ptr does not require changing
2256 // the default behavior.
2257 if (WhereFoundClauseKind != OMPC_map &&
2258 WhereFoundClauseKind != OMPC_has_device_addr)
2259 return false;
2260
2261 auto EI = MapExprComponents.rbegin();
2262 auto EE = MapExprComponents.rend();
2263
2264 assert(EI != EE && "Invalid map expression!");
2265
2266 if (isa<DeclRefExpr>(EI->getAssociatedExpression()) &&
2267 EI->getAssociatedDeclaration() == D) {
2268 IsVariableUsedInMapClause = true;
2269
2270 // If the component list has only one element, it's for mapping the
2271 // variable itself, like map(p). This takes precedence in
2272 // determining how it's captured, so we don't need to look further
2273 // for any other maps that use the variable (like map(p[0]) etc.)
2274 if (MapExprComponents.size() == 1) {
2275 IsVariableItselfMapped = true;
2276 return true;
2277 }
2278 }
2279
2280 ++EI;
2281 if (EI == EE)
2282 return false;
2283 auto Last = std::prev(EE);
2284 const auto *UO =
2285 dyn_cast<UnaryOperator>(Last->getAssociatedExpression());
2286 if ((UO && UO->getOpcode() == UO_Deref) ||
2287 isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) ||
2288 isa<ArraySectionExpr>(Last->getAssociatedExpression()) ||
2289 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2290 isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) {
2291 IsVariableAssociatedWithSection = true;
2292 // We've found a case like map(p[0]) or map(p->a) or map(*p),
2293 // so we are done with this particular map, but we need to keep
2294 // looking in case we find a map(p).
2295 return false;
2296 }
2297
2298 // Keep looking for more map info.
2299 return false;
2300 });
2301
2302 if (IsVariableUsedInMapClause) {
2303 // If variable is identified in a map clause it is always captured by
2304 // reference except if it is a pointer that is dereferenced somehow, but
2305 // not itself mapped.
2306 //
2307 // OpenMP 6.0, 7.1.1: Data sharing attribute rules, variables referenced
2308 // in a construct::
2309 // If a list item in a has_device_addr clause or in a map clause on the
2310 // target construct has a base pointer, and the base pointer is a scalar
2311 // variable *that is not a list item in a map clause on the construct*,
2312 // the base pointer is firstprivate.
2313 //
2314 // OpenMP 4.5, 2.15.1.1: Data-sharing Attribute Rules for Variables
2315 // Referenced in a Construct:
2316 // If an array section is a list item in a map clause on the target
2317 // construct and the array section is derived from a variable for which
2318 // the type is pointer then that variable is firstprivate.
2319 IsByRef = IsVariableItselfMapped ||
2320 !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2321 } else {
2322 // By default, all the data that has a scalar type is mapped by copy
2323 // (except for reduction variables).
2324 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2325 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2326 !Ty->isAnyPointerType()) ||
2327 !Ty->isScalarType() ||
2328 DSAStack->isDefaultmapCapturedByRef(
2330 DSAStack->hasExplicitDSA(
2331 D,
2332 [](OpenMPClauseKind K, bool AppliedToPointee) {
2333 return K == OMPC_reduction && !AppliedToPointee;
2334 },
2335 Level);
2336 }
2337 }
2338
2339 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2340 IsByRef =
2341 ((IsVariableUsedInMapClause &&
2342 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2343 OMPD_target) ||
2344 !(DSAStack->hasExplicitDSA(
2345 D,
2346 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2347 return K == OMPC_firstprivate ||
2348 (K == OMPC_reduction && AppliedToPointee);
2349 },
2350 Level, /*NotLastprivate=*/true) ||
2351 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2352 // If the variable is artificial and must be captured by value - try to
2353 // capture by value.
2354 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2355 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2356 // If the variable is implicitly firstprivate and scalar - capture by
2357 // copy
2358 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2359 DSAStack->getDefaultDSA() == DSA_private) &&
2360 !DSAStack->hasExplicitDSA(
2361 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2362 Level) &&
2363 !DSAStack->isLoopControlVariable(D, Level).first);
2364 }
2365
2366 // When passing data by copy, we need to make sure it fits the uintptr size
2367 // and alignment, because the runtime library only deals with uintptr types.
2368 // If it does not fit the uintptr size, we need to pass the data by reference
2369 // instead.
2370 if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) >
2372 Ctx.getAlignOfGlobalVarInChars(Ty, dyn_cast<VarDecl>(D)) >
2373 Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2374 IsByRef = true;
2375 }
2376
2377 return IsByRef;
2378}
2379
2380unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2381 assert(getLangOpts().OpenMP);
2382 return DSAStack->getNestingLevel();
2383}
2384
2386 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2387 DSAStack->isUntiedRegion();
2388}
2389
2391 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2392 !DSAStack->isClauseParsingMode()) ||
2393 DSAStack->hasDirective(
2395 SourceLocation) -> bool {
2397 },
2398 false);
2399}
2400
2402 // Only rebuild for Field.
2403 if (!isa<FieldDecl>(D))
2404 return false;
2405 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2406 D,
2407 [](OpenMPClauseKind C, bool AppliedToPointee,
2408 DefaultDataSharingAttributes DefaultAttr) {
2409 return isOpenMPPrivate(C) && !AppliedToPointee &&
2410 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2411 },
2412 [](OpenMPDirectiveKind) { return true; },
2413 DSAStack->isClauseParsingMode());
2414 if (DVarPrivate.CKind != OMPC_unknown)
2415 return true;
2416 return false;
2417}
2418
2420 Expr *CaptureExpr, bool WithInit,
2421 DeclContext *CurContext,
2422 bool AsExpression);
2423
2425 unsigned StopAt) {
2426 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2427 D = getCanonicalDecl(D);
2428
2429 auto *VD = dyn_cast<VarDecl>(D);
2430 // Do not capture constexpr variables.
2431 if (VD && VD->isConstexpr())
2432 return nullptr;
2433
2434 // If we want to determine whether the variable should be captured from the
2435 // perspective of the current capturing scope, and we've already left all the
2436 // capturing scopes of the top directive on the stack, check from the
2437 // perspective of its parent directive (if any) instead.
2438 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2439 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2440
2441 // If we are attempting to capture a global variable in a directive with
2442 // 'target' we return true so that this global is also mapped to the device.
2443 //
2444 if (VD && !VD->hasLocalStorage() &&
2445 (SemaRef.getCurCapturedRegion() || SemaRef.getCurBlock() ||
2446 SemaRef.getCurLambda())) {
2448 DSAStackTy::DSAVarData DVarTop =
2449 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2450 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2451 return VD;
2452 // If the declaration is enclosed in a 'declare target' directive,
2453 // then it should not be captured.
2454 //
2455 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2456 return nullptr;
2457 CapturedRegionScopeInfo *CSI = nullptr;
2458 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2459 llvm::reverse(SemaRef.FunctionScopes),
2460 CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2461 : 0)) {
2462 if (!isa<CapturingScopeInfo>(FSI))
2463 return nullptr;
2464 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2465 if (RSI->CapRegionKind == CR_OpenMP) {
2466 CSI = RSI;
2467 break;
2468 }
2469 }
2470 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2473 DSAStack->getDirective(CSI->OpenMPLevel));
2474 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2475 return VD;
2476 }
2478 // Try to mark variable as declare target if it is used in capturing
2479 // regions.
2480 if (getLangOpts().OpenMP <= 45 &&
2481 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2483 return nullptr;
2484 }
2485 }
2486
2487 if (CheckScopeInfo) {
2488 bool OpenMPFound = false;
2489 for (unsigned I = StopAt + 1; I > 0; --I) {
2490 FunctionScopeInfo *FSI = SemaRef.FunctionScopes[I - 1];
2491 if (!isa<CapturingScopeInfo>(FSI))
2492 return nullptr;
2493 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2494 if (RSI->CapRegionKind == CR_OpenMP) {
2495 OpenMPFound = true;
2496 break;
2497 }
2498 }
2499 if (!OpenMPFound)
2500 return nullptr;
2501 }
2502
2503 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2504 (!DSAStack->isClauseParsingMode() ||
2505 DSAStack->getParentDirective() != OMPD_unknown)) {
2506 auto &&Info = DSAStack->isLoopControlVariable(D);
2507 if (Info.first ||
2508 (VD && VD->hasLocalStorage() &&
2509 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2510 (VD && DSAStack->isForceVarCapturing()))
2511 return VD ? VD : Info.second;
2512 DSAStackTy::DSAVarData DVarTop =
2513 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2514 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2515 (!VD || VD->hasLocalStorage() ||
2516 !(DVarTop.AppliedToPointee && DVarTop.CKind != OMPC_reduction)))
2517 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2518 // Threadprivate variables must not be captured.
2519 if (isOpenMPThreadPrivate(DVarTop.CKind))
2520 return nullptr;
2521 // The variable is not private or it is the variable in the directive with
2522 // default(none) clause and not used in any clause.
2523 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2524 D,
2525 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2526 return isOpenMPPrivate(C) && !AppliedToPointee;
2527 },
2528 [](OpenMPDirectiveKind) { return true; },
2529 DSAStack->isClauseParsingMode());
2530 // Global shared must not be captured.
2531 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2532 ((DSAStack->getDefaultDSA() != DSA_none &&
2533 DSAStack->getDefaultDSA() != DSA_private &&
2534 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2535 DVarTop.CKind == OMPC_shared))
2536 return nullptr;
2537 auto *FD = dyn_cast<FieldDecl>(D);
2538 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2539 !DVarPrivate.PrivateCopy) {
2540 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2541 D,
2542 [](OpenMPClauseKind C, bool AppliedToPointee,
2543 DefaultDataSharingAttributes DefaultAttr) {
2544 return isOpenMPPrivate(C) && !AppliedToPointee &&
2545 (DefaultAttr == DSA_firstprivate ||
2546 DefaultAttr == DSA_private);
2547 },
2548 [](OpenMPDirectiveKind) { return true; },
2549 DSAStack->isClauseParsingMode());
2550 if (DVarPrivate.CKind == OMPC_unknown)
2551 return nullptr;
2552
2553 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2554 if (VD)
2555 return VD;
2556 if (SemaRef.getCurrentThisType().isNull())
2557 return nullptr;
2558 Expr *ThisExpr = SemaRef.BuildCXXThisExpr(SourceLocation(),
2559 SemaRef.getCurrentThisType(),
2560 /*IsImplicit=*/true);
2561 const CXXScopeSpec CS = CXXScopeSpec();
2562 Expr *ME = SemaRef.BuildMemberExpr(
2563 ThisExpr, /*IsArrow=*/true, SourceLocation(),
2566 /*HadMultipleCandidates=*/false, DeclarationNameInfo(), FD->getType(),
2569 SemaRef, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2570 SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2571 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2573 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2574 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2575 return VD;
2576 }
2577 if (DVarPrivate.CKind != OMPC_unknown ||
2578 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2579 DSAStack->getDefaultDSA() == DSA_private ||
2580 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2581 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2582 }
2583 return nullptr;
2584}
2585
2586void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2587 unsigned Level) const {
2588 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2589}
2590
2592 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2593 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2594 DSAStack->loopInit();
2595}
2596
2598 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2599 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2600 DSAStack->resetPossibleLoopCounter();
2601 DSAStack->loopStart();
2602 }
2603}
2604
2606 unsigned CapLevel) const {
2607 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2608 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2609 (!DSAStack->isClauseParsingMode() ||
2610 DSAStack->getParentDirective() != OMPD_unknown)) {
2611 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2612 D,
2613 [](OpenMPClauseKind C, bool AppliedToPointee,
2614 DefaultDataSharingAttributes DefaultAttr) {
2615 return isOpenMPPrivate(C) && !AppliedToPointee &&
2616 DefaultAttr == DSA_private;
2617 },
2618 [](OpenMPDirectiveKind) { return true; },
2619 DSAStack->isClauseParsingMode());
2620 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2621 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2622 !DSAStack->isLoopControlVariable(D).first)
2623 return OMPC_private;
2624 }
2625 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2626 bool IsTriviallyCopyable =
2628 getASTContext()) &&
2629 !D->getType()
2633 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2635 getOpenMPCaptureRegions(CaptureRegions, DKind);
2636 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2637 (IsTriviallyCopyable ||
2638 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2639 if (DSAStack->hasExplicitDSA(
2640 D,
2641 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2642 Level, /*NotLastprivate=*/true))
2643 return OMPC_firstprivate;
2644 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2645 if (DVar.CKind != OMPC_shared &&
2646 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2647 DSAStack->addImplicitTaskFirstprivate(Level, D);
2648 return OMPC_firstprivate;
2649 }
2650 }
2651 }
2652 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2653 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2654 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2655 DSAStack->resetPossibleLoopCounter(D);
2656 DSAStack->loopStart();
2657 return OMPC_private;
2658 }
2659 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2660 DSAStack->isLoopControlVariable(D).first) &&
2661 !DSAStack->hasExplicitDSA(
2662 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2663 Level) &&
2664 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2665 return OMPC_private;
2666 }
2667 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2668 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2669 DSAStack->isForceVarCapturing() &&
2670 !DSAStack->hasExplicitDSA(
2671 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2672 Level))
2673 return OMPC_private;
2674 }
2675 // User-defined allocators are private since they must be defined in the
2676 // context of target region.
2677 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2678 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2679 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2680 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2681 return OMPC_private;
2682 return (DSAStack->hasExplicitDSA(
2683 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2684 Level) ||
2685 (DSAStack->isClauseParsingMode() &&
2686 DSAStack->getClauseParsingMode() == OMPC_private) ||
2687 // Consider taskgroup reduction descriptor variable a private
2688 // to avoid possible capture in the region.
2689 (DSAStack->hasExplicitDirective(
2690 [](OpenMPDirectiveKind K) {
2691 return K == OMPD_taskgroup ||
2692 ((isOpenMPParallelDirective(K) ||
2693 isOpenMPWorksharingDirective(K)) &&
2694 !isOpenMPSimdDirective(K));
2695 },
2696 Level) &&
2697 DSAStack->isTaskgroupReductionRef(D, Level)))
2698 ? OMPC_private
2699 : OMPC_unknown;
2700}
2701
2703 unsigned Level) {
2704 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2705 D = getCanonicalDecl(D);
2706 OpenMPClauseKind OMPC = OMPC_unknown;
2707 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2708 const unsigned NewLevel = I - 1;
2709 if (DSAStack->hasExplicitDSA(
2710 D,
2711 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2712 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2713 OMPC = K;
2714 return true;
2715 }
2716 return false;
2717 },
2718 NewLevel))
2719 break;
2720 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2721 D, NewLevel,
2723 OpenMPClauseKind) { return true; })) {
2724 OMPC = OMPC_map;
2725 break;
2726 }
2727 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2728 NewLevel)) {
2729 OMPC = OMPC_map;
2730 if (DSAStack->mustBeFirstprivateAtLevel(
2732 OMPC = OMPC_firstprivate;
2733 break;
2734 }
2735 }
2736 if (OMPC != OMPC_unknown)
2737 FD->addAttr(
2738 OMPCaptureKindAttr::CreateImplicit(getASTContext(), unsigned(OMPC)));
2739}
2740
2742 unsigned CaptureLevel) const {
2743 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2744 // Return true if the current level is no longer enclosed in a target region.
2745
2747 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2748 const auto *VD = dyn_cast<VarDecl>(D);
2749 return VD && !VD->hasLocalStorage() &&
2750 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2751 Level) &&
2752 Regions[CaptureLevel] != OMPD_task;
2753}
2754
2756 unsigned CaptureLevel) const {
2757 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2758 // Return true if the current level is no longer enclosed in a target region.
2759
2760 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2761 if (!VD->hasLocalStorage()) {
2763 return true;
2764 DSAStackTy::DSAVarData TopDVar =
2765 DSAStack->getTopDSA(D, /*FromParent=*/false);
2766 unsigned NumLevels =
2767 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2768 if (Level == 0)
2769 // non-file scope static variable with default(firstprivate)
2770 // should be global captured.
2771 return (NumLevels == CaptureLevel + 1 &&
2772 (TopDVar.CKind != OMPC_shared ||
2773 DSAStack->getDefaultDSA() == DSA_firstprivate));
2774 do {
2775 --Level;
2776 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2777 if (DVar.CKind != OMPC_shared)
2778 return true;
2779 } while (Level > 0);
2780 }
2781 }
2782 return true;
2783}
2784
2785void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2786
2788 OMPTraitInfo &TI) {
2789 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2790}
2791
2794 "Not in OpenMP declare variant scope!");
2795
2796 OMPDeclareVariantScopes.pop_back();
2797}
2798
2800 const FunctionDecl *Callee,
2801 SourceLocation Loc) {
2802 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2803 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2804 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2805 // Ignore host functions during device analysis.
2806 if (getLangOpts().OpenMPIsTargetDevice &&
2807 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2808 return;
2809 // Ignore nohost functions during host analysis.
2810 if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2811 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2812 return;
2813 const FunctionDecl *FD = Callee->getMostRecentDecl();
2814 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2815 if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2816 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2817 // Diagnose host function called during device codegen.
2818 StringRef HostDevTy =
2819 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2820 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2821 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2822 diag::note_omp_marked_device_type_here)
2823 << HostDevTy;
2824 return;
2825 }
2826 if (!getLangOpts().OpenMPIsTargetDevice &&
2827 !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2828 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2829 // In OpenMP 5.2 or later, if the function has a host variant then allow
2830 // that to be called instead
2831 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2832 for (OMPDeclareVariantAttr *A :
2833 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2834 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2835 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2836 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2837 OMPDeclareTargetDeclAttr::getDeviceType(
2838 VariantFD->getMostRecentDecl());
2839 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2840 return true;
2841 }
2842 return false;
2843 };
2844 if (getLangOpts().OpenMP >= 52 &&
2845 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2846 return;
2847 // Diagnose nohost function called during host codegen.
2848 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2849 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2850 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2851 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2852 diag::note_omp_marked_device_type_here)
2853 << NoHostDevTy;
2854 }
2855}
2856
2858 const DeclarationNameInfo &DirName,
2859 Scope *CurScope, SourceLocation Loc) {
2860 DSAStack->push(DKind, DirName, CurScope, Loc);
2861 SemaRef.PushExpressionEvaluationContext(
2863}
2864
2866 DSAStack->setClauseParsingMode(K);
2867}
2868
2870 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2871 SemaRef.CleanupVarDeclMarking();
2872}
2873
2874static std::pair<ValueDecl *, bool>
2875getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2876 SourceRange &ERange, bool AllowArraySection = false,
2877 bool AllowAssumedSizeArray = false, StringRef DiagType = "");
2878
2879/// Check consistency of the reduction clauses.
2880static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2881 ArrayRef<OMPClause *> Clauses) {
2882 bool InscanFound = false;
2883 SourceLocation InscanLoc;
2884 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2885 // A reduction clause without the inscan reduction-modifier may not appear on
2886 // a construct on which a reduction clause with the inscan reduction-modifier
2887 // appears.
2888 for (OMPClause *C : Clauses) {
2889 if (C->getClauseKind() != OMPC_reduction)
2890 continue;
2891 auto *RC = cast<OMPReductionClause>(C);
2892 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2893 InscanFound = true;
2894 InscanLoc = RC->getModifierLoc();
2895 continue;
2896 }
2897 if (RC->getModifier() == OMPC_REDUCTION_task) {
2898 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2899 // A reduction clause with the task reduction-modifier may only appear on
2900 // a parallel construct, a worksharing construct or a combined or
2901 // composite construct for which any of the aforementioned constructs is a
2902 // constituent construct and simd or loop are not constituent constructs.
2903 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2904 if (!(isOpenMPParallelDirective(CurDir) ||
2906 isOpenMPSimdDirective(CurDir))
2907 S.Diag(RC->getModifierLoc(),
2908 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2909 continue;
2910 }
2911 }
2912 if (InscanFound) {
2913 for (OMPClause *C : Clauses) {
2914 if (C->getClauseKind() != OMPC_reduction)
2915 continue;
2916 auto *RC = cast<OMPReductionClause>(C);
2917 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2918 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2919 ? RC->getBeginLoc()
2920 : RC->getModifierLoc(),
2921 diag::err_omp_inscan_reduction_expected);
2922 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2923 continue;
2924 }
2925 for (Expr *Ref : RC->varlist()) {
2926 assert(Ref && "NULL expr in OpenMP reduction clause.");
2927 SourceLocation ELoc;
2928 SourceRange ERange;
2929 Expr *SimpleRefExpr = Ref;
2930 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2931 /*AllowArraySection=*/true);
2932 ValueDecl *D = Res.first;
2933 if (!D)
2934 continue;
2935 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2936 S.Diag(Ref->getExprLoc(),
2937 diag::err_omp_reduction_not_inclusive_exclusive)
2938 << Ref->getSourceRange();
2939 }
2940 }
2941 }
2942 }
2943}
2944
2945static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2946 ArrayRef<OMPClause *> Clauses);
2947static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2948 bool WithInit);
2949
2950static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2951 const ValueDecl *D,
2952 const DSAStackTy::DSAVarData &DVar,
2953 bool IsLoopIterVar = false);
2954
2956 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2957 // A variable of class type (or array thereof) that appears in a lastprivate
2958 // clause requires an accessible, unambiguous default constructor for the
2959 // class type, unless the list item is also specified in a firstprivate
2960 // clause.
2961
2962 auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) {
2963 SmallVector<Expr *, 8> PrivateCopies;
2964 for (Expr *DE : Clause->varlist()) {
2965 if (DE->isValueDependent() || DE->isTypeDependent()) {
2966 PrivateCopies.push_back(nullptr);
2967 continue;
2968 }
2969 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2970 auto *VD = cast<VarDecl>(DRE->getDecl());
2972 const DSAStackTy::DSAVarData DVar =
2973 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2974 if (DVar.CKind != OMPC_lastprivate) {
2975 // The variable is also a firstprivate, so initialization sequence
2976 // for private copy is generated already.
2977 PrivateCopies.push_back(nullptr);
2978 continue;
2979 }
2980 // Generate helper private variable and initialize it with the
2981 // default value. The address of the original variable is replaced
2982 // by the address of the new private variable in CodeGen. This new
2983 // variable is not added to IdResolver, so the code in the OpenMP
2984 // region uses original variable for proper diagnostics.
2985 VarDecl *VDPrivate = buildVarDecl(
2986 SemaRef, DE->getExprLoc(), Type.getUnqualifiedType(), VD->getName(),
2987 VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2988 SemaRef.ActOnUninitializedDecl(VDPrivate);
2989 if (VDPrivate->isInvalidDecl()) {
2990 PrivateCopies.push_back(nullptr);
2991 continue;
2992 }
2993 PrivateCopies.push_back(buildDeclRefExpr(
2994 SemaRef, VDPrivate, DE->getType(), DE->getExprLoc()));
2995 }
2996 Clause->setPrivateCopies(PrivateCopies);
2997 };
2998
2999 auto FinalizeNontemporal = [&](OMPNontemporalClause *Clause) {
3000 // Finalize nontemporal clause by handling private copies, if any.
3001 SmallVector<Expr *, 8> PrivateRefs;
3002 for (Expr *RefExpr : Clause->varlist()) {
3003 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
3004 SourceLocation ELoc;
3005 SourceRange ERange;
3006 Expr *SimpleRefExpr = RefExpr;
3007 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
3008 if (Res.second)
3009 // It will be analyzed later.
3010 PrivateRefs.push_back(RefExpr);
3011 ValueDecl *D = Res.first;
3012 if (!D)
3013 continue;
3014
3015 const DSAStackTy::DSAVarData DVar =
3016 DSAStack->getTopDSA(D, /*FromParent=*/false);
3017 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
3018 : SimpleRefExpr);
3019 }
3020 Clause->setPrivateRefs(PrivateRefs);
3021 };
3022
3023 auto FinalizeAllocators = [&](OMPUsesAllocatorsClause *Clause) {
3024 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
3025 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
3026 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
3027 if (!DRE)
3028 continue;
3029 ValueDecl *VD = DRE->getDecl();
3030 if (!VD || !isa<VarDecl>(VD))
3031 continue;
3032 DSAStackTy::DSAVarData DVar =
3033 DSAStack->getTopDSA(VD, /*FromParent=*/false);
3034 // OpenMP [2.12.5, target Construct]
3035 // Memory allocators that appear in a uses_allocators clause cannot
3036 // appear in other data-sharing attribute clauses or data-mapping
3037 // attribute clauses in the same construct.
3038 Expr *MapExpr = nullptr;
3039 if (DVar.RefExpr ||
3040 DSAStack->checkMappableExprComponentListsForDecl(
3041 VD, /*CurrentRegionOnly=*/true,
3042 [VD, &MapExpr](
3044 MapExprComponents,
3046 auto MI = MapExprComponents.rbegin();
3047 auto ME = MapExprComponents.rend();
3048 if (MI != ME &&
3049 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
3050 VD->getCanonicalDecl()) {
3051 MapExpr = MI->getAssociatedExpression();
3052 return true;
3053 }
3054 return false;
3055 })) {
3056 Diag(D.Allocator->getExprLoc(), diag::err_omp_allocator_used_in_clauses)
3057 << D.Allocator->getSourceRange();
3058 if (DVar.RefExpr)
3060 else
3061 Diag(MapExpr->getExprLoc(), diag::note_used_here)
3062 << MapExpr->getSourceRange();
3063 }
3064 }
3065 };
3066
3067 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
3068 for (OMPClause *C : D->clauses()) {
3069 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
3070 FinalizeLastprivate(Clause);
3071 } else if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
3072 FinalizeNontemporal(Clause);
3073 } else if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
3074 FinalizeAllocators(Clause);
3075 }
3076 }
3077 // Check allocate clauses.
3078 if (!SemaRef.CurContext->isDependentContext())
3079 checkAllocateClauses(SemaRef, DSAStack, D->clauses());
3080 checkReductionClauses(SemaRef, DSAStack, D->clauses());
3081 }
3082
3083 DSAStack->pop();
3086}
3087
3088static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
3089 Expr *NumIterations, Sema &SemaRef,
3090 Scope *S, DSAStackTy *Stack);
3091
3092static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
3093 OMPLoopBasedDirective::HelperExprs &B,
3094 DSAStackTy *Stack) {
3095 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
3096 "loop exprs were not built");
3097
3098 if (SemaRef.CurContext->isDependentContext())
3099 return false;
3100
3101 // Finalize the clauses that need pre-built expressions for CodeGen.
3102 for (OMPClause *C : Clauses) {
3103 auto *LC = dyn_cast<OMPLinearClause>(C);
3104 if (!LC)
3105 continue;
3106 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
3107 B.NumIterations, SemaRef,
3108 SemaRef.getCurScope(), Stack))
3109 return true;
3110 }
3111
3112 return false;
3113}
3114
3115namespace {
3116
3117class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3118private:
3119 Sema &SemaRef;
3120
3121public:
3122 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3123 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3124 NamedDecl *ND = Candidate.getCorrectionDecl();
3125 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3126 return VD->hasGlobalStorage() &&
3127 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3128 SemaRef.getCurScope());
3129 }
3130 return false;
3131 }
3132
3133 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3134 return std::make_unique<VarDeclFilterCCC>(*this);
3135 }
3136};
3137
3138class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3139private:
3140 Sema &SemaRef;
3141
3142public:
3143 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3144 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3145 NamedDecl *ND = Candidate.getCorrectionDecl();
3146 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3147 isa<FunctionDecl>(ND))) {
3148 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3149 SemaRef.getCurScope());
3150 }
3151 return false;
3152 }
3153
3154 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3155 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3156 }
3157};
3158
3159} // namespace
3160
3162 CXXScopeSpec &ScopeSpec,
3163 const DeclarationNameInfo &Id,
3164 OpenMPDirectiveKind Kind) {
3165 ASTContext &Context = getASTContext();
3166 unsigned OMPVersion = getLangOpts().OpenMP;
3168 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
3169 /*ObjectType=*/QualType(),
3170 /*AllowBuiltinCreation=*/true);
3171
3172 if (Lookup.isAmbiguous())
3173 return ExprError();
3174
3175 VarDecl *VD;
3176 if (!Lookup.isSingleResult()) {
3177 VarDeclFilterCCC CCC(SemaRef);
3178 if (TypoCorrection Corrected =
3179 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
3181 SemaRef.diagnoseTypo(
3182 Corrected,
3183 SemaRef.PDiag(Lookup.empty() ? diag::err_undeclared_var_use_suggest
3184 : diag::err_omp_expected_var_arg_suggest)
3185 << Id.getName());
3186 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3187 } else {
3188 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3189 : diag::err_omp_expected_var_arg)
3190 << Id.getName();
3191 return ExprError();
3192 }
3193 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3194 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3195 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3196 return ExprError();
3197 }
3198 Lookup.suppressDiagnostics();
3199
3200 // OpenMP [2.9.2, Syntax, C/C++]
3201 // Variables must be file-scope, namespace-scope, or static block-scope.
3202 if ((Kind == OMPD_threadprivate || Kind == OMPD_groupprivate) &&
3203 !VD->hasGlobalStorage()) {
3204 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3205 << getOpenMPDirectiveName(Kind, OMPVersion) << !VD->isStaticLocal();
3206 bool IsDecl =
3208 Diag(VD->getLocation(),
3209 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3210 << VD;
3211 return ExprError();
3212 }
3213
3214 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3215 NamedDecl *ND = CanonicalVD;
3216 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3217 // A threadprivate or groupprivate directive for file-scope variables must
3218 // appear outside any definition or declaration.
3219 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3220 !SemaRef.getCurLexicalContext()->isTranslationUnit()) {
3221 Diag(Id.getLoc(), diag::err_omp_var_scope)
3222 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3223 bool IsDecl =
3225 Diag(VD->getLocation(),
3226 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3227 << VD;
3228 return ExprError();
3229 }
3230 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3231 // A threadprivate or groupprivate directive for static class member
3232 // variables must appear in the class definition, in the same scope in which
3233 // the member variables are declared.
3234 if (CanonicalVD->isStaticDataMember() &&
3235 !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) {
3236 Diag(Id.getLoc(), diag::err_omp_var_scope)
3237 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3238 bool IsDecl =
3240 Diag(VD->getLocation(),
3241 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3242 << VD;
3243 return ExprError();
3244 }
3245 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3246 // A threadprivate or groupprivate directive for namespace-scope variables
3247 // must appear outside any definition or declaration other than the
3248 // namespace definition itself.
3249 if (CanonicalVD->getDeclContext()->isNamespace() &&
3250 (!SemaRef.getCurLexicalContext()->isFileContext() ||
3251 !SemaRef.getCurLexicalContext()->Encloses(
3252 CanonicalVD->getDeclContext()))) {
3253 Diag(Id.getLoc(), diag::err_omp_var_scope)
3254 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3255 bool IsDecl =
3257 Diag(VD->getLocation(),
3258 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3259 << VD;
3260 return ExprError();
3261 }
3262 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3263 // A threadprivate or groupprivate directive for static block-scope
3264 // variables must appear in the scope of the variable and not in a nested
3265 // scope.
3266 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3267 !SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(), CurScope)) {
3268 Diag(Id.getLoc(), diag::err_omp_var_scope)
3269 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3270 bool IsDecl =
3272 Diag(VD->getLocation(),
3273 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3274 << VD;
3275 return ExprError();
3276 }
3277
3278 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3279 // A threadprivate or groupprivate directive must lexically precede all
3280 // references to any of the variables in its list.
3281 if ((Kind == OMPD_threadprivate && VD->isUsed() &&
3282 !DSAStack->isThreadPrivate(VD)) ||
3283 (Kind == OMPD_groupprivate && VD->isUsed())) {
3284 Diag(Id.getLoc(), diag::err_omp_var_used)
3285 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3286 return ExprError();
3287 }
3288
3289 QualType ExprType = VD->getType().getNonReferenceType();
3291 SourceLocation(), VD,
3292 /*RefersToEnclosingVariableOrCapture=*/false,
3293 Id.getLoc(), ExprType, VK_LValue);
3294}
3295
3298 ArrayRef<Expr *> VarList) {
3299 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3300 SemaRef.CurContext->addDecl(D);
3302 }
3303 return nullptr;
3304}
3305
3308 ArrayRef<Expr *> VarList) {
3309 if (!getLangOpts().OpenMP || getLangOpts().OpenMP < 60) {
3310 Diag(Loc, diag::err_omp_unexpected_directive)
3311 << getOpenMPDirectiveName(OMPD_groupprivate, getLangOpts().OpenMP);
3312 return nullptr;
3313 }
3314 if (OMPGroupPrivateDecl *D = CheckOMPGroupPrivateDecl(Loc, VarList)) {
3315 SemaRef.CurContext->addDecl(D);
3317 }
3318 return nullptr;
3319}
3320
3321namespace {
3322class LocalVarRefChecker final
3323 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3324 Sema &SemaRef;
3325
3326public:
3327 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3328 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3329 if (VD->hasLocalStorage()) {
3330 SemaRef.Diag(E->getBeginLoc(),
3331 diag::err_omp_local_var_in_threadprivate_init)
3332 << E->getSourceRange();
3333 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3334 << VD << VD->getSourceRange();
3335 return true;
3336 }
3337 }
3338 return false;
3339 }
3340 bool VisitStmt(const Stmt *S) {
3341 for (const Stmt *Child : S->children()) {
3342 if (Child && Visit(Child))
3343 return true;
3344 }
3345 return false;
3346 }
3347 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3348};
3349} // namespace
3350
3351OMPThreadPrivateDecl *
3353 ArrayRef<Expr *> VarList) {
3354 ASTContext &Context = getASTContext();
3356 for (Expr *RefExpr : VarList) {
3357 auto *DE = cast<DeclRefExpr>(RefExpr);
3358 auto *VD = cast<VarDecl>(DE->getDecl());
3359 SourceLocation ILoc = DE->getExprLoc();
3360
3361 // Mark variable as used.
3362 VD->setReferenced();
3363 VD->markUsed(Context);
3364
3365 QualType QType = VD->getType();
3366 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3367 // It will be analyzed later.
3368 Vars.push_back(DE);
3369 continue;
3370 }
3371
3372 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3373 // A threadprivate variable must not have an incomplete type.
3374 if (SemaRef.RequireCompleteType(
3375 ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) {
3376 continue;
3377 }
3378
3379 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3380 // A threadprivate variable must not have a reference type.
3381 if (VD->getType()->isReferenceType()) {
3382 unsigned OMPVersion = getLangOpts().OpenMP;
3383 Diag(ILoc, diag::err_omp_ref_type_arg)
3384 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion)
3385 << VD->getType();
3386 bool IsDecl =
3388 Diag(VD->getLocation(),
3389 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3390 << VD;
3391 continue;
3392 }
3393
3394 // Check if this is a TLS variable. If TLS is not being supported, produce
3395 // the corresponding diagnostic.
3396 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3397 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3398 getLangOpts().OpenMPUseTLS &&
3399 getASTContext().getTargetInfo().isTLSSupported())) ||
3400 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3401 !VD->isLocalVarDecl())) {
3402 Diag(ILoc, diag::err_omp_var_thread_local)
3403 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3404 bool IsDecl =
3406 Diag(VD->getLocation(),
3407 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3408 << VD;
3409 continue;
3410 }
3411
3412 // Check if initial value of threadprivate variable reference variable with
3413 // local storage (it is not supported by runtime).
3414 if (const Expr *Init = VD->getAnyInitializer()) {
3415 LocalVarRefChecker Checker(SemaRef);
3416 if (Checker.Visit(Init))
3417 continue;
3418 }
3419
3420 Vars.push_back(RefExpr);
3421 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3422 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3423 Context, SourceRange(Loc, Loc)));
3424 if (ASTMutationListener *ML = Context.getASTMutationListener())
3425 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3426 }
3427 OMPThreadPrivateDecl *D = nullptr;
3428 if (!Vars.empty()) {
3429 D = OMPThreadPrivateDecl::Create(Context, SemaRef.getCurLexicalContext(),
3430 Loc, Vars);
3431 D->setAccess(AS_public);
3432 }
3433 return D;
3434}
3435
3438 ArrayRef<Expr *> VarList) {
3439 ASTContext &Context = getASTContext();
3441 for (Expr *RefExpr : VarList) {
3442 auto *DE = cast<DeclRefExpr>(RefExpr);
3443 auto *VD = cast<VarDecl>(DE->getDecl());
3444 SourceLocation ILoc = DE->getExprLoc();
3445
3446 // Mark variable as used.
3447 VD->setReferenced();
3448 VD->markUsed(Context);
3449
3450 QualType QType = VD->getType();
3451 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3452 // It will be analyzed later.
3453 Vars.push_back(DE);
3454 continue;
3455 }
3456
3457 // OpenMP groupprivate restrictions:
3458 // A groupprivate variable must not have an incomplete type.
3459 if (SemaRef.RequireCompleteType(
3460 ILoc, VD->getType(), diag::err_omp_groupprivate_incomplete_type)) {
3461 continue;
3462 }
3463
3464 // A groupprivate variable must not have a reference type.
3465 if (VD->getType()->isReferenceType()) {
3466 Diag(ILoc, diag::err_omp_ref_type_arg)
3467 << getOpenMPDirectiveName(OMPD_groupprivate) << VD->getType();
3468 bool IsDecl =
3470 Diag(VD->getLocation(),
3471 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3472 << VD;
3473 continue;
3474 }
3475
3476 // A variable that is declared with an initializer must not appear in a
3477 // groupprivate directive.
3478 if (VD->getAnyInitializer()) {
3479 Diag(ILoc, diag::err_omp_groupprivate_with_initializer)
3480 << VD->getDeclName();
3481 bool IsDecl =
3483 Diag(VD->getLocation(),
3484 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3485 << VD;
3486 continue;
3487 }
3488
3489 Vars.push_back(RefExpr);
3490 DSAStack->addDSA(VD, DE, OMPC_groupprivate);
3491 VD->addAttr(OMPGroupPrivateDeclAttr::CreateImplicit(Context,
3492 SourceRange(Loc, Loc)));
3493 if (ASTMutationListener *ML = Context.getASTMutationListener())
3494 ML->DeclarationMarkedOpenMPGroupPrivate(VD);
3495 }
3496 OMPGroupPrivateDecl *D = nullptr;
3497 if (!Vars.empty()) {
3498 D = OMPGroupPrivateDecl::Create(Context, SemaRef.getCurLexicalContext(),
3499 Loc, Vars);
3500 D->setAccess(AS_public);
3501 }
3502 return D;
3503}
3504
3505static OMPAllocateDeclAttr::AllocatorTypeTy
3506getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3507 if (!Allocator)
3508 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3509 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3510 Allocator->isInstantiationDependent() ||
3512 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3513 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3514 llvm::FoldingSetNodeID AEId;
3515 const Expr *AE = Allocator->IgnoreParenImpCasts();
3516 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3517 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3518 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3519 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3520 llvm::FoldingSetNodeID DAEId;
3521 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3522 /*Canonical=*/true);
3523 if (AEId == DAEId) {
3524 AllocatorKindRes = AllocatorKind;
3525 break;
3526 }
3527 }
3528 return AllocatorKindRes;
3529}
3530
3532 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3533 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3534 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3535 return false;
3536 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3537 Expr *PrevAllocator = A->getAllocator();
3538 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3539 getAllocatorKind(S, Stack, PrevAllocator);
3540 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3541 if (AllocatorsMatch &&
3542 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3543 Allocator && PrevAllocator) {
3544 const Expr *AE = Allocator->IgnoreParenImpCasts();
3545 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3546 llvm::FoldingSetNodeID AEId, PAEId;
3547 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3548 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3549 AllocatorsMatch = AEId == PAEId;
3550 }
3551 if (!AllocatorsMatch) {
3552 SmallString<256> AllocatorBuffer;
3553 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3554 if (Allocator)
3555 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3556 SmallString<256> PrevAllocatorBuffer;
3557 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3558 if (PrevAllocator)
3559 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3560 S.getPrintingPolicy());
3561
3562 SourceLocation AllocatorLoc =
3563 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3564 SourceRange AllocatorRange =
3565 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3566 SourceLocation PrevAllocatorLoc =
3567 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3568 SourceRange PrevAllocatorRange =
3569 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3570 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3571 << (Allocator ? 1 : 0) << AllocatorStream.str()
3572 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3573 << AllocatorRange;
3574 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3575 << PrevAllocatorRange;
3576 return true;
3577 }
3578 return false;
3579}
3580
3581static void
3583 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3584 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3585 if (VD->hasAttr<OMPAllocateDeclAttr>())
3586 return;
3587 if (Alignment &&
3588 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3589 Alignment->isInstantiationDependent() ||
3590 Alignment->containsUnexpandedParameterPack()))
3591 // Apply later when we have a usable value.
3592 return;
3593 if (Allocator &&
3594 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3595 Allocator->isInstantiationDependent() ||
3596 Allocator->containsUnexpandedParameterPack()))
3597 return;
3598 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3599 Allocator, Alignment, SR);
3600 VD->addAttr(A);
3602 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3603}
3604
3607 DeclContext *Owner) {
3608 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3609 Expr *Alignment = nullptr;
3610 Expr *Allocator = nullptr;
3611 if (Clauses.empty()) {
3612 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3613 // allocate directives that appear in a target region must specify an
3614 // allocator clause unless a requires directive with the dynamic_allocators
3615 // clause is present in the same compilation unit.
3616 if (getLangOpts().OpenMPIsTargetDevice &&
3617 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3618 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3619 } else {
3620 for (const OMPClause *C : Clauses)
3621 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3622 Allocator = AC->getAllocator();
3623 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3624 Alignment = AC->getAlignment();
3625 else
3626 llvm_unreachable("Unexpected clause on allocate directive");
3627 }
3628 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3629 getAllocatorKind(SemaRef, DSAStack, Allocator);
3631 for (Expr *RefExpr : VarList) {
3632 auto *DE = cast<DeclRefExpr>(RefExpr);
3633 auto *VD = cast<VarDecl>(DE->getDecl());
3634
3635 // Check if this is a TLS variable or global register.
3636 if (VD->getTLSKind() != VarDecl::TLS_None ||
3637 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3638 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3639 !VD->isLocalVarDecl()))
3640 continue;
3641
3642 // If the used several times in the allocate directive, the same allocator
3643 // must be used.
3645 AllocatorKind, Allocator))
3646 continue;
3647
3648 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3649 // If a list item has a static storage type, the allocator expression in the
3650 // allocator clause must be a constant expression that evaluates to one of
3651 // the predefined memory allocator values.
3652 if (Allocator && VD->hasGlobalStorage()) {
3653 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3654 Diag(Allocator->getExprLoc(),
3655 diag::err_omp_expected_predefined_allocator)
3656 << Allocator->getSourceRange();
3657 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3659 Diag(VD->getLocation(),
3660 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3661 << VD;
3662 continue;
3663 }
3664 }
3665
3666 Vars.push_back(RefExpr);
3667 applyOMPAllocateAttribute(SemaRef, VD, AllocatorKind, Allocator, Alignment,
3668 DE->getSourceRange());
3669 }
3670 if (Vars.empty())
3671 return nullptr;
3672 if (!Owner)
3673 Owner = SemaRef.getCurLexicalContext();
3674 auto *D = OMPAllocateDecl::Create(getASTContext(), Owner, Loc, Vars, Clauses);
3675 D->setAccess(AS_public);
3676 Owner->addDecl(D);
3678}
3679
3682 ArrayRef<OMPClause *> ClauseList) {
3683 OMPRequiresDecl *D = nullptr;
3684 if (!SemaRef.CurContext->isFileContext()) {
3685 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3686 } else {
3687 D = CheckOMPRequiresDecl(Loc, ClauseList);
3688 if (D) {
3689 SemaRef.CurContext->addDecl(D);
3690 DSAStack->addRequiresDecl(D);
3691 }
3692 }
3694}
3695
3697 OpenMPDirectiveKind DKind,
3698 ArrayRef<std::string> Assumptions,
3699 bool SkippedClauses) {
3700 if (!SkippedClauses && Assumptions.empty()) {
3701 unsigned OMPVersion = getLangOpts().OpenMP;
3702 Diag(Loc, diag::err_omp_no_clause_for_directive)
3703 << llvm::omp::getAllAssumeClauseOptions()
3704 << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion);
3705 }
3706
3707 auto *AA =
3708 OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc);
3709 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3710 OMPAssumeScoped.push_back(AA);
3711 return;
3712 }
3713
3714 // Global assumes without assumption clauses are ignored.
3715 if (Assumptions.empty())
3716 return;
3717
3718 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3719 "Unexpected omp assumption directive!");
3720 OMPAssumeGlobal.push_back(AA);
3721
3722 // The OMPAssumeGlobal scope above will take care of new declarations but
3723 // we also want to apply the assumption to existing ones, e.g., to
3724 // declarations in included headers. To this end, we traverse all existing
3725 // declaration contexts and annotate function declarations here.
3726 SmallVector<DeclContext *, 8> DeclContexts;
3727 auto *Ctx = SemaRef.CurContext;
3728 while (Ctx->getLexicalParent())
3729 Ctx = Ctx->getLexicalParent();
3730 DeclContexts.push_back(Ctx);
3731 while (!DeclContexts.empty()) {
3732 DeclContext *DC = DeclContexts.pop_back_val();
3733 for (auto *SubDC : DC->decls()) {
3734 if (SubDC->isInvalidDecl())
3735 continue;
3736 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3737 DeclContexts.push_back(CTD->getTemplatedDecl());
3738 llvm::append_range(DeclContexts, CTD->specializations());
3739 continue;
3740 }
3741 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3742 DeclContexts.push_back(DC);
3743 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3744 F->addAttr(AA);
3745 continue;
3746 }
3747 }
3748 }
3749}
3750
3752 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3753 OMPAssumeScoped.pop_back();
3754}
3755
3757 Stmt *AStmt,
3758 SourceLocation StartLoc,
3759 SourceLocation EndLoc) {
3760 if (!AStmt)
3761 return StmtError();
3762
3763 return OMPAssumeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
3764 AStmt);
3765}
3766
3769 ArrayRef<OMPClause *> ClauseList) {
3770 /// For target specific clauses, the requires directive cannot be
3771 /// specified after the handling of any of the target regions in the
3772 /// current compilation unit.
3773 ArrayRef<SourceLocation> TargetLocations =
3774 DSAStack->getEncounteredTargetLocs();
3775 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3776 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3777 for (const OMPClause *CNew : ClauseList) {
3778 // Check if any of the requires clauses affect target regions.
3783 Diag(Loc, diag::err_omp_directive_before_requires)
3784 << "target" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3785 for (SourceLocation TargetLoc : TargetLocations) {
3786 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3787 << "target";
3788 }
3789 } else if (!AtomicLoc.isInvalid() &&
3791 Diag(Loc, diag::err_omp_directive_before_requires)
3792 << "atomic" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3793 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3794 << "atomic";
3795 }
3796 }
3797 }
3798
3799 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3801 getASTContext(), SemaRef.getCurLexicalContext(), Loc, ClauseList);
3802 return nullptr;
3803}
3804
3805static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3806 const ValueDecl *D,
3807 const DSAStackTy::DSAVarData &DVar,
3808 bool IsLoopIterVar) {
3809 if (DVar.RefExpr) {
3810 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3811 << getOpenMPClauseNameForDiag(DVar.CKind);
3812 return;
3813 }
3814 enum {
3815 PDSA_StaticMemberShared,
3816 PDSA_StaticLocalVarShared,
3817 PDSA_LoopIterVarPrivate,
3818 PDSA_LoopIterVarLinear,
3819 PDSA_LoopIterVarLastprivate,
3820 PDSA_ConstVarShared,
3821 PDSA_GlobalVarShared,
3822 PDSA_TaskVarFirstprivate,
3823 PDSA_LocalVarPrivate,
3824 PDSA_Implicit
3825 } Reason = PDSA_Implicit;
3826 bool ReportHint = false;
3827 auto ReportLoc = D->getLocation();
3828 auto *VD = dyn_cast<VarDecl>(D);
3829 if (IsLoopIterVar) {
3830 if (DVar.CKind == OMPC_private)
3831 Reason = PDSA_LoopIterVarPrivate;
3832 else if (DVar.CKind == OMPC_lastprivate)
3833 Reason = PDSA_LoopIterVarLastprivate;
3834 else
3835 Reason = PDSA_LoopIterVarLinear;
3836 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3837 DVar.CKind == OMPC_firstprivate) {
3838 Reason = PDSA_TaskVarFirstprivate;
3839 ReportLoc = DVar.ImplicitDSALoc;
3840 } else if (VD && VD->isStaticLocal())
3841 Reason = PDSA_StaticLocalVarShared;
3842 else if (VD && VD->isStaticDataMember())
3843 Reason = PDSA_StaticMemberShared;
3844 else if (VD && VD->isFileVarDecl())
3845 Reason = PDSA_GlobalVarShared;
3846 else if (D->getType().isConstant(SemaRef.getASTContext()))
3847 Reason = PDSA_ConstVarShared;
3848 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3849 ReportHint = true;
3850 Reason = PDSA_LocalVarPrivate;
3851 }
3852 if (Reason != PDSA_Implicit) {
3853 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
3854 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3855 << Reason << ReportHint
3856 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
3857 } else if (DVar.ImplicitDSALoc.isValid()) {
3858 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3859 << getOpenMPClauseNameForDiag(DVar.CKind);
3860 }
3861}
3862
3865 bool IsAggregateOrDeclareTarget,
3866 bool HasConstQualifier) {
3868 switch (M) {
3869 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3870 case OMPC_DEFAULTMAP_MODIFIER_storage:
3871 Kind = OMPC_MAP_alloc;
3872 break;
3873 case OMPC_DEFAULTMAP_MODIFIER_to:
3874 Kind = OMPC_MAP_to;
3875 break;
3876 case OMPC_DEFAULTMAP_MODIFIER_from:
3877 Kind = OMPC_MAP_from;
3878 break;
3879 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3880 Kind = OMPC_MAP_tofrom;
3881 break;
3882 case OMPC_DEFAULTMAP_MODIFIER_present:
3883 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3884 // If implicit-behavior is present, each variable referenced in the
3885 // construct in the category specified by variable-category is treated as if
3886 // it had been listed in a map clause with the map-type of alloc and
3887 // map-type-modifier of present.
3888 Kind = OMPC_MAP_alloc;
3889 break;
3890 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3891 case OMPC_DEFAULTMAP_MODIFIER_private:
3893 llvm_unreachable("Unexpected defaultmap implicit behavior");
3894 case OMPC_DEFAULTMAP_MODIFIER_none:
3895 case OMPC_DEFAULTMAP_MODIFIER_default:
3897 // IsAggregateOrDeclareTarget could be true if:
3898 // 1. the implicit behavior for aggregate is tofrom
3899 // 2. it's a declare target link
3900 if (IsAggregateOrDeclareTarget) {
3901 if (HasConstQualifier)
3902 Kind = OMPC_MAP_to;
3903 else
3904 Kind = OMPC_MAP_tofrom;
3905 break;
3906 }
3907 llvm_unreachable("Unexpected defaultmap implicit behavior");
3908 }
3909 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3910 return Kind;
3911}
3912
3913static bool hasNoMutableFields(const CXXRecordDecl *RD) {
3914 for (const auto *FD : RD->fields()) {
3915 if (FD->isMutable())
3916 return false;
3917 QualType FT = FD->getType();
3918 while (FT->isArrayType())
3920 if (const auto *NestedRD = FT->getAsCXXRecordDecl())
3921 if (!hasNoMutableFields(NestedRD))
3922 return false;
3923 }
3924 return true;
3925}
3926
3928 while (T->isArrayType())
3929 T = T->getAsArrayTypeUnsafe()->getElementType();
3930 if (!T.isConstQualified())
3931 return false;
3932 if (const auto *RD = T->getAsCXXRecordDecl())
3933 // TODO : Per OpenMP 6.0 p299 lines 3-4, non-mutable members of a
3934 // const-qualified struct should also be ignored for 'from'. This
3935 // requires per-member mapping granularity via compiler-generated
3936 // default mappers and a mechanism to ensure constness to the mapper.
3937 // For now we conservatively treat any struct with mutable members as
3938 // requiring full 'tofrom'.
3939 return hasNoMutableFields(RD);
3940 return true;
3941}
3942
3943namespace {
3944struct VariableImplicitInfo {
3945 static const unsigned MapKindNum = OMPC_MAP_unknown;
3946 static const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3947
3948 llvm::SetVector<Expr *> Privates;
3949 llvm::SetVector<Expr *> Firstprivates;
3950 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3951 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3952 MapModifiers[DefaultmapKindNum];
3953};
3954
3955class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3956 DSAStackTy *Stack;
3957 Sema &SemaRef;
3958 OpenMPDirectiveKind DKind = OMPD_unknown;
3959 bool ErrorFound = false;
3960 bool TryCaptureCXXThisMembers = false;
3961 CapturedStmt *CS = nullptr;
3962
3963 VariableImplicitInfo ImpInfo;
3964 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3965 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3966
3967 void VisitSubCaptures(OMPExecutableDirective *S) {
3968 // Check implicitly captured variables.
3969 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3970 return;
3971 if (S->getDirectiveKind() == OMPD_atomic ||
3972 S->getDirectiveKind() == OMPD_critical ||
3973 S->getDirectiveKind() == OMPD_section ||
3974 S->getDirectiveKind() == OMPD_master ||
3975 S->getDirectiveKind() == OMPD_masked ||
3976 S->getDirectiveKind() == OMPD_scope ||
3977 S->getDirectiveKind() == OMPD_assume ||
3978 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3979 Visit(S->getAssociatedStmt());
3980 return;
3981 }
3982 visitSubCaptures(S->getInnermostCapturedStmt());
3983 // Try to capture inner this->member references to generate correct mappings
3984 // and diagnostics.
3985 if (TryCaptureCXXThisMembers ||
3987 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3988 [](const CapturedStmt::Capture &C) {
3989 return C.capturesThis();
3990 }))) {
3991 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3992 TryCaptureCXXThisMembers = true;
3993 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3994 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3995 }
3996 // In tasks firstprivates are not captured anymore, need to analyze them
3997 // explicitly.
3998 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3999 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
4000 for (OMPClause *C : S->clauses())
4001 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
4002 for (Expr *Ref : FC->varlist())
4003 Visit(Ref);
4004 }
4005 }
4006 }
4007
4008public:
4009 void VisitDeclRefExpr(DeclRefExpr *E) {
4010 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
4014 return;
4015 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
4016 // Check the datasharing rules for the expressions in the clauses.
4017 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
4018 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
4019 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
4020 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
4021 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
4022 Visit(CED->getInit());
4023 return;
4024 }
4025 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
4026 // Do not analyze internal variables and do not enclose them into
4027 // implicit clauses.
4028 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
4029 return;
4030 VD = VD->getCanonicalDecl();
4031 // Skip internally declared variables.
4032 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
4033 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4034 !Stack->isImplicitTaskFirstprivate(VD))
4035 return;
4036 // Skip allocators in uses_allocators clauses.
4037 if (Stack->isUsesAllocatorsDecl(VD))
4038 return;
4039
4040 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
4041 // Check if the variable has explicit DSA set and stop analysis if it so.
4042 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
4043 return;
4044
4045 // Skip internally declared static variables.
4046 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
4047 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
4048 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
4049 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
4050 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
4051 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4052 !Stack->isImplicitTaskFirstprivate(VD))
4053 return;
4054
4055 SourceLocation ELoc = E->getExprLoc();
4056 // The default(none) clause requires that each variable that is referenced
4057 // in the construct, and does not have a predetermined data-sharing
4058 // attribute, must have its data-sharing attribute explicitly determined
4059 // by being listed in a data-sharing attribute clause.
4060 if (DVar.CKind == OMPC_unknown &&
4061 (Stack->getDefaultDSA() == DSA_none ||
4062 Stack->getDefaultDSA() == DSA_private ||
4063 Stack->getDefaultDSA() == DSA_firstprivate) &&
4064 isImplicitOrExplicitTaskingRegion(DKind) &&
4065 VarsWithInheritedDSA.count(VD) == 0) {
4066 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
4067 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
4068 Stack->getDefaultDSA() == DSA_private)) {
4069 DSAStackTy::DSAVarData DVar =
4070 Stack->getImplicitDSA(VD, /*FromParent=*/false);
4071 InheritedDSA = DVar.CKind == OMPC_unknown;
4072 }
4073 if (InheritedDSA)
4074 VarsWithInheritedDSA[VD] = E;
4075 if (Stack->getDefaultDSA() == DSA_none)
4076 return;
4077 }
4078
4079 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
4080 // If implicit-behavior is none, each variable referenced in the
4081 // construct that does not have a predetermined data-sharing attribute
4082 // and does not appear in a to or link clause on a declare target
4083 // directive must be listed in a data-mapping attribute clause, a
4084 // data-sharing attribute clause (including a data-sharing attribute
4085 // clause on a combined construct where target. is one of the
4086 // constituent constructs), or an is_device_ptr clause.
4087 OpenMPDefaultmapClauseKind ClauseKind =
4089 if (SemaRef.getLangOpts().OpenMP >= 50) {
4090 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
4091 OMPC_DEFAULTMAP_MODIFIER_none;
4092 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
4093 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
4094 // Only check for data-mapping attribute and is_device_ptr here
4095 // since we have already make sure that the declaration does not
4096 // have a data-sharing attribute above
4097 if (!Stack->checkMappableExprComponentListsForDecl(
4098 VD, /*CurrentRegionOnly=*/true,
4100 MapExprComponents,
4102 auto MI = MapExprComponents.rbegin();
4103 auto ME = MapExprComponents.rend();
4104 return MI != ME && MI->getAssociatedDeclaration() == VD;
4105 })) {
4106 VarsWithInheritedDSA[VD] = E;
4107 return;
4108 }
4109 }
4110 }
4111 if (SemaRef.getLangOpts().OpenMP > 50) {
4112 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
4113 OMPC_DEFAULTMAP_MODIFIER_present;
4114 if (IsModifierPresent) {
4115 if (!llvm::is_contained(ImpInfo.MapModifiers[ClauseKind],
4116 OMPC_MAP_MODIFIER_present)) {
4117 ImpInfo.MapModifiers[ClauseKind].push_back(
4118 OMPC_MAP_MODIFIER_present);
4119 }
4120 }
4121 }
4122
4124 !Stack->isLoopControlVariable(VD).first) {
4125 if (!Stack->checkMappableExprComponentListsForDecl(
4126 VD, /*CurrentRegionOnly=*/true,
4128 StackComponents,
4130 if (SemaRef.LangOpts.OpenMP >= 50)
4131 return !StackComponents.empty();
4132 // Variable is used if it has been marked as an array, array
4133 // section, array shaping or the variable itself.
4134 return StackComponents.size() == 1 ||
4135 llvm::all_of(
4136 llvm::drop_begin(llvm::reverse(StackComponents)),
4137 [](const OMPClauseMappableExprCommon::
4138 MappableComponent &MC) {
4139 return MC.getAssociatedDeclaration() ==
4140 nullptr &&
4141 (isa<ArraySectionExpr>(
4142 MC.getAssociatedExpression()) ||
4143 isa<OMPArrayShapingExpr>(
4144 MC.getAssociatedExpression()) ||
4145 isa<ArraySubscriptExpr>(
4146 MC.getAssociatedExpression()));
4147 });
4148 })) {
4149 bool IsFirstprivate = false;
4150 // By default lambdas are captured as firstprivates.
4151 if (const auto *RD =
4153 IsFirstprivate = RD->isLambda();
4154 IsFirstprivate =
4155 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
4156 if (IsFirstprivate) {
4157 ImpInfo.Firstprivates.insert(E);
4158 } else {
4160 Stack->getDefaultmapModifier(ClauseKind);
4161 if (M == OMPC_DEFAULTMAP_MODIFIER_private) {
4162 ImpInfo.Privates.insert(E);
4163 } else {
4165 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res,
4167 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
4168 }
4169 }
4170 return;
4171 }
4172 }
4173
4174 // OpenMP [2.9.3.6, Restrictions, p.2]
4175 // A list item that appears in a reduction clause of the innermost
4176 // enclosing worksharing or parallel construct may not be accessed in an
4177 // explicit task.
4178 DVar = Stack->hasInnermostDSA(
4179 VD,
4180 [](OpenMPClauseKind C, bool AppliedToPointee) {
4181 return C == OMPC_reduction && !AppliedToPointee;
4182 },
4183 [](OpenMPDirectiveKind K) {
4184 return isOpenMPParallelDirective(K) ||
4186 },
4187 /*FromParent=*/true);
4188 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4189 ErrorFound = true;
4190 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4191 reportOriginalDsa(SemaRef, Stack, VD, DVar);
4192 return;
4193 }
4194
4195 // Define implicit data-sharing attributes for task.
4196 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
4197 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
4198 (((Stack->getDefaultDSA() == DSA_firstprivate &&
4199 DVar.CKind == OMPC_firstprivate) ||
4200 (Stack->getDefaultDSA() == DSA_private &&
4201 DVar.CKind == OMPC_private)) &&
4202 !DVar.RefExpr)) &&
4203 !Stack->isLoopControlVariable(VD).first) {
4204 if (Stack->getDefaultDSA() == DSA_private)
4205 ImpInfo.Privates.insert(E);
4206 else
4207 ImpInfo.Firstprivates.insert(E);
4208 return;
4209 }
4210
4211 // Store implicitly used globals with declare target link for parent
4212 // target.
4213 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
4214 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
4215 Stack->addToParentTargetRegionLinkGlobals(E);
4216 return;
4217 }
4218 }
4219 }
4220 void VisitMemberExpr(MemberExpr *E) {
4221 if (E->isTypeDependent() || E->isValueDependent() ||
4223 return;
4224 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
4225 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
4226 if (!FD)
4227 return;
4228 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
4229 // Check if the variable has explicit DSA set and stop analysis if it
4230 // so.
4231 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
4232 return;
4233
4235 !Stack->isLoopControlVariable(FD).first &&
4236 !Stack->checkMappableExprComponentListsForDecl(
4237 FD, /*CurrentRegionOnly=*/true,
4239 StackComponents,
4241 return isa<CXXThisExpr>(
4242 cast<MemberExpr>(
4243 StackComponents.back().getAssociatedExpression())
4244 ->getBase()
4245 ->IgnoreParens());
4246 })) {
4247 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
4248 // A bit-field cannot appear in a map clause.
4249 //
4250 if (FD->isBitField())
4251 return;
4252
4253 // Check to see if the member expression is referencing a class that
4254 // has already been explicitly mapped
4255 if (Stack->isClassPreviouslyMapped(TE->getType()))
4256 return;
4257
4259 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4260 OpenMPDefaultmapClauseKind ClauseKind =
4263 Modifier, /*IsAggregateOrDeclareTarget=*/true,
4264 /*HasConstQualifier=*/false);
4265 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
4266 return;
4267 }
4268
4269 SourceLocation ELoc = E->getExprLoc();
4270 // OpenMP [2.9.3.6, Restrictions, p.2]
4271 // A list item that appears in a reduction clause of the innermost
4272 // enclosing worksharing or parallel construct may not be accessed in
4273 // an explicit task.
4274 DVar = Stack->hasInnermostDSA(
4275 FD,
4276 [](OpenMPClauseKind C, bool AppliedToPointee) {
4277 return C == OMPC_reduction && !AppliedToPointee;
4278 },
4279 [](OpenMPDirectiveKind K) {
4280 return isOpenMPParallelDirective(K) ||
4282 },
4283 /*FromParent=*/true);
4284 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4285 ErrorFound = true;
4286 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4287 reportOriginalDsa(SemaRef, Stack, FD, DVar);
4288 return;
4289 }
4290
4291 // Define implicit data-sharing attributes for task.
4292 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4293 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4294 !Stack->isLoopControlVariable(FD).first) {
4295 // Check if there is a captured expression for the current field in the
4296 // region. Do not mark it as firstprivate unless there is no captured
4297 // expression.
4298 // TODO: try to make it firstprivate.
4299 if (DVar.CKind != OMPC_unknown)
4300 ImpInfo.Firstprivates.insert(E);
4301 }
4302 return;
4303 }
4306 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4307 DKind, /*NoDiagnose=*/true))
4308 return;
4309 const auto *VD = cast<ValueDecl>(
4310 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4311 if (!Stack->checkMappableExprComponentListsForDecl(
4312 VD, /*CurrentRegionOnly=*/true,
4313 [&CurComponents](
4315 StackComponents,
4317 auto CCI = CurComponents.rbegin();
4318 auto CCE = CurComponents.rend();
4319 for (const auto &SC : llvm::reverse(StackComponents)) {
4320 // Do both expressions have the same kind?
4321 if (CCI->getAssociatedExpression()->getStmtClass() !=
4322 SC.getAssociatedExpression()->getStmtClass())
4323 if (!((isa<ArraySectionExpr>(
4324 SC.getAssociatedExpression()) ||
4325 isa<OMPArrayShapingExpr>(
4326 SC.getAssociatedExpression())) &&
4327 isa<ArraySubscriptExpr>(
4328 CCI->getAssociatedExpression())))
4329 return false;
4330
4331 const Decl *CCD = CCI->getAssociatedDeclaration();
4332 const Decl *SCD = SC.getAssociatedDeclaration();
4333 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4334 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4335 if (SCD != CCD)
4336 return false;
4337 std::advance(CCI, 1);
4338 if (CCI == CCE)
4339 break;
4340 }
4341 return true;
4342 })) {
4343 Visit(E->getBase());
4344 }
4345 } else if (!TryCaptureCXXThisMembers) {
4346 Visit(E->getBase());
4347 }
4348 }
4349 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4350 for (OMPClause *C : S->clauses()) {
4351 // Skip analysis of arguments of private clauses for task|target
4352 // directives.
4353 if (isa_and_nonnull<OMPPrivateClause>(C))
4354 continue;
4355 // Skip analysis of arguments of implicitly defined firstprivate clause
4356 // for task|target directives.
4357 // Skip analysis of arguments of implicitly defined map clause for target
4358 // directives.
4360 C->isImplicit() && !isOpenMPTaskingDirective(DKind))) {
4361 for (Stmt *CC : C->children()) {
4362 if (CC)
4363 Visit(CC);
4364 }
4365 }
4366 }
4367 // Check implicitly captured variables.
4368 VisitSubCaptures(S);
4369 }
4370
4371 void VisitOMPCanonicalLoopNestTransformationDirective(
4372 OMPCanonicalLoopNestTransformationDirective *S) {
4373 // Loop transformation directives do not introduce data sharing
4374 VisitStmt(S);
4375 }
4376
4377 void VisitCallExpr(CallExpr *S) {
4378 for (Stmt *C : S->arguments()) {
4379 if (C) {
4380 // Check implicitly captured variables in the task-based directives to
4381 // check if they must be firstprivatized.
4382 Visit(C);
4383 }
4384 }
4385 if (Expr *Callee = S->getCallee()) {
4386 auto *CI = Callee->IgnoreParenImpCasts();
4387 if (auto *CE = dyn_cast<MemberExpr>(CI))
4388 Visit(CE->getBase());
4389 else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4390 Visit(CE);
4391 }
4392 }
4393 void VisitStmt(Stmt *S) {
4394 for (Stmt *C : S->children()) {
4395 if (C) {
4396 // Check implicitly captured variables in the task-based directives to
4397 // check if they must be firstprivatized.
4398 Visit(C);
4399 }
4400 }
4401 }
4402
4403 void visitSubCaptures(CapturedStmt *S) {
4404 for (const CapturedStmt::Capture &Cap : S->captures()) {
4405 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4406 continue;
4407 VarDecl *VD = Cap.getCapturedVar();
4408 // Do not try to map the variable if it or its sub-component was mapped
4409 // already.
4411 Stack->checkMappableExprComponentListsForDecl(
4412 VD, /*CurrentRegionOnly=*/true,
4414 OpenMPClauseKind) { return true; }))
4415 continue;
4416 DeclRefExpr *DRE = buildDeclRefExpr(
4417 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4418 Cap.getLocation(), /*RefersToCapture=*/true);
4419 Visit(DRE);
4420 }
4421 }
4422 bool isErrorFound() const { return ErrorFound; }
4423 const VariableImplicitInfo &getImplicitInfo() const { return ImpInfo; }
4424 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4425 return VarsWithInheritedDSA;
4426 }
4427
4428 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4429 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4430 DKind = S->getCurrentDirective();
4431 // Process declare target link variables for the target directives.
4433 for (DeclRefExpr *E : Stack->getLinkGlobals())
4434 Visit(E);
4435 }
4436 }
4437};
4438} // namespace
4439
4440static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4441 OpenMPDirectiveKind DKind,
4442 bool ScopeEntry) {
4445 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4446 if (isOpenMPTeamsDirective(DKind))
4447 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4448 if (isOpenMPParallelDirective(DKind))
4449 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4451 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4452 if (isOpenMPSimdDirective(DKind))
4453 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4454 Stack->handleConstructTrait(Traits, ScopeEntry);
4455}
4456
4457static SmallVector<SemaOpenMP::CapturedParamNameType>
4458getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4459 ASTContext &Context = SemaRef.getASTContext();
4460 QualType KmpInt32Ty =
4461 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4462 QualType KmpInt32PtrTy =
4463 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4465 std::make_pair(".global_tid.", KmpInt32PtrTy),
4466 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4467 };
4468 if (LoopBoundSharing) {
4469 QualType KmpSizeTy = Context.getSizeType().withConst();
4470 Params.push_back(std::make_pair(".previous.lb.", KmpSizeTy));
4471 Params.push_back(std::make_pair(".previous.ub.", KmpSizeTy));
4472 }
4473
4474 // __context with shared vars
4475 Params.push_back(std::make_pair(StringRef(), QualType()));
4476 return Params;
4477}
4478
4479static SmallVector<SemaOpenMP::CapturedParamNameType>
4481 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4482}
4483
4484static SmallVector<SemaOpenMP::CapturedParamNameType>
4486 ASTContext &Context = SemaRef.getASTContext();
4487 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4488 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4489 QualType KmpInt32PtrTy =
4490 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4491 QualType Args[] = {VoidPtrTy};
4493 EPI.Variadic = true;
4494 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4496 std::make_pair(".global_tid.", KmpInt32Ty),
4497 std::make_pair(".part_id.", KmpInt32PtrTy),
4498 std::make_pair(".privates.", VoidPtrTy),
4499 std::make_pair(
4500 ".copy_fn.",
4501 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4502 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4503 std::make_pair(StringRef(), QualType()) // __context with shared vars
4504 };
4505 return Params;
4506}
4507
4508static SmallVector<SemaOpenMP::CapturedParamNameType>
4510 ASTContext &Context = SemaRef.getASTContext();
4512 // __context with shared vars
4513 Params.push_back(std::make_pair(StringRef(), QualType()));
4514 // Implicit dyn_ptr argument, appended as the last parameter. Present on both
4515 // host and device so argument counts match without runtime manipulation.
4516 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4517 Params.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4518 return Params;
4519}
4520
4521static SmallVector<SemaOpenMP::CapturedParamNameType>
4524 std::make_pair(StringRef(), QualType()) // __context with shared vars
4525 };
4526 return Params;
4527}
4528
4529static SmallVector<SemaOpenMP::CapturedParamNameType>
4531 ASTContext &Context = SemaRef.getASTContext();
4532 QualType KmpInt32Ty =
4533 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4534 QualType KmpUInt64Ty =
4535 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4536 QualType KmpInt64Ty =
4537 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4538 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4539 QualType KmpInt32PtrTy =
4540 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4541 QualType Args[] = {VoidPtrTy};
4543 EPI.Variadic = true;
4544 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4546 std::make_pair(".global_tid.", KmpInt32Ty),
4547 std::make_pair(".part_id.", KmpInt32PtrTy),
4548 std::make_pair(".privates.", VoidPtrTy),
4549 std::make_pair(
4550 ".copy_fn.",
4551 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4552 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4553 std::make_pair(".lb.", KmpUInt64Ty),
4554 std::make_pair(".ub.", KmpUInt64Ty),
4555 std::make_pair(".st.", KmpInt64Ty),
4556 std::make_pair(".liter.", KmpInt32Ty),
4557 std::make_pair(".reductions.", VoidPtrTy),
4558 std::make_pair(StringRef(), QualType()) // __context with shared vars
4559 };
4560 return Params;
4561}
4562
4564 Scope *CurScope, SourceLocation Loc) {
4566 getOpenMPCaptureRegions(Regions, DKind);
4567
4568 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(DKind);
4569
4570 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4571 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4572 SemaRef.getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4573 };
4574
4575 for (auto [Level, RKind] : llvm::enumerate(Regions)) {
4576 switch (RKind) {
4577 // All region kinds that can be returned from `getOpenMPCaptureRegions`
4578 // are listed here.
4579 case OMPD_parallel:
4581 Loc, CurScope, CR_OpenMP,
4582 getParallelRegionParams(SemaRef, LoopBoundSharing), Level);
4583 break;
4584 case OMPD_teams:
4585 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4586 getTeamsRegionParams(SemaRef), Level);
4587 break;
4588 case OMPD_task:
4589 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4590 getTaskRegionParams(SemaRef), Level);
4591 // Mark this captured region as inlined, because we don't use outlined
4592 // function directly.
4593 MarkAsInlined(SemaRef.getCurCapturedRegion());
4594 break;
4595 case OMPD_taskloop:
4596 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4597 getTaskloopRegionParams(SemaRef), Level);
4598 // Mark this captured region as inlined, because we don't use outlined
4599 // function directly.
4600 MarkAsInlined(SemaRef.getCurCapturedRegion());
4601 break;
4602 case OMPD_target:
4603 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4604 getTargetRegionParams(SemaRef), Level);
4605 break;
4606 case OMPD_unknown:
4607 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4608 getUnknownRegionParams(SemaRef));
4609 break;
4610 case OMPD_metadirective:
4611 case OMPD_nothing:
4612 default:
4613 llvm_unreachable("Unexpected capture region");
4614 }
4615 }
4616}
4617
4619 Scope *CurScope) {
4620 switch (DKind) {
4621 case OMPD_atomic:
4622 case OMPD_critical:
4623 case OMPD_masked:
4624 case OMPD_master:
4625 case OMPD_section:
4626 case OMPD_tile:
4627 case OMPD_stripe:
4628 case OMPD_unroll:
4629 case OMPD_reverse:
4630 case OMPD_split:
4631 case OMPD_interchange:
4632 case OMPD_fuse:
4633 case OMPD_assume:
4634 break;
4635 default:
4636 processCapturedRegions(SemaRef, DKind, CurScope,
4637 DSAStack->getConstructLoc());
4638 break;
4639 }
4640
4641 DSAStack->setContext(SemaRef.CurContext);
4642 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
4643}
4644
4645int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4646 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4647}
4648
4651 getOpenMPCaptureRegions(CaptureRegions, DKind);
4652 return CaptureRegions.size();
4653}
4654
4656 Expr *CaptureExpr, bool WithInit,
4657 DeclContext *CurContext,
4658 bool AsExpression) {
4659 assert(CaptureExpr);
4660 ASTContext &C = S.getASTContext();
4661 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4662 QualType Ty = Init->getType();
4663 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4664 if (S.getLangOpts().CPlusPlus) {
4665 Ty = C.getLValueReferenceType(Ty);
4666 } else {
4667 Ty = C.getPointerType(Ty);
4668 ExprResult Res =
4669 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4670 if (!Res.isUsable())
4671 return nullptr;
4672 Init = Res.get();
4673 }
4674 WithInit = true;
4675 }
4676 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4677 CaptureExpr->getBeginLoc());
4678 if (!WithInit)
4679 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4680 CurContext->addHiddenDecl(CED);
4682 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4683 return CED;
4684}
4685
4686static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4687 bool WithInit) {
4689 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4691 else
4692 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4693 S.CurContext,
4694 /*AsExpression=*/false);
4695 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4696 CaptureExpr->getExprLoc());
4697}
4698
4699static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4700 StringRef Name) {
4701 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4702 if (!Ref) {
4704 S, &S.getASTContext().Idents.get(Name), CaptureExpr,
4705 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4706 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4707 CaptureExpr->getExprLoc());
4708 }
4709 ExprResult Res = Ref;
4710 if (!S.getLangOpts().CPlusPlus &&
4711 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4712 Ref->getType()->isPointerType()) {
4713 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4714 if (!Res.isUsable())
4715 return ExprError();
4716 }
4717 return S.DefaultLvalueConversion(Res.get());
4718}
4719
4720namespace {
4721// OpenMP directives parsed in this section are represented as a
4722// CapturedStatement with an associated statement. If a syntax error
4723// is detected during the parsing of the associated statement, the
4724// compiler must abort processing and close the CapturedStatement.
4725//
4726// Combined directives such as 'target parallel' have more than one
4727// nested CapturedStatements. This RAII ensures that we unwind out
4728// of all the nested CapturedStatements when an error is found.
4729class CaptureRegionUnwinderRAII {
4730private:
4731 Sema &S;
4732 bool &ErrorFound;
4733 OpenMPDirectiveKind DKind = OMPD_unknown;
4734
4735public:
4736 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4737 OpenMPDirectiveKind DKind)
4738 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4739 ~CaptureRegionUnwinderRAII() {
4740 if (ErrorFound) {
4741 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4742 while (--ThisCaptureLevel >= 0)
4744 }
4745 }
4746};
4747} // namespace
4748
4750 // Capture variables captured by reference in lambdas for target-based
4751 // directives.
4752 if (!SemaRef.CurContext->isDependentContext() &&
4753 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4755 DSAStack->getCurrentDirective()))) {
4756 QualType Type = V->getType();
4757 if (const auto *RD = Type.getCanonicalType()
4758 .getNonReferenceType()
4759 ->getAsCXXRecordDecl()) {
4760 bool SavedForceCaptureByReferenceInTargetExecutable =
4761 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4762 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4763 /*V=*/true);
4764 if (RD->isLambda()) {
4765 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4766 FieldDecl *ThisCapture;
4767 RD->getCaptureFields(Captures, ThisCapture);
4768 for (const LambdaCapture &LC : RD->captures()) {
4769 if (LC.getCaptureKind() == LCK_ByRef) {
4770 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4771 DeclContext *VDC = VD->getDeclContext();
4772 if (!VDC->Encloses(SemaRef.CurContext))
4773 continue;
4774 SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
4775 } else if (LC.getCaptureKind() == LCK_This) {
4776 QualType ThisTy = SemaRef.getCurrentThisType();
4777 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4778 ThisTy, ThisCapture->getType()))
4779 SemaRef.CheckCXXThisCapture(LC.getLocation());
4780 }
4781 }
4782 }
4783 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4784 SavedForceCaptureByReferenceInTargetExecutable);
4785 }
4786 }
4787}
4788
4790 const ArrayRef<OMPClause *> Clauses) {
4791 const OMPOrderedClause *Ordered = nullptr;
4792 const OMPOrderClause *Order = nullptr;
4793
4794 for (const OMPClause *Clause : Clauses) {
4795 if (Clause->getClauseKind() == OMPC_ordered)
4796 Ordered = cast<OMPOrderedClause>(Clause);
4797 else if (Clause->getClauseKind() == OMPC_order) {
4798 Order = cast<OMPOrderClause>(Clause);
4799 if (Order->getKind() != OMPC_ORDER_concurrent)
4800 Order = nullptr;
4801 }
4802 if (Ordered && Order)
4803 break;
4804 }
4805
4806 if (Ordered && Order) {
4807 S.Diag(Order->getKindKwLoc(),
4808 diag::err_omp_simple_clause_incompatible_with_ordered)
4809 << getOpenMPClauseNameForDiag(OMPC_order)
4810 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4811 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4812 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4813 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4814 return true;
4815 }
4816 return false;
4817}
4818
4820 ArrayRef<OMPClause *> Clauses) {
4822 /*ScopeEntry=*/false);
4823 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
4824 return S;
4825
4826 bool ErrorFound = false;
4827 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4828 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4829 if (!S.isUsable()) {
4830 ErrorFound = true;
4831 return StmtError();
4832 }
4833
4835 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4836 OMPOrderedClause *OC = nullptr;
4837 OMPScheduleClause *SC = nullptr;
4840 // This is required for proper codegen.
4841 for (OMPClause *Clause : Clauses) {
4842 if (!getLangOpts().OpenMPSimd &&
4843 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4844 DSAStack->getCurrentDirective() == OMPD_target) &&
4845 Clause->getClauseKind() == OMPC_in_reduction) {
4846 // Capture taskgroup task_reduction descriptors inside the tasking regions
4847 // with the corresponding in_reduction items.
4848 auto *IRC = cast<OMPInReductionClause>(Clause);
4849 for (Expr *E : IRC->taskgroup_descriptors())
4850 if (E)
4851 SemaRef.MarkDeclarationsReferencedInExpr(E);
4852 }
4853 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4854 Clause->getClauseKind() == OMPC_copyprivate ||
4855 (getLangOpts().OpenMPUseTLS &&
4856 getASTContext().getTargetInfo().isTLSSupported() &&
4857 Clause->getClauseKind() == OMPC_copyin)) {
4858 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4859 // Mark all variables in private list clauses as used in inner region.
4860 for (Stmt *VarRef : Clause->children()) {
4861 if (auto *E = cast_or_null<Expr>(VarRef)) {
4862 SemaRef.MarkDeclarationsReferencedInExpr(E);
4863 }
4864 }
4865 DSAStack->setForceVarCapturing(/*V=*/false);
4866 } else if (CaptureRegions.size() > 1 ||
4867 CaptureRegions.back() != OMPD_unknown) {
4868 if (auto *C = OMPClauseWithPreInit::get(Clause))
4869 PICs.push_back(C);
4870 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4871 if (Expr *E = C->getPostUpdateExpr())
4872 SemaRef.MarkDeclarationsReferencedInExpr(E);
4873 }
4874 }
4875 if (Clause->getClauseKind() == OMPC_schedule)
4876 SC = cast<OMPScheduleClause>(Clause);
4877 else if (Clause->getClauseKind() == OMPC_ordered)
4878 OC = cast<OMPOrderedClause>(Clause);
4879 else if (Clause->getClauseKind() == OMPC_linear)
4880 LCs.push_back(cast<OMPLinearClause>(Clause));
4881 }
4882 // Capture allocator expressions if used.
4883 for (Expr *E : DSAStack->getInnerAllocators())
4884 SemaRef.MarkDeclarationsReferencedInExpr(E);
4885 // OpenMP, 2.7.1 Loop Construct, Restrictions
4886 // The nonmonotonic modifier cannot be specified if an ordered clause is
4887 // specified.
4888 if (SC &&
4889 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4890 SC->getSecondScheduleModifier() ==
4891 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4892 OC) {
4893 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4894 ? SC->getFirstScheduleModifierLoc()
4895 : SC->getSecondScheduleModifierLoc(),
4896 diag::err_omp_simple_clause_incompatible_with_ordered)
4897 << getOpenMPClauseNameForDiag(OMPC_schedule)
4898 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4899 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4900 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4901 ErrorFound = true;
4902 }
4903 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4904 // If an order(concurrent) clause is present, an ordered clause may not appear
4905 // on the same directive.
4906 if (checkOrderedOrderSpecified(SemaRef, Clauses))
4907 ErrorFound = true;
4908 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4909 for (const OMPLinearClause *C : LCs) {
4910 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4911 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4912 }
4913 ErrorFound = true;
4914 }
4915 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4916 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4917 OC->getNumForLoops()) {
4918 unsigned OMPVersion = getLangOpts().OpenMP;
4919 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4920 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(), OMPVersion);
4921 ErrorFound = true;
4922 }
4923 if (ErrorFound) {
4924 return StmtError();
4925 }
4926 StmtResult SR = S;
4927 unsigned CompletedRegions = 0;
4928 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4929 // Mark all variables in private list clauses as used in inner region.
4930 // Required for proper codegen of combined directives.
4931 // TODO: add processing for other clauses.
4932 if (ThisCaptureRegion != OMPD_unknown) {
4933 for (const clang::OMPClauseWithPreInit *C : PICs) {
4934 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4935 // Find the particular capture region for the clause if the
4936 // directive is a combined one with multiple capture regions.
4937 // If the directive is not a combined one, the capture region
4938 // associated with the clause is OMPD_unknown and is generated
4939 // only once.
4940 if (CaptureRegion == ThisCaptureRegion ||
4941 CaptureRegion == OMPD_unknown) {
4942 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4943 for (Decl *D : DS->decls())
4944 SemaRef.MarkVariableReferenced(D->getLocation(),
4945 cast<VarDecl>(D));
4946 }
4947 }
4948 }
4949 }
4950 if (ThisCaptureRegion == OMPD_target) {
4951 // Capture allocator traits in the target region. They are used implicitly
4952 // and, thus, are not captured by default.
4953 for (OMPClause *C : Clauses) {
4954 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4955 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4956 ++I) {
4957 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4958 if (Expr *E = D.AllocatorTraits)
4959 SemaRef.MarkDeclarationsReferencedInExpr(E);
4960 }
4961 continue;
4962 }
4963 }
4964 }
4965 if (ThisCaptureRegion == OMPD_parallel) {
4966 // Capture temp arrays for inscan reductions and locals in aligned
4967 // clauses.
4968 for (OMPClause *C : Clauses) {
4969 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4970 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4971 continue;
4972 for (Expr *E : RC->copy_array_temps())
4973 if (E)
4974 SemaRef.MarkDeclarationsReferencedInExpr(E);
4975 }
4976 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4977 for (Expr *E : AC->varlist())
4978 SemaRef.MarkDeclarationsReferencedInExpr(E);
4979 }
4980 }
4981 }
4982 if (++CompletedRegions == CaptureRegions.size())
4983 DSAStack->setBodyComplete();
4984 SR = SemaRef.ActOnCapturedRegionEnd(SR.get());
4985 }
4986 return SR;
4987}
4988
4989static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4990 OpenMPDirectiveKind CancelRegion,
4991 SourceLocation StartLoc) {
4992 // CancelRegion is only needed for cancel and cancellation_point.
4993 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4994 return false;
4995
4996 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4997 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4998 return false;
4999
5000 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
5001 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
5002 << getOpenMPDirectiveName(CancelRegion, OMPVersion);
5003 return true;
5004}
5005
5006static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
5007 OpenMPDirectiveKind CurrentRegion,
5008 const DeclarationNameInfo &CurrentName,
5009 OpenMPDirectiveKind CancelRegion,
5010 OpenMPBindClauseKind BindKind,
5011 SourceLocation StartLoc) {
5012 if (!Stack->getCurScope())
5013 return false;
5014
5015 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
5016 OpenMPDirectiveKind OffendingRegion = ParentRegion;
5017 bool NestingProhibited = false;
5018 bool CloseNesting = true;
5019 bool OrphanSeen = false;
5020 enum {
5021 NoRecommend,
5022 ShouldBeInParallelRegion,
5023 ShouldBeInOrderedRegion,
5024 ShouldBeInTargetRegion,
5025 ShouldBeInTeamsRegion,
5026 ShouldBeInLoopSimdRegion,
5027 } Recommend = NoRecommend;
5028
5031 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
5032 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
5033 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
5034
5035 if (OMPVersion >= 50 && Stack->isParentOrderConcurrent() &&
5037 SemaRef.LangOpts)) {
5038 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
5039 << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5040 return true;
5041 }
5042 if (isOpenMPSimdDirective(ParentRegion) &&
5043 ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered) ||
5044 (OMPVersion >= 50 && CurrentRegion != OMPD_ordered &&
5045 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
5046 CurrentRegion != OMPD_scan))) {
5047 // OpenMP [2.16, Nesting of Regions]
5048 // OpenMP constructs may not be nested inside a simd region.
5049 // OpenMP [2.8.1,simd Construct, Restrictions]
5050 // An ordered construct with the simd clause is the only OpenMP
5051 // construct that can appear in the simd region.
5052 // Allowing a SIMD construct nested in another SIMD construct is an
5053 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
5054 // message.
5055 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
5056 // The only OpenMP constructs that can be encountered during execution of
5057 // a simd region are the atomic construct, the loop construct, the simd
5058 // construct and the ordered construct with the simd clause.
5059 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
5060 ? diag::err_omp_prohibited_region_simd
5061 : diag::warn_omp_nesting_simd)
5062 << (OMPVersion >= 50 ? 1 : 0);
5063 return CurrentRegion != OMPD_simd;
5064 }
5065 if (EnclosingConstruct == OMPD_atomic) {
5066 // OpenMP [2.16, Nesting of Regions]
5067 // OpenMP constructs may not be nested inside an atomic region.
5068 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
5069 return true;
5070 }
5071 if (CurrentRegion == OMPD_section) {
5072 // OpenMP [2.7.2, sections Construct, Restrictions]
5073 // Orphaned section directives are prohibited. That is, the section
5074 // directives must appear within the sections construct and must not be
5075 // encountered elsewhere in the sections region.
5076 if (EnclosingConstruct != OMPD_sections) {
5077 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
5078 << (ParentRegion != OMPD_unknown)
5079 << getOpenMPDirectiveName(ParentRegion, OMPVersion);
5080 return true;
5081 }
5082 return false;
5083 }
5084 // Allow some constructs (except teams and cancellation constructs) to be
5085 // orphaned (they could be used in functions, called from OpenMP regions
5086 // with the required preconditions).
5087 if (ParentRegion == OMPD_unknown &&
5088 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
5089 CurrentRegion != OMPD_cancellation_point &&
5090 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5091 return false;
5092 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
5093 // for a detailed explanation
5094 if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
5095 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
5096 (isOpenMPWorksharingDirective(ParentRegion) ||
5097 EnclosingConstruct == OMPD_loop)) {
5098 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
5099 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5100 << true << getOpenMPDirectiveName(ParentRegion, OMPVersion)
5101 << ErrorMsgNumber << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5102 return true;
5103 }
5104 if (CurrentRegion == OMPD_cancellation_point ||
5105 CurrentRegion == OMPD_cancel) {
5106 // OpenMP [2.16, Nesting of Regions]
5107 // A cancellation point construct for which construct-type-clause is
5108 // taskgroup must be nested inside a task construct. A cancellation
5109 // point construct for which construct-type-clause is not taskgroup must
5110 // be closely nested inside an OpenMP construct that matches the type
5111 // specified in construct-type-clause.
5112 // A cancel construct for which construct-type-clause is taskgroup must be
5113 // nested inside a task construct. A cancel construct for which
5114 // construct-type-clause is not taskgroup must be closely nested inside an
5115 // OpenMP construct that matches the type specified in
5116 // construct-type-clause.
5117 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(ParentRegion);
5118 if (CancelRegion == OMPD_taskgroup) {
5119 NestingProhibited =
5120 EnclosingConstruct != OMPD_task &&
5121 (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
5122 } else if (CancelRegion == OMPD_sections) {
5123 NestingProhibited = EnclosingConstruct != OMPD_section &&
5124 EnclosingConstruct != OMPD_sections;
5125 } else {
5126 NestingProhibited = CancelRegion != Leafs.back();
5127 }
5128 OrphanSeen = ParentRegion == OMPD_unknown;
5129 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5130 // OpenMP 5.1 [2.22, Nesting of Regions]
5131 // A masked region may not be closely nested inside a worksharing, loop,
5132 // atomic, task, or taskloop region.
5133 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5134 isOpenMPGenericLoopDirective(ParentRegion) ||
5135 isOpenMPTaskingDirective(ParentRegion);
5136 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5137 // OpenMP [2.16, Nesting of Regions]
5138 // A critical region may not be nested (closely or otherwise) inside a
5139 // critical region with the same name. Note that this restriction is not
5140 // sufficient to prevent deadlock.
5141 SourceLocation PreviousCriticalLoc;
5142 bool DeadLock = Stack->hasDirective(
5143 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5144 const DeclarationNameInfo &DNI,
5145 SourceLocation Loc) {
5146 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5147 PreviousCriticalLoc = Loc;
5148 return true;
5149 }
5150 return false;
5151 },
5152 false /* skip top directive */);
5153 if (DeadLock) {
5154 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
5155 << CurrentName.getName();
5156 if (PreviousCriticalLoc.isValid())
5157 SemaRef.Diag(PreviousCriticalLoc,
5158 diag::note_omp_previous_critical_region);
5159 return true;
5160 }
5161 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5162 // OpenMP 5.1 [2.22, Nesting of Regions]
5163 // A scope region may not be closely nested inside a worksharing, loop,
5164 // task, taskloop, critical, ordered, atomic, or masked region.
5165 // OpenMP 5.1 [2.22, Nesting of Regions]
5166 // A barrier region may not be closely nested inside a worksharing, loop,
5167 // task, taskloop, critical, ordered, atomic, or masked region.
5168 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5169 isOpenMPGenericLoopDirective(ParentRegion) ||
5170 isOpenMPTaskingDirective(ParentRegion) ||
5171 llvm::is_contained({OMPD_masked, OMPD_master,
5172 OMPD_critical, OMPD_ordered},
5173 EnclosingConstruct);
5174 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
5175 !isOpenMPParallelDirective(CurrentRegion) &&
5176 !isOpenMPTeamsDirective(CurrentRegion)) {
5177 // OpenMP 5.1 [2.22, Nesting of Regions]
5178 // A loop region that binds to a parallel region or a worksharing region
5179 // may not be closely nested inside a worksharing, loop, task, taskloop,
5180 // critical, ordered, atomic, or masked region.
5181 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5182 isOpenMPGenericLoopDirective(ParentRegion) ||
5183 isOpenMPTaskingDirective(ParentRegion) ||
5184 llvm::is_contained({OMPD_masked, OMPD_master,
5185 OMPD_critical, OMPD_ordered},
5186 EnclosingConstruct);
5187 Recommend = ShouldBeInParallelRegion;
5188 } else if (CurrentRegion == OMPD_ordered) {
5189 // OpenMP [2.16, Nesting of Regions]
5190 // An ordered region may not be closely nested inside a critical,
5191 // atomic, or explicit task region.
5192 // An ordered region must be closely nested inside a loop region (or
5193 // parallel loop region) with an ordered clause.
5194 // OpenMP [2.8.1,simd Construct, Restrictions]
5195 // An ordered construct with the simd clause is the only OpenMP construct
5196 // that can appear in the simd region.
5197 NestingProhibited = EnclosingConstruct == OMPD_critical ||
5198 isOpenMPTaskingDirective(ParentRegion) ||
5199 !(isOpenMPSimdDirective(ParentRegion) ||
5200 Stack->isParentOrderedRegion());
5201 Recommend = ShouldBeInOrderedRegion;
5202 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
5203 // OpenMP [2.16, Nesting of Regions]
5204 // If specified, a teams construct must be contained within a target
5205 // construct.
5206 NestingProhibited =
5207 (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
5208 (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
5209 EnclosingConstruct != OMPD_target);
5210 OrphanSeen = ParentRegion == OMPD_unknown;
5211 Recommend = ShouldBeInTargetRegion;
5212 } else if (CurrentRegion == OMPD_scan) {
5213 if (OMPVersion >= 50) {
5214 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
5215 // simd, or for simd. This has to take into account combined directives.
5216 // In 5.2 this seems to be implied by the fact that the specified
5217 // separated constructs are do, for, and simd.
5218 NestingProhibited = !llvm::is_contained(
5219 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
5220 } else {
5221 NestingProhibited = true;
5222 }
5223 OrphanSeen = ParentRegion == OMPD_unknown;
5224 Recommend = ShouldBeInLoopSimdRegion;
5225 }
5226 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5227 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5228 EnclosingConstruct == OMPD_teams) {
5229 // OpenMP [5.1, 2.22, Nesting of Regions]
5230 // distribute, distribute simd, distribute parallel worksharing-loop,
5231 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5232 // including any parallel regions arising from combined constructs,
5233 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5234 // only OpenMP regions that may be strictly nested inside the teams
5235 // region.
5236 //
5237 // As an extension, we permit atomic within teams as well.
5238 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5239 !isOpenMPDistributeDirective(CurrentRegion) &&
5240 CurrentRegion != OMPD_loop &&
5241 !(SemaRef.getLangOpts().OpenMPExtensions &&
5242 CurrentRegion == OMPD_atomic);
5243 Recommend = ShouldBeInParallelRegion;
5244 }
5245 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5246 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5247 // If the bind clause is present on the loop construct and binding is
5248 // teams then the corresponding loop region must be strictly nested inside
5249 // a teams region.
5250 NestingProhibited =
5251 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5252 Recommend = ShouldBeInTeamsRegion;
5253 }
5254 if (!NestingProhibited && isOpenMPNestingDistributeDirective(CurrentRegion)) {
5255 // OpenMP 4.5 [2.17 Nesting of Regions]
5256 // The region associated with the distribute construct must be strictly
5257 // nested inside a teams region
5258 NestingProhibited = EnclosingConstruct != OMPD_teams;
5259 Recommend = ShouldBeInTeamsRegion;
5260 }
5261 if (!NestingProhibited &&
5262 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5263 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5264 // OpenMP 4.5 [2.17 Nesting of Regions]
5265 // If a target, target update, target data, target enter data, or
5266 // target exit data construct is encountered during execution of a
5267 // target region, the behavior is unspecified.
5268 NestingProhibited = Stack->hasDirective(
5269 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5272 OffendingRegion = K;
5273 return true;
5274 }
5275 return false;
5276 },
5277 false /* don't skip top directive */);
5278 CloseNesting = false;
5279 }
5280 if (NestingProhibited) {
5281 if (OrphanSeen) {
5282 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5283 << getOpenMPDirectiveName(CurrentRegion, OMPVersion) << Recommend;
5284 } else {
5285 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5286 << CloseNesting << getOpenMPDirectiveName(OffendingRegion, OMPVersion)
5287 << Recommend << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5288 }
5289 return true;
5290 }
5291 return false;
5292}
5293
5299 ArrayRef<OMPClause *> Clauses,
5300 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5301 bool ErrorFound = false;
5302 unsigned NamedModifiersNumber = 0;
5303 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5304 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5305 SmallVector<SourceLocation, 4> NameModifierLoc;
5306 unsigned OMPVersion = S.getLangOpts().OpenMP;
5307 for (const OMPClause *C : Clauses) {
5308 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5309 // At most one if clause without a directive-name-modifier can appear on
5310 // the directive.
5311 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5312 auto &FNM = FoundNameModifiers[CurNM];
5313 if (FNM) {
5314 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5315 << getOpenMPDirectiveName(Kind, OMPVersion)
5316 << getOpenMPClauseNameForDiag(OMPC_if) << (CurNM != OMPD_unknown)
5317 << getOpenMPDirectiveName(CurNM, OMPVersion);
5318 ErrorFound = true;
5319 } else if (CurNM != OMPD_unknown) {
5320 NameModifierLoc.push_back(IC->getNameModifierLoc());
5321 ++NamedModifiersNumber;
5322 }
5323 FNM = IC;
5324 if (CurNM == OMPD_unknown)
5325 continue;
5326 // Check if the specified name modifier is allowed for the current
5327 // directive.
5328 // At most one if clause with the particular directive-name-modifier can
5329 // appear on the directive.
5330 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5331 S.Diag(IC->getNameModifierLoc(),
5332 diag::err_omp_wrong_if_directive_name_modifier)
5333 << getOpenMPDirectiveName(CurNM, OMPVersion)
5334 << getOpenMPDirectiveName(Kind, OMPVersion);
5335 ErrorFound = true;
5336 }
5337 }
5338 }
5339 // If any if clause on the directive includes a directive-name-modifier then
5340 // all if clauses on the directive must include a directive-name-modifier.
5341 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5342 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5343 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5344 diag::err_omp_no_more_if_clause);
5345 } else {
5346 std::string Values;
5347 std::string Sep(", ");
5348 unsigned AllowedCnt = 0;
5349 unsigned TotalAllowedNum =
5350 AllowedNameModifiers.size() - NamedModifiersNumber;
5351 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5352 ++Cnt) {
5353 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5354 if (!FoundNameModifiers[NM]) {
5355 Values += "'";
5356 Values += getOpenMPDirectiveName(NM, OMPVersion);
5357 Values += "'";
5358 if (AllowedCnt + 2 == TotalAllowedNum)
5359 Values += " or ";
5360 else if (AllowedCnt + 1 != TotalAllowedNum)
5361 Values += Sep;
5362 ++AllowedCnt;
5363 }
5364 }
5365 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5366 diag::err_omp_unnamed_if_clause)
5367 << (TotalAllowedNum > 1) << Values;
5368 }
5369 for (SourceLocation Loc : NameModifierLoc) {
5370 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5371 }
5372 ErrorFound = true;
5373 }
5374 return ErrorFound;
5375}
5376
5377static std::pair<ValueDecl *, bool>
5379 SourceRange &ERange, bool AllowArraySection,
5380 bool AllowAssumedSizeArray, StringRef DiagType) {
5381 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5383 return std::make_pair(nullptr, true);
5384
5385 // OpenMP [3.1, C/C++]
5386 // A list item is a variable name.
5387 // OpenMP [2.9.3.3, Restrictions, p.1]
5388 // A variable that is part of another variable (as an array or
5389 // structure element) cannot appear in a private clause.
5390 //
5391 // OpenMP [6.0]
5392 // 5.2.5 Array Sections, p. 166, L28-29
5393 // When the length is absent and the size of the dimension is not known,
5394 // the array section is an assumed-size array.
5395 // 2 Glossary, p. 23, L4-6
5396 // assumed-size array
5397 // For C/C++, an array section for which the length is absent and the
5398 // size of the dimensions is not known.
5399 // 5.2.5 Array Sections, p. 168, L11
5400 // An assumed-size array can appear only in clauses for which it is
5401 // explicitly allowed.
5402 // 7.4 List Item Privatization, Restrictions, p. 222, L15
5403 // Assumed-size arrays must not be privatized.
5404 RefExpr = RefExpr->IgnoreParens();
5405 enum {
5406 NoArrayExpr = -1,
5407 ArraySubscript = 0,
5408 OMPArraySection = 1
5409 } IsArrayExpr = NoArrayExpr;
5410 if (AllowArraySection) {
5411 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5412 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5413 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5414 Base = TempASE->getBase()->IgnoreParenImpCasts();
5415 RefExpr = Base;
5416 IsArrayExpr = ArraySubscript;
5417 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5418 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5419 if (S.getLangOpts().OpenMP >= 60 && !AllowAssumedSizeArray &&
5420 OASE->getColonLocFirst().isValid() && !OASE->getLength()) {
5422 if (BaseType.isNull() || (!BaseType->isConstantArrayType() &&
5423 !BaseType->isVariableArrayType())) {
5424 S.Diag(OASE->getColonLocFirst(),
5425 diag::err_omp_section_length_undefined)
5426 << (!BaseType.isNull() && BaseType->isArrayType());
5427 return std::make_pair(nullptr, false);
5428 }
5429 }
5430 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Base))
5431 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5432 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5433 Base = TempASE->getBase()->IgnoreParenImpCasts();
5434 RefExpr = Base;
5435 IsArrayExpr = OMPArraySection;
5436 }
5437 }
5438 ELoc = RefExpr->getExprLoc();
5439 ERange = RefExpr->getSourceRange();
5440 RefExpr = RefExpr->IgnoreParenImpCasts();
5441 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5442 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5443 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5444 (S.getCurrentThisType().isNull() || !ME ||
5445 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5446 !isa<FieldDecl>(ME->getMemberDecl()))) {
5447 if (IsArrayExpr != NoArrayExpr) {
5448 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5449 << IsArrayExpr << ERange;
5450 } else if (!DiagType.empty()) {
5451 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5452 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5453 : 0;
5454 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5455 << DiagSelect << DiagType << ERange;
5456 } else {
5457 S.Diag(ELoc,
5458 AllowArraySection
5459 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5460 : diag::err_omp_expected_var_name_member_expr)
5461 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5462 }
5463 return std::make_pair(nullptr, false);
5464 }
5465 return std::make_pair(
5466 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5467}
5468
5469namespace {
5470/// Checks if the allocator is used in uses_allocators clause to be allowed in
5471/// target regions.
5472class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5473 DSAStackTy *S = nullptr;
5474
5475public:
5476 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5477 return S->isUsesAllocatorsDecl(E->getDecl())
5478 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5479 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5480 }
5481 bool VisitStmt(const Stmt *S) {
5482 for (const Stmt *Child : S->children()) {
5483 if (Child && Visit(Child))
5484 return true;
5485 }
5486 return false;
5487 }
5488 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5489};
5490} // namespace
5491
5492static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5493 ArrayRef<OMPClause *> Clauses) {
5494 assert(!S.CurContext->isDependentContext() &&
5495 "Expected non-dependent context.");
5496 auto AllocateRange =
5497 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5498 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5499 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5500 return isOpenMPPrivate(C->getClauseKind());
5501 });
5502 for (OMPClause *Cl : PrivateRange) {
5504 if (Cl->getClauseKind() == OMPC_private) {
5505 auto *PC = cast<OMPPrivateClause>(Cl);
5506 I = PC->private_copies().begin();
5507 It = PC->varlist_begin();
5508 Et = PC->varlist_end();
5509 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5510 auto *PC = cast<OMPFirstprivateClause>(Cl);
5511 I = PC->private_copies().begin();
5512 It = PC->varlist_begin();
5513 Et = PC->varlist_end();
5514 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5515 auto *PC = cast<OMPLastprivateClause>(Cl);
5516 I = PC->private_copies().begin();
5517 It = PC->varlist_begin();
5518 Et = PC->varlist_end();
5519 } else if (Cl->getClauseKind() == OMPC_linear) {
5520 auto *PC = cast<OMPLinearClause>(Cl);
5521 I = PC->privates().begin();
5522 It = PC->varlist_begin();
5523 Et = PC->varlist_end();
5524 } else if (Cl->getClauseKind() == OMPC_reduction) {
5525 auto *PC = cast<OMPReductionClause>(Cl);
5526 I = PC->privates().begin();
5527 It = PC->varlist_begin();
5528 Et = PC->varlist_end();
5529 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5530 auto *PC = cast<OMPTaskReductionClause>(Cl);
5531 I = PC->privates().begin();
5532 It = PC->varlist_begin();
5533 Et = PC->varlist_end();
5534 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5535 auto *PC = cast<OMPInReductionClause>(Cl);
5536 I = PC->privates().begin();
5537 It = PC->varlist_begin();
5538 Et = PC->varlist_end();
5539 } else {
5540 llvm_unreachable("Expected private clause.");
5541 }
5542 for (Expr *E : llvm::make_range(It, Et)) {
5543 if (!*I) {
5544 ++I;
5545 continue;
5546 }
5547 SourceLocation ELoc;
5548 SourceRange ERange;
5549 Expr *SimpleRefExpr = E;
5550 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5551 /*AllowArraySection=*/true);
5552 DeclToCopy.try_emplace(Res.first,
5553 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5554 ++I;
5555 }
5556 }
5557 for (OMPClause *C : AllocateRange) {
5558 auto *AC = cast<OMPAllocateClause>(C);
5559 if (S.getLangOpts().OpenMP >= 50 &&
5560 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5561 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5562 AC->getAllocator()) {
5563 Expr *Allocator = AC->getAllocator();
5564 // OpenMP, 2.12.5 target Construct
5565 // Memory allocators that do not appear in a uses_allocators clause cannot
5566 // appear as an allocator in an allocate clause or be used in the target
5567 // region unless a requires directive with the dynamic_allocators clause
5568 // is present in the same compilation unit.
5569 AllocatorChecker Checker(Stack);
5570 if (Checker.Visit(Allocator))
5571 S.Diag(Allocator->getExprLoc(),
5572 diag::err_omp_allocator_not_in_uses_allocators)
5573 << Allocator->getSourceRange();
5574 }
5575 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5576 getAllocatorKind(S, Stack, AC->getAllocator());
5577 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5578 // For task, taskloop or target directives, allocation requests to memory
5579 // allocators with the trait access set to thread result in unspecified
5580 // behavior.
5581 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5582 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5583 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5584 unsigned OMPVersion = S.getLangOpts().OpenMP;
5585 S.Diag(AC->getAllocator()->getExprLoc(),
5586 diag::warn_omp_allocate_thread_on_task_target_directive)
5587 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
5588 }
5589 for (Expr *E : AC->varlist()) {
5590 SourceLocation ELoc;
5591 SourceRange ERange;
5592 Expr *SimpleRefExpr = E;
5593 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5594 ValueDecl *VD = Res.first;
5595 if (!VD)
5596 continue;
5597 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5598 if (!isOpenMPPrivate(Data.CKind)) {
5599 S.Diag(E->getExprLoc(),
5600 diag::err_omp_expected_private_copy_for_allocate);
5601 continue;
5602 }
5603 VarDecl *PrivateVD = DeclToCopy[VD];
5604 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5605 AllocatorKind, AC->getAllocator()))
5606 continue;
5607 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5608 AC->getAlignment(), E->getSourceRange());
5609 }
5610 }
5611}
5612
5613namespace {
5614/// Rewrite statements and expressions for Sema \p Actions CurContext.
5615///
5616/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5617/// context. DeclRefExpr used inside the new context are changed to refer to the
5618/// captured variable instead.
5619class CaptureVars : public TreeTransform<CaptureVars> {
5620 using BaseTransform = TreeTransform<CaptureVars>;
5621
5622public:
5623 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5624
5625 bool AlwaysRebuild() { return true; }
5626};
5627} // namespace
5628
5629static VarDecl *precomputeExpr(Sema &Actions,
5630 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5631 StringRef Name) {
5632 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5633 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5634 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5635 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5636 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5637 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5638 BodyStmts.push_back(NewDeclStmt);
5639 return NewVar;
5640}
5641
5642/// Create a closure that computes the number of iterations of a loop.
5643///
5644/// \param Actions The Sema object.
5645/// \param LogicalTy Type for the logical iteration number.
5646/// \param Rel Comparison operator of the loop condition.
5647/// \param StartExpr Value of the loop counter at the first iteration.
5648/// \param StopExpr Expression the loop counter is compared against in the loop
5649/// condition. \param StepExpr Amount of increment after each iteration.
5650///
5651/// \return Closure (CapturedStmt) of the distance calculation.
5652static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5654 Expr *StartExpr, Expr *StopExpr,
5655 Expr *StepExpr) {
5656 ASTContext &Ctx = Actions.getASTContext();
5657 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5658
5659 // Captured regions currently don't support return values, we use an
5660 // out-parameter instead. All inputs are implicit captures.
5661 // TODO: Instead of capturing each DeclRefExpr occurring in
5662 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5663 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5664 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5665 {StringRef(), QualType()}};
5666 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5667
5668 Stmt *Body;
5669 {
5670 Sema::CompoundScopeRAII CompoundScope(Actions);
5672
5673 // Get the LValue expression for the result.
5674 ImplicitParamDecl *DistParam = CS->getParam(0);
5675 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5676 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5677
5678 SmallVector<Stmt *, 4> BodyStmts;
5679
5680 // Capture all referenced variable references.
5681 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5682 // CapturedStmt, we could compute them before and capture the result, to be
5683 // used jointly with the LoopVar function.
5684 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5685 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5686 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5687 auto BuildVarRef = [&](VarDecl *VD) {
5688 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5689 };
5690
5692 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5694 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5695 Expr *Dist;
5696 if (Rel == BO_NE) {
5697 // When using a != comparison, the increment can be +1 or -1. This can be
5698 // dynamic at runtime, so we need to check for the direction.
5699 Expr *IsNegStep = AssertSuccess(
5700 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5701
5702 // Positive increment.
5703 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5704 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5705 ForwardRange = AssertSuccess(
5706 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5707 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5708 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5709
5710 // Negative increment.
5711 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5712 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5713 BackwardRange = AssertSuccess(
5714 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5715 Expr *NegIncAmount = AssertSuccess(
5716 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5717 Expr *BackwardDist = AssertSuccess(
5718 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5719
5720 // Use the appropriate case.
5721 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5722 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5723 } else {
5724 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5725 "Expected one of these relational operators");
5726
5727 // We can derive the direction from any other comparison operator. It is
5728 // non well-formed OpenMP if Step increments/decrements in the other
5729 // directions. Whether at least the first iteration passes the loop
5730 // condition.
5731 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5732 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5733
5734 // Compute the range between first and last counter value.
5735 Expr *Range;
5736 if (Rel == BO_GE || Rel == BO_GT)
5737 Range = AssertSuccess(Actions.BuildBinOp(
5738 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5739 else
5740 Range = AssertSuccess(Actions.BuildBinOp(
5741 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5742
5743 // Ensure unsigned range space.
5744 Range =
5745 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5746
5747 if (Rel == BO_LE || Rel == BO_GE) {
5748 // Add one to the range if the relational operator is inclusive.
5749 Range =
5750 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5751 }
5752
5753 // Divide by the absolute step amount. If the range is not a multiple of
5754 // the step size, rounding-up the effective upper bound ensures that the
5755 // last iteration is included.
5756 // Note that the rounding-up may cause an overflow in a temporary that
5757 // could be avoided, but would have occurred in a C-style for-loop as
5758 // well.
5759 Expr *Divisor = BuildVarRef(NewStep);
5760 if (Rel == BO_GE || Rel == BO_GT)
5761 Divisor =
5762 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5763 Expr *DivisorMinusOne =
5764 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5765 Expr *RangeRoundUp = AssertSuccess(
5766 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5767 Dist = AssertSuccess(
5768 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5769
5770 // If there is not at least one iteration, the range contains garbage. Fix
5771 // to zero in this case.
5772 Dist = AssertSuccess(
5773 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5774 }
5775
5776 // Assign the result to the out-parameter.
5777 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5778 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5779 BodyStmts.push_back(ResultAssign);
5780
5781 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5782 }
5783
5784 return cast<CapturedStmt>(
5785 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5786}
5787
5788/// Create a closure that computes the loop variable from the logical iteration
5789/// number.
5790///
5791/// \param Actions The Sema object.
5792/// \param LoopVarTy Type for the loop variable used for result value.
5793/// \param LogicalTy Type for the logical iteration number.
5794/// \param StartExpr Value of the loop counter at the first iteration.
5795/// \param Step Amount of increment after each iteration.
5796/// \param Deref Whether the loop variable is a dereference of the loop
5797/// counter variable.
5798///
5799/// \return Closure (CapturedStmt) of the loop value calculation.
5800static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5801 QualType LogicalTy,
5802 DeclRefExpr *StartExpr, Expr *Step,
5803 bool Deref) {
5804 ASTContext &Ctx = Actions.getASTContext();
5805
5806 // Pass the result as an out-parameter. Passing as return value would require
5807 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5808 // invoke a copy constructor.
5809 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5810 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5811 {"Logical", LogicalTy},
5812 {StringRef(), QualType()}};
5813 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5814
5815 // Capture the initial iterator which represents the LoopVar value at the
5816 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5817 // it in every iteration, capture it by value before it is modified.
5818 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5819 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5821 (void)Invalid;
5822 assert(!Invalid && "Expecting capture-by-value to work.");
5823
5824 Expr *Body;
5825 {
5826 Sema::CompoundScopeRAII CompoundScope(Actions);
5827 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5828
5829 ImplicitParamDecl *TargetParam = CS->getParam(0);
5830 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5831 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5832 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5833 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5834 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5835
5836 // Capture the Start expression.
5837 CaptureVars Recap(Actions);
5838 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5839 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5840
5842 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5843 // TODO: Explicitly cast to the iterator's difference_type instead of
5844 // relying on implicit conversion.
5845 Expr *Advanced =
5846 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5847
5848 if (Deref) {
5849 // For range-based for-loops convert the loop counter value to a concrete
5850 // loop variable value by dereferencing the iterator.
5851 Advanced =
5852 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5853 }
5854
5855 // Assign the result to the output parameter.
5856 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5857 BO_Assign, TargetRef, Advanced));
5858 }
5859 return cast<CapturedStmt>(
5860 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5861}
5862
5864 ASTContext &Ctx = getASTContext();
5865
5866 // Extract the common elements of ForStmt and CXXForRangeStmt:
5867 // Loop variable, repeat condition, increment
5868 Expr *Cond, *Inc;
5869 VarDecl *LIVDecl, *LUVDecl;
5870 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5871 Stmt *Init = For->getInit();
5872 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5873 // For statement declares loop variable.
5874 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5875 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5876 // For statement reuses variable.
5877 assert(LCAssign->getOpcode() == BO_Assign &&
5878 "init part must be a loop variable assignment");
5879 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5880 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5881 } else
5882 llvm_unreachable("Cannot determine loop variable");
5883 LUVDecl = LIVDecl;
5884
5885 Cond = For->getCond();
5886 Inc = For->getInc();
5887 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5888 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5889 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5890 LUVDecl = RangeFor->getLoopVariable();
5891
5892 Cond = RangeFor->getCond();
5893 Inc = RangeFor->getInc();
5894 } else
5895 llvm_unreachable("unhandled kind of loop");
5896
5897 QualType CounterTy = LIVDecl->getType();
5898 QualType LVTy = LUVDecl->getType();
5899
5900 // Analyze the loop condition.
5901 Expr *LHS, *RHS;
5902 BinaryOperator::Opcode CondRel;
5903 Cond = Cond->IgnoreImplicit();
5904 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5905 LHS = CondBinExpr->getLHS();
5906 RHS = CondBinExpr->getRHS();
5907 CondRel = CondBinExpr->getOpcode();
5908 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5909 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5910 LHS = CondCXXOp->getArg(0);
5911 RHS = CondCXXOp->getArg(1);
5912 switch (CondCXXOp->getOperator()) {
5913 case OO_ExclaimEqual:
5914 CondRel = BO_NE;
5915 break;
5916 case OO_Less:
5917 CondRel = BO_LT;
5918 break;
5919 case OO_LessEqual:
5920 CondRel = BO_LE;
5921 break;
5922 case OO_Greater:
5923 CondRel = BO_GT;
5924 break;
5925 case OO_GreaterEqual:
5926 CondRel = BO_GE;
5927 break;
5928 default:
5929 llvm_unreachable("unexpected iterator operator");
5930 }
5931 } else
5932 llvm_unreachable("unexpected loop condition");
5933
5934 // Normalize such that the loop counter is on the LHS.
5935 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5936 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5937 std::swap(LHS, RHS);
5938 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5939 }
5940 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5941
5942 // Decide the bit width for the logical iteration counter. By default use the
5943 // unsigned ptrdiff_t integer size (for iterators and pointers).
5944 // TODO: For iterators, use iterator::difference_type,
5945 // std::iterator_traits<>::difference_type or decltype(it - end).
5946 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5947 if (CounterTy->isIntegerType()) {
5948 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5949 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5950 }
5951
5952 // Analyze the loop increment.
5953 Expr *Step;
5954 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5955 int Direction;
5956 switch (IncUn->getOpcode()) {
5957 case UO_PreInc:
5958 case UO_PostInc:
5959 Direction = 1;
5960 break;
5961 case UO_PreDec:
5962 case UO_PostDec:
5963 Direction = -1;
5964 break;
5965 default:
5966 llvm_unreachable("unhandled unary increment operator");
5967 }
5969 Ctx,
5970 llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction, /*isSigned=*/true),
5971 LogicalTy, {});
5972 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5973 if (IncBin->getOpcode() == BO_AddAssign) {
5974 Step = IncBin->getRHS();
5975 } else if (IncBin->getOpcode() == BO_SubAssign) {
5976 Step = AssertSuccess(
5977 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5978 } else
5979 llvm_unreachable("unhandled binary increment operator");
5980 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5981 switch (CondCXXOp->getOperator()) {
5982 case OO_PlusPlus:
5984 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5985 break;
5986 case OO_MinusMinus:
5988 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5989 break;
5990 case OO_PlusEqual:
5991 Step = CondCXXOp->getArg(1);
5992 break;
5993 case OO_MinusEqual:
5994 Step = AssertSuccess(
5995 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5996 break;
5997 default:
5998 llvm_unreachable("unhandled overloaded increment operator");
5999 }
6000 } else
6001 llvm_unreachable("unknown increment expression");
6002
6003 CapturedStmt *DistanceFunc =
6004 buildDistanceFunc(SemaRef, LogicalTy, CondRel, LHS, RHS, Step);
6005 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
6006 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
6007 DeclRefExpr *LVRef =
6008 SemaRef.BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue, {},
6009 nullptr, nullptr, {}, nullptr);
6010 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
6011 LoopVarFunc, LVRef);
6012}
6013
6015 // Handle a literal loop.
6016 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
6017 return ActOnOpenMPCanonicalLoop(AStmt);
6018
6019 // If not a literal loop, it must be the result of a loop transformation.
6021 assert(
6022 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
6023 "Loop transformation directive expected");
6024 return LoopTransform;
6025}
6026
6028 CXXScopeSpec &MapperIdScopeSpec,
6029 const DeclarationNameInfo &MapperId,
6030 QualType Type,
6031 Expr *UnresolvedMapper);
6032
6033/// Perform DFS through the structure/class data members trying to find
6034/// member(s) with user-defined 'default' mapper and generate implicit map
6035/// clauses for such members with the found 'default' mapper.
6036static void
6039 // Check for the default mapper for data members.
6040 if (S.getLangOpts().OpenMP < 50)
6041 return;
6042 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
6043 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
6044 if (!C)
6045 continue;
6046 SmallVector<Expr *, 4> SubExprs;
6047 auto *MI = C->mapperlist_begin();
6048 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
6049 ++I, ++MI) {
6050 // Expression is mapped using mapper - skip it.
6051 if (*MI)
6052 continue;
6053 Expr *E = *I;
6054 // Expression is dependent - skip it, build the mapper when it gets
6055 // instantiated.
6056 if (E->isTypeDependent() || E->isValueDependent() ||
6058 continue;
6059 // Array section - need to check for the mapping of the array section
6060 // element.
6061 QualType CanonType = E->getType().getCanonicalType();
6062 if (CanonType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
6063 const auto *OASE = cast<ArraySectionExpr>(E->IgnoreParenImpCasts());
6064 QualType BaseType =
6066 QualType ElemType;
6067 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6068 ElemType = ATy->getElementType();
6069 else
6070 ElemType = BaseType->getPointeeType();
6071 CanonType = ElemType;
6072 }
6073
6074 // DFS over data members in structures/classes.
6076 1, {CanonType, nullptr});
6077 llvm::DenseMap<const Type *, Expr *> Visited;
6079 1, {nullptr, 1});
6080 while (!Types.empty()) {
6081 QualType BaseType;
6082 FieldDecl *CurFD;
6083 std::tie(BaseType, CurFD) = Types.pop_back_val();
6084 while (ParentChain.back().second == 0)
6085 ParentChain.pop_back();
6086 --ParentChain.back().second;
6087 if (BaseType.isNull())
6088 continue;
6089 // Only structs/classes are allowed to have mappers.
6090 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6091 if (!RD)
6092 continue;
6093 auto It = Visited.find(BaseType.getTypePtr());
6094 if (It == Visited.end()) {
6095 // Try to find the associated user-defined mapper.
6096 CXXScopeSpec MapperIdScopeSpec;
6097 DeclarationNameInfo DefaultMapperId;
6099 &S.Context.Idents.get("default")));
6100 DefaultMapperId.setLoc(E->getExprLoc());
6102 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
6103 BaseType, /*UnresolvedMapper=*/nullptr);
6104 if (ER.isInvalid())
6105 continue;
6106 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
6107 }
6108 // Found default mapper.
6109 if (It->second) {
6110 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
6112 OE->setIsUnique(/*V=*/true);
6113 Expr *BaseExpr = OE;
6114 for (const auto &P : ParentChain) {
6115 if (P.first) {
6116 BaseExpr = S.BuildMemberExpr(
6117 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6119 DeclAccessPair::make(P.first, P.first->getAccess()),
6120 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6121 P.first->getType(), VK_LValue, OK_Ordinary);
6122 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
6123 }
6124 }
6125 if (CurFD)
6126 BaseExpr = S.BuildMemberExpr(
6127 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6129 DeclAccessPair::make(CurFD, CurFD->getAccess()),
6130 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6131 CurFD->getType(), VK_LValue, OK_Ordinary);
6132 SubExprs.push_back(BaseExpr);
6133 continue;
6134 }
6135 // Check for the "default" mapper for data members.
6136 bool FirstIter = true;
6137 for (FieldDecl *FD : RD->fields()) {
6138 if (!FD)
6139 continue;
6140 QualType FieldTy = FD->getType();
6141 if (FieldTy.isNull() ||
6142 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6143 continue;
6144 if (FirstIter) {
6145 FirstIter = false;
6146 ParentChain.emplace_back(CurFD, 1);
6147 } else {
6148 ++ParentChain.back().second;
6149 }
6150 Types.emplace_back(FieldTy, FD);
6151 }
6152 }
6153 }
6154 if (SubExprs.empty())
6155 continue;
6156 CXXScopeSpec MapperIdScopeSpec;
6157 DeclarationNameInfo MapperId;
6158 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
6159 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
6160 MapperIdScopeSpec, MapperId, C->getMapType(),
6161 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6162 SubExprs, OMPVarListLocTy()))
6163 Clauses.push_back(NewClause);
6164 }
6165}
6166
6167namespace {
6168/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
6169/// call in the associated loop-nest cannot be a 'parallel for'.
6170class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
6171 Sema &SemaRef;
6172
6173public:
6174 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
6175
6176 // Is there a nested OpenMP loop bind(parallel)
6177 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
6178 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
6179 if (const auto *C = D->getSingleClause<OMPBindClause>())
6180 if (C->getBindKind() == OMPC_BIND_parallel) {
6181 TeamsLoopCanBeParallelFor = false;
6182 // No need to continue visiting any more
6183 return;
6184 }
6185 }
6186 for (const Stmt *Child : D->children())
6187 if (Child)
6188 Visit(Child);
6189 }
6190
6191 void VisitCallExpr(const CallExpr *C) {
6192 // Function calls inhibit parallel loop translation of 'target teams loop'
6193 // unless the assume-no-nested-parallelism flag has been specified.
6194 // OpenMP API runtime library calls do not inhibit parallel loop
6195 // translation, regardless of the assume-no-nested-parallelism.
6196 bool IsOpenMPAPI = false;
6197 auto *FD = dyn_cast_or_null<FunctionDecl>(C->getCalleeDecl());
6198 if (FD) {
6199 std::string Name = FD->getNameInfo().getAsString();
6200 IsOpenMPAPI = Name.find("omp_") == 0;
6201 }
6202 TeamsLoopCanBeParallelFor =
6203 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
6204 if (!TeamsLoopCanBeParallelFor)
6205 return;
6206
6207 for (const Stmt *Child : C->children())
6208 if (Child)
6209 Visit(Child);
6210 }
6211
6212 void VisitCapturedStmt(const CapturedStmt *S) {
6213 if (!S)
6214 return;
6215 Visit(S->getCapturedDecl()->getBody());
6216 }
6217
6218 void VisitStmt(const Stmt *S) {
6219 if (!S)
6220 return;
6221 for (const Stmt *Child : S->children())
6222 if (Child)
6223 Visit(Child);
6224 }
6225 explicit TeamsLoopChecker(Sema &SemaRef)
6226 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
6227
6228private:
6229 bool TeamsLoopCanBeParallelFor;
6230};
6231} // namespace
6232
6233static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
6234 TeamsLoopChecker Checker(SemaRef);
6235 Checker.Visit(AStmt);
6236 return Checker.teamsLoopCanBeParallelFor();
6237}
6238
6240 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6241 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6242 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
6243 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
6244
6245 StmtResult Res = StmtError();
6247 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6248
6249 if (const OMPBindClause *BC =
6250 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6251 BindKind = BC->getBindKind();
6252
6253 if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
6254 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
6255
6256 // Setting the enclosing teams or parallel construct for the loop
6257 // directive without bind clause.
6258 // [5.0:129:25-28] If the bind clause is not present on the construct and
6259 // the loop construct is closely nested inside a teams or parallel
6260 // construct, the binding region is the corresponding teams or parallel
6261 // region. If none of those conditions hold, the binding region is not
6262 // defined.
6263 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6264 ArrayRef<OpenMPDirectiveKind> ParentLeafs =
6265 getLeafConstructsOrSelf(ParentDirective);
6266
6267 if (ParentDirective == OMPD_unknown) {
6268 Diag(DSAStack->getDefaultDSALocation(),
6269 diag::err_omp_bind_required_on_loop);
6270 } else if (ParentLeafs.back() == OMPD_parallel) {
6271 BindKind = OMPC_BIND_parallel;
6272 } else if (ParentLeafs.back() == OMPD_teams) {
6273 BindKind = OMPC_BIND_teams;
6274 }
6275
6276 assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind");
6277
6278 OMPClause *C =
6281 ClausesWithImplicit.push_back(C);
6282 }
6283
6284 // Diagnose "loop bind(teams)" with "reduction".
6285 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6286 for (OMPClause *C : Clauses) {
6287 if (C->getClauseKind() == OMPC_reduction)
6288 Diag(DSAStack->getDefaultDSALocation(),
6289 diag::err_omp_loop_reduction_clause);
6290 }
6291 }
6292
6293 // First check CancelRegion which is then used in checkNestingOfRegions.
6294 if (checkCancelRegion(SemaRef, Kind, CancelRegion, StartLoc) ||
6295 checkNestingOfRegions(SemaRef, DSAStack, Kind, DirName, CancelRegion,
6296 BindKind, StartLoc)) {
6297 return StmtError();
6298 }
6299
6300 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6303 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6304
6305 VarsWithInheritedDSAType VarsWithInheritedDSA;
6306 bool ErrorFound = false;
6307 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6308
6309 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6311 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6312
6313 // Check default data sharing attributes for referenced variables.
6314 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(AStmt));
6315 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6316 Stmt *S = AStmt;
6317 while (--ThisCaptureLevel >= 0)
6318 S = cast<CapturedStmt>(S)->getCapturedStmt();
6319 DSAChecker.Visit(S);
6321 !isOpenMPTaskingDirective(Kind)) {
6322 // Visit subcaptures to generate implicit clauses for captured vars.
6323 auto *CS = cast<CapturedStmt>(AStmt);
6325 getOpenMPCaptureRegions(CaptureRegions, Kind);
6326 // Ignore outer tasking regions for target directives.
6327 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6329 DSAChecker.visitSubCaptures(CS);
6330 }
6331 if (DSAChecker.isErrorFound())
6332 return StmtError();
6333 // Generate list of implicitly defined firstprivate variables.
6334 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6335 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6336
6338 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6339 // Get the original location of present modifier from Defaultmap clause.
6340 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6341 for (OMPClause *C : Clauses) {
6342 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6343 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6344 PresentModifierLocs[DMC->getDefaultmapKind()] =
6345 DMC->getDefaultmapModifierLoc();
6346 }
6347
6349 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6351 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[K]),
6352 ImpInfo.MapModifiers[K].size(), PresentModifierLocs[K]);
6353 }
6354 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6355 for (OMPClause *C : Clauses) {
6356 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6357 for (Expr *E : IRC->taskgroup_descriptors())
6358 if (E)
6359 ImpInfo.Firstprivates.insert(E);
6360 }
6361 // OpenMP 5.0, 2.10.1 task Construct
6362 // [detach clause]... The event-handle will be considered as if it was
6363 // specified on a firstprivate clause.
6364 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6365 ImpInfo.Firstprivates.insert(DC->getEventHandler());
6366 }
6367 if (!ImpInfo.Firstprivates.empty()) {
6369 ImpInfo.Firstprivates.getArrayRef(), SourceLocation(),
6371 ClausesWithImplicit.push_back(Implicit);
6372 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6373 ImpInfo.Firstprivates.size();
6374 } else {
6375 ErrorFound = true;
6376 }
6377 }
6378 if (!ImpInfo.Privates.empty()) {
6380 ImpInfo.Privates.getArrayRef(), SourceLocation(),
6382 ClausesWithImplicit.push_back(Implicit);
6383 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6384 ImpInfo.Privates.size();
6385 } else {
6386 ErrorFound = true;
6387 }
6388 }
6389 // OpenMP 5.0 [2.19.7]
6390 // If a list item appears in a reduction, lastprivate or linear
6391 // clause on a combined target construct then it is treated as
6392 // if it also appears in a map clause with a map-type of tofrom
6393 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6395 SmallVector<Expr *, 4> ImplicitExprs;
6396 for (OMPClause *C : Clauses) {
6397 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6398 for (Expr *E : RC->varlist())
6400 ImplicitExprs.emplace_back(E);
6401 }
6402 if (!ImplicitExprs.empty()) {
6403 ArrayRef<Expr *> Exprs = ImplicitExprs;
6404 CXXScopeSpec MapperIdScopeSpec;
6405 DeclarationNameInfo MapperId;
6408 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6409 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6410 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6411 ClausesWithImplicit.emplace_back(Implicit);
6412 }
6413 }
6414 for (unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6415 int ClauseKindCnt = -1;
6416 for (unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6417 ArrayRef<Expr *> ImplicitMap = ImpInfo.Mappings[I][J].getArrayRef();
6418 ++ClauseKindCnt;
6419 if (ImplicitMap.empty())
6420 continue;
6421 CXXScopeSpec MapperIdScopeSpec;
6422 DeclarationNameInfo MapperId;
6423 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6425 nullptr, ImpInfo.MapModifiers[I], ImplicitMapModifiersLoc[I],
6426 MapperIdScopeSpec, MapperId, K, /*IsMapTypeImplicit=*/true,
6427 SourceLocation(), SourceLocation(), ImplicitMap,
6428 OMPVarListLocTy())) {
6429 ClausesWithImplicit.emplace_back(Implicit);
6430 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6431 ImplicitMap.size();
6432 } else {
6433 ErrorFound = true;
6434 }
6435 }
6436 }
6437 // Build expressions for implicit maps of data members with 'default'
6438 // mappers.
6439 if (getLangOpts().OpenMP >= 50)
6441 ClausesWithImplicit);
6442 }
6443
6444 switch (Kind) {
6445 case OMPD_parallel:
6446 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6447 EndLoc);
6448 break;
6449 case OMPD_simd:
6450 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6451 VarsWithInheritedDSA);
6452 break;
6453 case OMPD_tile:
6454 Res =
6455 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6456 break;
6457 case OMPD_stripe:
6458 Res = ActOnOpenMPStripeDirective(ClausesWithImplicit, AStmt, StartLoc,
6459 EndLoc);
6460 break;
6461 case OMPD_unroll:
6462 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6463 EndLoc);
6464 break;
6465 case OMPD_reverse:
6466 assert(ClausesWithImplicit.empty() &&
6467 "reverse directive does not support any clauses");
6468 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6469 break;
6470 case OMPD_split:
6471 Res =
6472 ActOnOpenMPSplitDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6473 break;
6474 case OMPD_interchange:
6475 Res = ActOnOpenMPInterchangeDirective(ClausesWithImplicit, AStmt, StartLoc,
6476 EndLoc);
6477 break;
6478 case OMPD_fuse:
6479 Res =
6480 ActOnOpenMPFuseDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6481 break;
6482 case OMPD_for:
6483 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6484 VarsWithInheritedDSA);
6485 break;
6486 case OMPD_for_simd:
6487 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6488 EndLoc, VarsWithInheritedDSA);
6489 break;
6490 case OMPD_sections:
6491 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6492 EndLoc);
6493 break;
6494 case OMPD_section:
6495 assert(ClausesWithImplicit.empty() &&
6496 "No clauses are allowed for 'omp section' directive");
6497 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6498 break;
6499 case OMPD_single:
6500 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6501 EndLoc);
6502 break;
6503 case OMPD_master:
6504 assert(ClausesWithImplicit.empty() &&
6505 "No clauses are allowed for 'omp master' directive");
6506 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6507 break;
6508 case OMPD_masked:
6509 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6510 EndLoc);
6511 break;
6512 case OMPD_critical:
6513 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6514 StartLoc, EndLoc);
6515 break;
6516 case OMPD_parallel_for:
6517 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6518 EndLoc, VarsWithInheritedDSA);
6519 break;
6520 case OMPD_parallel_for_simd:
6522 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6523 break;
6524 case OMPD_scope:
6525 Res =
6526 ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6527 break;
6528 case OMPD_parallel_master:
6529 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6530 StartLoc, EndLoc);
6531 break;
6532 case OMPD_parallel_masked:
6533 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6534 StartLoc, EndLoc);
6535 break;
6536 case OMPD_parallel_sections:
6537 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6538 StartLoc, EndLoc);
6539 break;
6540 case OMPD_task:
6541 Res =
6542 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6543 break;
6544 case OMPD_taskyield:
6545 assert(ClausesWithImplicit.empty() &&
6546 "No clauses are allowed for 'omp taskyield' directive");
6547 assert(AStmt == nullptr &&
6548 "No associated statement allowed for 'omp taskyield' directive");
6549 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6550 break;
6551 case OMPD_error:
6552 assert(AStmt == nullptr &&
6553 "No associated statement allowed for 'omp error' directive");
6554 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6555 break;
6556 case OMPD_barrier:
6557 assert(ClausesWithImplicit.empty() &&
6558 "No clauses are allowed for 'omp barrier' directive");
6559 assert(AStmt == nullptr &&
6560 "No associated statement allowed for 'omp barrier' directive");
6561 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6562 break;
6563 case OMPD_taskwait:
6564 assert(AStmt == nullptr &&
6565 "No associated statement allowed for 'omp taskwait' directive");
6566 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6567 break;
6568 case OMPD_taskgroup:
6569 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6570 EndLoc);
6571 break;
6572 case OMPD_flush:
6573 assert(AStmt == nullptr &&
6574 "No associated statement allowed for 'omp flush' directive");
6575 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6576 break;
6577 case OMPD_depobj:
6578 assert(AStmt == nullptr &&
6579 "No associated statement allowed for 'omp depobj' directive");
6580 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6581 break;
6582 case OMPD_scan:
6583 assert(AStmt == nullptr &&
6584 "No associated statement allowed for 'omp scan' directive");
6585 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6586 break;
6587 case OMPD_ordered:
6588 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6589 EndLoc);
6590 break;
6591 case OMPD_atomic:
6592 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6593 EndLoc);
6594 break;
6595 case OMPD_teams:
6596 Res =
6597 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6598 break;
6599 case OMPD_target:
6600 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6601 EndLoc);
6602 break;
6603 case OMPD_target_parallel:
6604 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6605 StartLoc, EndLoc);
6606 break;
6607 case OMPD_target_parallel_for:
6609 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6610 break;
6611 case OMPD_cancellation_point:
6612 assert(ClausesWithImplicit.empty() &&
6613 "No clauses are allowed for 'omp cancellation point' directive");
6614 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6615 "cancellation point' directive");
6616 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6617 break;
6618 case OMPD_cancel:
6619 assert(AStmt == nullptr &&
6620 "No associated statement allowed for 'omp cancel' directive");
6621 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6622 CancelRegion);
6623 break;
6624 case OMPD_target_data:
6625 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6626 EndLoc);
6627 break;
6628 case OMPD_target_enter_data:
6629 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6630 EndLoc, AStmt);
6631 break;
6632 case OMPD_target_exit_data:
6633 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6634 EndLoc, AStmt);
6635 break;
6636 case OMPD_taskloop:
6637 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6638 EndLoc, VarsWithInheritedDSA);
6639 break;
6640 case OMPD_taskloop_simd:
6641 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6642 EndLoc, VarsWithInheritedDSA);
6643 break;
6644 case OMPD_master_taskloop:
6646 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6647 break;
6648 case OMPD_masked_taskloop:
6650 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6651 break;
6652 case OMPD_master_taskloop_simd:
6654 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6655 break;
6656 case OMPD_masked_taskloop_simd:
6658 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6659 break;
6660 case OMPD_parallel_master_taskloop:
6662 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6663 break;
6664 case OMPD_parallel_masked_taskloop:
6666 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6667 break;
6668 case OMPD_parallel_master_taskloop_simd:
6670 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6671 break;
6672 case OMPD_parallel_masked_taskloop_simd:
6674 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6675 break;
6676 case OMPD_distribute:
6677 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6678 EndLoc, VarsWithInheritedDSA);
6679 break;
6680 case OMPD_target_update:
6681 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6682 EndLoc, AStmt);
6683 break;
6684 case OMPD_distribute_parallel_for:
6686 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6687 break;
6688 case OMPD_distribute_parallel_for_simd:
6690 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6691 break;
6692 case OMPD_distribute_simd:
6694 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6695 break;
6696 case OMPD_target_parallel_for_simd:
6698 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6699 break;
6700 case OMPD_target_simd:
6701 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6702 EndLoc, VarsWithInheritedDSA);
6703 break;
6704 case OMPD_teams_distribute:
6706 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6707 break;
6708 case OMPD_teams_distribute_simd:
6710 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6711 break;
6712 case OMPD_teams_distribute_parallel_for_simd:
6714 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6715 break;
6716 case OMPD_teams_distribute_parallel_for:
6718 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6719 break;
6720 case OMPD_target_teams:
6721 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6722 EndLoc);
6723 break;
6724 case OMPD_target_teams_distribute:
6726 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6727 break;
6728 case OMPD_target_teams_distribute_parallel_for:
6730 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6731 break;
6732 case OMPD_target_teams_distribute_parallel_for_simd:
6734 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6735 break;
6736 case OMPD_target_teams_distribute_simd:
6738 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6739 break;
6740 case OMPD_interop:
6741 assert(AStmt == nullptr &&
6742 "No associated statement allowed for 'omp interop' directive");
6743 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6744 break;
6745 case OMPD_dispatch:
6746 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6747 EndLoc);
6748 break;
6749 case OMPD_loop:
6750 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6751 EndLoc, VarsWithInheritedDSA);
6752 break;
6753 case OMPD_teams_loop:
6755 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6756 break;
6757 case OMPD_target_teams_loop:
6759 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6760 break;
6761 case OMPD_parallel_loop:
6763 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6764 break;
6765 case OMPD_target_parallel_loop:
6767 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6768 break;
6769 case OMPD_declare_target:
6770 case OMPD_end_declare_target:
6771 case OMPD_threadprivate:
6772 case OMPD_allocate:
6773 case OMPD_declare_reduction:
6774 case OMPD_declare_mapper:
6775 case OMPD_declare_simd:
6776 case OMPD_requires:
6777 case OMPD_declare_variant:
6778 case OMPD_begin_declare_variant:
6779 case OMPD_end_declare_variant:
6780 llvm_unreachable("OpenMP Directive is not allowed");
6781 case OMPD_taskgraph:
6782 Diag(StartLoc, diag::err_omp_unexpected_directive)
6783 << 1 << getOpenMPDirectiveName(OMPD_taskgraph);
6784 return StmtError();
6785 case OMPD_unknown:
6786 default:
6787 llvm_unreachable("Unknown OpenMP directive");
6788 }
6789
6790 ErrorFound = Res.isInvalid() || ErrorFound;
6791
6792 // Check variables in the clauses if default(none) or
6793 // default(firstprivate) was specified.
6794 if (DSAStack->getDefaultDSA() == DSA_none ||
6795 DSAStack->getDefaultDSA() == DSA_private ||
6796 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6797 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6798 for (OMPClause *C : Clauses) {
6799 switch (C->getClauseKind()) {
6800 case OMPC_num_threads:
6801 case OMPC_dist_schedule:
6802 // Do not analyze if no parent teams directive.
6803 if (isOpenMPTeamsDirective(Kind))
6804 break;
6805 continue;
6806 case OMPC_if:
6807 if (isOpenMPTeamsDirective(Kind) &&
6808 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6809 break;
6810 if (isOpenMPParallelDirective(Kind) &&
6812 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6813 break;
6814 continue;
6815 case OMPC_schedule:
6816 case OMPC_detach:
6817 break;
6818 case OMPC_grainsize:
6819 case OMPC_num_tasks:
6820 case OMPC_final:
6821 case OMPC_priority:
6822 case OMPC_novariants:
6823 case OMPC_nocontext:
6824 // Do not analyze if no parent parallel directive.
6825 if (isOpenMPParallelDirective(Kind))
6826 break;
6827 continue;
6828 case OMPC_ordered:
6829 case OMPC_device:
6830 case OMPC_num_teams:
6831 case OMPC_thread_limit:
6832 case OMPC_hint:
6833 case OMPC_collapse:
6834 case OMPC_safelen:
6835 case OMPC_simdlen:
6836 case OMPC_sizes:
6837 case OMPC_default:
6838 case OMPC_proc_bind:
6839 case OMPC_private:
6840 case OMPC_firstprivate:
6841 case OMPC_lastprivate:
6842 case OMPC_shared:
6843 case OMPC_reduction:
6844 case OMPC_task_reduction:
6845 case OMPC_in_reduction:
6846 case OMPC_linear:
6847 case OMPC_aligned:
6848 case OMPC_copyin:
6849 case OMPC_copyprivate:
6850 case OMPC_nowait:
6851 case OMPC_untied:
6852 case OMPC_mergeable:
6853 case OMPC_allocate:
6854 case OMPC_read:
6855 case OMPC_write:
6856 case OMPC_update:
6857 case OMPC_capture:
6858 case OMPC_compare:
6859 case OMPC_seq_cst:
6860 case OMPC_acq_rel:
6861 case OMPC_acquire:
6862 case OMPC_release:
6863 case OMPC_relaxed:
6864 case OMPC_depend:
6865 case OMPC_threads:
6866 case OMPC_simd:
6867 case OMPC_map:
6868 case OMPC_nogroup:
6869 case OMPC_defaultmap:
6870 case OMPC_to:
6871 case OMPC_from:
6872 case OMPC_use_device_ptr:
6873 case OMPC_use_device_addr:
6874 case OMPC_is_device_ptr:
6875 case OMPC_has_device_addr:
6876 case OMPC_nontemporal:
6877 case OMPC_order:
6878 case OMPC_destroy:
6879 case OMPC_inclusive:
6880 case OMPC_exclusive:
6881 case OMPC_uses_allocators:
6882 case OMPC_affinity:
6883 case OMPC_bind:
6884 case OMPC_filter:
6885 case OMPC_severity:
6886 case OMPC_message:
6887 continue;
6888 case OMPC_allocator:
6889 case OMPC_flush:
6890 case OMPC_depobj:
6891 case OMPC_threadprivate:
6892 case OMPC_groupprivate:
6893 case OMPC_uniform:
6894 case OMPC_unknown:
6895 case OMPC_unified_address:
6896 case OMPC_unified_shared_memory:
6897 case OMPC_reverse_offload:
6898 case OMPC_dynamic_allocators:
6899 case OMPC_atomic_default_mem_order:
6900 case OMPC_self_maps:
6901 case OMPC_device_type:
6902 case OMPC_match:
6903 case OMPC_when:
6904 case OMPC_at:
6905 default:
6906 llvm_unreachable("Unexpected clause");
6907 }
6908 for (Stmt *CC : C->children()) {
6909 if (CC)
6910 DSAChecker.Visit(CC);
6911 }
6912 }
6913 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6914 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6915 }
6916 for (const auto &P : VarsWithInheritedDSA) {
6917 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6918 continue;
6919 ErrorFound = true;
6920 if (DSAStack->getDefaultDSA() == DSA_none ||
6921 DSAStack->getDefaultDSA() == DSA_private ||
6922 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6923 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6924 << P.first << P.second->getSourceRange();
6925 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6926 } else if (getLangOpts().OpenMP >= 50) {
6927 Diag(P.second->getExprLoc(),
6928 diag::err_omp_defaultmap_no_attr_for_variable)
6929 << P.first << P.second->getSourceRange();
6930 Diag(DSAStack->getDefaultDSALocation(),
6931 diag::note_omp_defaultmap_attr_none);
6932 }
6933 }
6934
6935 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6936 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(Kind)) {
6937 if (isAllowedClauseForDirective(D, OMPC_if, getLangOpts().OpenMP))
6938 AllowedNameModifiers.push_back(D);
6939 }
6940 if (!AllowedNameModifiers.empty())
6941 ErrorFound = checkIfClauses(SemaRef, Kind, Clauses, AllowedNameModifiers) ||
6942 ErrorFound;
6943
6944 if (ErrorFound)
6945 return StmtError();
6946
6947 if (!SemaRef.CurContext->isDependentContext() &&
6949 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6950 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6951 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6952 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6953 // Register target to DSA Stack.
6954 DSAStack->addTargetDirLocation(StartLoc);
6955 }
6956
6957 return Res;
6958}
6959
6961 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6962 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6963 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6964 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6965 assert(Aligneds.size() == Alignments.size());
6966 assert(Linears.size() == LinModifiers.size());
6967 assert(Linears.size() == Steps.size());
6968 if (!DG || DG.get().isNull())
6969 return DeclGroupPtrTy();
6970
6971 const int SimdId = 0;
6972 if (!DG.get().isSingleDecl()) {
6973 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6974 << SimdId;
6975 return DG;
6976 }
6977 Decl *ADecl = DG.get().getSingleDecl();
6978 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6979 ADecl = FTD->getTemplatedDecl();
6980
6981 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6982 if (!FD) {
6983 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6984 return DeclGroupPtrTy();
6985 }
6986
6987 // OpenMP [2.8.2, declare simd construct, Description]
6988 // The parameter of the simdlen clause must be a constant positive integer
6989 // expression.
6990 ExprResult SL;
6991 if (Simdlen)
6992 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6993 // OpenMP [2.8.2, declare simd construct, Description]
6994 // The special this pointer can be used as if was one of the arguments to the
6995 // function in any of the linear, aligned, or uniform clauses.
6996 // The uniform clause declares one or more arguments to have an invariant
6997 // value for all concurrent invocations of the function in the execution of a
6998 // single SIMD loop.
6999 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
7000 const Expr *UniformedLinearThis = nullptr;
7001 for (const Expr *E : Uniforms) {
7002 E = E->IgnoreParenImpCasts();
7003 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7004 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
7005 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7006 FD->getParamDecl(PVD->getFunctionScopeIndex())
7007 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
7008 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
7009 continue;
7010 }
7011 if (isa<CXXThisExpr>(E)) {
7012 UniformedLinearThis = E;
7013 continue;
7014 }
7015 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7016 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7017 }
7018 // OpenMP [2.8.2, declare simd construct, Description]
7019 // The aligned clause declares that the object to which each list item points
7020 // is aligned to the number of bytes expressed in the optional parameter of
7021 // the aligned clause.
7022 // The special this pointer can be used as if was one of the arguments to the
7023 // function in any of the linear, aligned, or uniform clauses.
7024 // The type of list items appearing in the aligned clause must be array,
7025 // pointer, reference to array, or reference to pointer.
7026 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
7027 const Expr *AlignedThis = nullptr;
7028 for (const Expr *E : Aligneds) {
7029 E = E->IgnoreParenImpCasts();
7030 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7031 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7032 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7033 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7034 FD->getParamDecl(PVD->getFunctionScopeIndex())
7035 ->getCanonicalDecl() == CanonPVD) {
7036 // OpenMP [2.8.1, simd construct, Restrictions]
7037 // A list-item cannot appear in more than one aligned clause.
7038 auto [It, Inserted] = AlignedArgs.try_emplace(CanonPVD, E);
7039 if (!Inserted) {
7040 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
7041 << 1 << getOpenMPClauseNameForDiag(OMPC_aligned)
7042 << E->getSourceRange();
7043 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7044 << getOpenMPClauseNameForDiag(OMPC_aligned);
7045 continue;
7046 }
7047 QualType QTy = PVD->getType()
7048 .getNonReferenceType()
7049 .getUnqualifiedType()
7050 .getCanonicalType();
7051 const Type *Ty = QTy.getTypePtrOrNull();
7052 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
7053 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
7054 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
7055 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
7056 }
7057 continue;
7058 }
7059 }
7060 if (isa<CXXThisExpr>(E)) {
7061 if (AlignedThis) {
7062 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
7063 << 2 << getOpenMPClauseNameForDiag(OMPC_aligned)
7064 << E->getSourceRange();
7065 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
7066 << getOpenMPClauseNameForDiag(OMPC_aligned);
7067 }
7068 AlignedThis = E;
7069 continue;
7070 }
7071 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7072 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7073 }
7074 // The optional parameter of the aligned clause, alignment, must be a constant
7075 // positive integer expression. If no optional parameter is specified,
7076 // implementation-defined default alignments for SIMD instructions on the
7077 // target platforms are assumed.
7079 for (Expr *E : Alignments) {
7080 ExprResult Align;
7081 if (E)
7082 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
7083 NewAligns.push_back(Align.get());
7084 }
7085 // OpenMP [2.8.2, declare simd construct, Description]
7086 // The linear clause declares one or more list items to be private to a SIMD
7087 // lane and to have a linear relationship with respect to the iteration space
7088 // of a loop.
7089 // The special this pointer can be used as if was one of the arguments to the
7090 // function in any of the linear, aligned, or uniform clauses.
7091 // When a linear-step expression is specified in a linear clause it must be
7092 // either a constant integer expression or an integer-typed parameter that is
7093 // specified in a uniform clause on the directive.
7094 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7095 const bool IsUniformedThis = UniformedLinearThis != nullptr;
7096 auto MI = LinModifiers.begin();
7097 for (const Expr *E : Linears) {
7098 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
7099 ++MI;
7100 E = E->IgnoreParenImpCasts();
7101 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7102 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7103 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7104 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7105 FD->getParamDecl(PVD->getFunctionScopeIndex())
7106 ->getCanonicalDecl() == CanonPVD) {
7107 // OpenMP [2.15.3.7, linear Clause, Restrictions]
7108 // A list-item cannot appear in more than one linear clause.
7109 if (auto It = LinearArgs.find(CanonPVD); It != LinearArgs.end()) {
7110 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7111 << getOpenMPClauseNameForDiag(OMPC_linear)
7112 << getOpenMPClauseNameForDiag(OMPC_linear)
7113 << E->getSourceRange();
7114 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7115 << getOpenMPClauseNameForDiag(OMPC_linear);
7116 continue;
7117 }
7118 // Each argument can appear in at most one uniform or linear clause.
7119 if (auto It = UniformedArgs.find(CanonPVD);
7120 It != UniformedArgs.end()) {
7121 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7122 << getOpenMPClauseNameForDiag(OMPC_linear)
7123 << getOpenMPClauseNameForDiag(OMPC_uniform)
7124 << E->getSourceRange();
7125 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7126 << getOpenMPClauseNameForDiag(OMPC_uniform);
7127 continue;
7128 }
7129 LinearArgs[CanonPVD] = E;
7130 if (E->isValueDependent() || E->isTypeDependent() ||
7133 continue;
7134 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
7135 PVD->getOriginalType(),
7136 /*IsDeclareSimd=*/true);
7137 continue;
7138 }
7139 }
7140 if (isa<CXXThisExpr>(E)) {
7141 if (UniformedLinearThis) {
7142 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7143 << getOpenMPClauseNameForDiag(OMPC_linear)
7144 << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
7145 : OMPC_linear)
7146 << E->getSourceRange();
7147 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
7148 << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
7149 : OMPC_linear);
7150 continue;
7151 }
7152 UniformedLinearThis = E;
7153 if (E->isValueDependent() || E->isTypeDependent() ||
7155 continue;
7156 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
7157 E->getType(), /*IsDeclareSimd=*/true);
7158 continue;
7159 }
7160 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7161 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7162 }
7163 Expr *Step = nullptr;
7164 Expr *NewStep = nullptr;
7165 SmallVector<Expr *, 4> NewSteps;
7166 for (Expr *E : Steps) {
7167 // Skip the same step expression, it was checked already.
7168 if (Step == E || !E) {
7169 NewSteps.push_back(E ? NewStep : nullptr);
7170 continue;
7171 }
7172 Step = E;
7173 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
7174 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7175 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7176 if (UniformedArgs.count(CanonPVD) == 0) {
7177 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
7178 << Step->getSourceRange();
7179 } else if (E->isValueDependent() || E->isTypeDependent() ||
7182 CanonPVD->getType()->hasIntegerRepresentation()) {
7183 NewSteps.push_back(Step);
7184 } else {
7185 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
7186 << Step->getSourceRange();
7187 }
7188 continue;
7189 }
7190 NewStep = Step;
7191 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
7192 !Step->isInstantiationDependent() &&
7194 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
7195 .get();
7196 if (NewStep)
7197 NewStep = SemaRef
7198 .VerifyIntegerConstantExpression(
7199 NewStep, /*FIXME*/ AllowFoldKind::Allow)
7200 .get();
7201 }
7202 NewSteps.push_back(NewStep);
7203 }
7204 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7205 getASTContext(), BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
7206 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
7207 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
7208 const_cast<Expr **>(Linears.data()), Linears.size(),
7209 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
7210 NewSteps.data(), NewSteps.size(), SR);
7211 ADecl->addAttr(NewAttr);
7212 return DG;
7213}
7214
7216 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
7217 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
7218 SourceLocation EndLoc) {
7219 assert(isOpenMPInformationalDirective(Kind) &&
7220 "Unexpected directive category");
7221
7222 StmtResult Res = StmtError();
7223
7224 switch (Kind) {
7225 case OMPD_assume:
7226 Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc);
7227 break;
7228 default:
7229 llvm_unreachable("Unknown OpenMP directive");
7230 }
7231
7232 return Res;
7233}
7234
7235static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7236 QualType NewType) {
7237 assert(NewType->isFunctionProtoType() &&
7238 "Expected function type with prototype.");
7239 assert(FD->getType()->isFunctionNoProtoType() &&
7240 "Expected function with type with no prototype.");
7241 assert(FDWithProto->getType()->isFunctionProtoType() &&
7242 "Expected function with prototype.");
7243 // Synthesize parameters with the same types.
7244 FD->setType(NewType);
7246 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7247 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
7248 SourceLocation(), nullptr, P->getType(),
7249 /*TInfo=*/nullptr, SC_None, nullptr);
7250 Param->setScopeInfo(0, Params.size());
7251 Param->setImplicit();
7252 Params.push_back(Param);
7253 }
7254
7255 FD->setParams(Params);
7256}
7257
7259 if (D->isInvalidDecl())
7260 return;
7261 FunctionDecl *FD = nullptr;
7262 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7263 FD = UTemplDecl->getTemplatedDecl();
7264 else
7265 FD = cast<FunctionDecl>(D);
7266 assert(FD && "Expected a function declaration!");
7267
7268 // If we are instantiating templates we do *not* apply scoped assumptions but
7269 // only global ones. We apply scoped assumption to the template definition
7270 // though.
7271 if (!SemaRef.inTemplateInstantiation()) {
7272 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7273 FD->addAttr(AA);
7274 }
7275 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7276 FD->addAttr(AA);
7277}
7278
7279SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7280 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7281
7283 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7285 if (!D.getIdentifier())
7286 return;
7287
7288 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7289
7290 // Template specialization is an extension, check if we do it.
7291 bool IsTemplated = !TemplateParamLists.empty();
7292 if (IsTemplated &&
7293 !DVScope.TI->isExtensionActive(
7294 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7295 return;
7296
7297 const IdentifierInfo *BaseII = D.getIdentifier();
7300 SemaRef.LookupParsedName(Lookup, S, &D.getCXXScopeSpec(),
7301 /*ObjectType=*/QualType());
7302
7303 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
7304 QualType FType = TInfo->getType();
7305
7306 bool IsConstexpr =
7308 bool IsConsteval =
7310
7311 for (auto *Candidate : Lookup) {
7312 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7313 FunctionDecl *UDecl = nullptr;
7314 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7315 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7316 // FIXME: Should this compare the template parameter lists on all levels?
7317 if (SemaRef.Context.isSameTemplateParameterList(
7318 FTD->getTemplateParameters(), TemplateParamLists.back()))
7319 UDecl = FTD->getTemplatedDecl();
7320 } else if (!IsTemplated)
7321 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7322 if (!UDecl)
7323 continue;
7324
7325 // Don't specialize constexpr/consteval functions with
7326 // non-constexpr/consteval functions.
7327 if (UDecl->isConstexpr() && !IsConstexpr)
7328 continue;
7329 if (UDecl->isConsteval() && !IsConsteval)
7330 continue;
7331
7332 QualType UDeclTy = UDecl->getType();
7333 if (!UDeclTy->isDependentType()) {
7335 FType, UDeclTy, /*OfBlockPointer=*/false,
7336 /*Unqualified=*/false, /*AllowCXX=*/true);
7337 if (NewType.isNull())
7338 continue;
7339 }
7340
7341 // Found a base!
7342 Bases.push_back(UDecl);
7343 }
7344
7345 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7346 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7347 // If no base was found we create a declaration that we use as base.
7348 if (Bases.empty() && UseImplicitBase) {
7350 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7351 BaseD->setImplicit(true);
7352 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7353 Bases.push_back(BaseTemplD->getTemplatedDecl());
7354 else
7355 Bases.push_back(cast<FunctionDecl>(BaseD));
7356 }
7357
7358 std::string MangledName;
7359 MangledName += D.getIdentifier()->getName();
7360 MangledName += getOpenMPVariantManglingSeparatorStr();
7361 MangledName += DVScope.NameSuffix;
7362 IdentifierInfo &VariantII = getASTContext().Idents.get(MangledName);
7363
7364 VariantII.setMangledOpenMPVariantName(true);
7365 D.SetIdentifier(&VariantII, D.getBeginLoc());
7366}
7367
7370 // Do not mark function as is used to prevent its emission if this is the
7371 // only place where it is used.
7374
7375 FunctionDecl *FD = nullptr;
7376 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7377 FD = UTemplDecl->getTemplatedDecl();
7378 else
7379 FD = cast<FunctionDecl>(D);
7380 auto *VariantFuncRef = DeclRefExpr::Create(
7382 /*RefersToEnclosingVariableOrCapture=*/false,
7383 /*NameLoc=*/FD->getLocation(), FD->getType(), ExprValueKind::VK_PRValue);
7384
7385 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7386 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7387 getASTContext(), VariantFuncRef, DVScope.TI,
7388 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7389 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7390 /*NeedDeviceAddrArgs=*/nullptr, /*NeedDeviceAddrArgsSize=*/0,
7391 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7392 for (FunctionDecl *BaseFD : Bases)
7393 BaseFD->addAttr(OMPDeclareVariantA);
7394}
7395
7397 SourceLocation LParenLoc,
7398 MultiExprArg ArgExprs,
7399 SourceLocation RParenLoc,
7400 Expr *ExecConfig) {
7401 // The common case is a regular call we do not want to specialize at all. Try
7402 // to make that case fast by bailing early.
7403 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7404 if (!CE)
7405 return Call;
7406
7407 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7408
7409 // Mark indirect calls inside target regions, to allow for insertion of
7410 // __llvm_omp_indirect_call_lookup calls during codegen.
7411 if (!CalleeFnDecl) {
7413 Expr *E = CE->getCallee()->IgnoreParenImpCasts();
7414 DeclRefExpr *DRE = nullptr;
7415 while (E) {
7416 if ((DRE = dyn_cast<DeclRefExpr>(E)))
7417 break;
7418 if (auto *ME = dyn_cast<MemberExpr>(E))
7419 E = ME->getBase()->IgnoreParenImpCasts();
7420 else if (auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
7421 E = ASE->getBase()->IgnoreParenImpCasts();
7422 else
7423 break;
7424 }
7425 VarDecl *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) : nullptr;
7426 if (VD && !VD->hasAttr<OMPTargetIndirectCallAttr>()) {
7427 VD->addAttr(OMPTargetIndirectCallAttr::CreateImplicit(getASTContext()));
7428 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
7429 ML->DeclarationMarkedOpenMPIndirectCall(VD);
7430 }
7431 }
7432
7433 return Call;
7434 }
7435
7436 if (getLangOpts().OpenMP >= 50 && getLangOpts().OpenMP <= 60 &&
7437 CalleeFnDecl->getIdentifier() &&
7438 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7439 // checking for any calls inside an Order region
7441 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7442 }
7443
7444 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7445 return Call;
7446
7447 ASTContext &Context = getASTContext();
7448 std::function<void(StringRef)> DiagUnknownTrait = [this,
7449 CE](StringRef ISATrait) {
7450 // TODO Track the selector locations in a way that is accessible here to
7451 // improve the diagnostic location.
7452 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7453 << ISATrait;
7454 };
7455 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7456 SemaRef.getCurFunctionDecl(),
7457 DSAStack->getConstructTraits(), getOpenMPDeviceNum());
7458
7459 QualType CalleeFnType = CalleeFnDecl->getType();
7460
7463 while (CalleeFnDecl) {
7464 for (OMPDeclareVariantAttr *A :
7465 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7466 Expr *VariantRef = A->getVariantFuncRef();
7467
7468 VariantMatchInfo VMI;
7469 OMPTraitInfo &TI = A->getTraitInfo();
7470 TI.getAsVariantMatchInfo(Context, VMI);
7471 if (!isVariantApplicableInContext(VMI, OMPCtx,
7472 /*DeviceSetOnly=*/false))
7473 continue;
7474
7475 VMIs.push_back(VMI);
7476 Exprs.push_back(VariantRef);
7477 }
7478
7479 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7480 }
7481
7482 ExprResult NewCall;
7483 do {
7484 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7485 if (BestIdx < 0)
7486 return Call;
7487 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7488 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7489
7490 {
7491 // Try to build a (member) call expression for the current best applicable
7492 // variant expression. We allow this to fail in which case we continue
7493 // with the next best variant expression. The fail case is part of the
7494 // implementation defined behavior in the OpenMP standard when it talks
7495 // about what differences in the function prototypes: "Any differences
7496 // that the specific OpenMP context requires in the prototype of the
7497 // variant from the base function prototype are implementation defined."
7498 // This wording is there to allow the specialized variant to have a
7499 // different type than the base function. This is intended and OK but if
7500 // we cannot create a call the difference is not in the "implementation
7501 // defined range" we allow.
7503
7504 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7505 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7506 BestExpr = MemberExpr::CreateImplicit(
7507 Context, MemberCall->getImplicitObjectArgument(),
7508 /*IsArrow=*/false, SpecializedMethod, Context.BoundMemberTy,
7509 MemberCall->getValueKind(), MemberCall->getObjectKind());
7510 }
7511 NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs,
7512 RParenLoc, ExecConfig);
7513 if (NewCall.isUsable()) {
7514 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7515 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7517 CalleeFnType, NewCalleeFnDecl->getType(),
7518 /*OfBlockPointer=*/false,
7519 /*Unqualified=*/false, /*AllowCXX=*/true);
7520 if (!NewType.isNull())
7521 break;
7522 // Don't use the call if the function type was not compatible.
7523 NewCall = nullptr;
7524 }
7525 }
7526 }
7527
7528 VMIs.erase(VMIs.begin() + BestIdx);
7529 Exprs.erase(Exprs.begin() + BestIdx);
7530 } while (!VMIs.empty());
7531
7532 if (!NewCall.isUsable())
7533 return Call;
7534 return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
7535}
7536
7537std::optional<std::pair<FunctionDecl *, Expr *>>
7539 Expr *VariantRef,
7540 OMPTraitInfo &TI,
7541 unsigned NumAppendArgs,
7542 SourceRange SR) {
7543 ASTContext &Context = getASTContext();
7544 if (!DG || DG.get().isNull())
7545 return std::nullopt;
7546
7547 const int VariantId = 1;
7548 // Must be applied only to single decl.
7549 if (!DG.get().isSingleDecl()) {
7550 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7551 << VariantId << SR;
7552 return std::nullopt;
7553 }
7554 Decl *ADecl = DG.get().getSingleDecl();
7555 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7556 ADecl = FTD->getTemplatedDecl();
7557
7558 // Decl must be a function.
7559 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7560 if (!FD) {
7561 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7562 << VariantId << SR;
7563 return std::nullopt;
7564 }
7565
7566 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7567 // The 'target' attribute needs to be separately checked because it does
7568 // not always signify a multiversion function declaration.
7569 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7570 };
7571 // OpenMP is not compatible with multiversion function attributes.
7572 if (HasMultiVersionAttributes(FD)) {
7573 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7574 << SR;
7575 return std::nullopt;
7576 }
7577
7578 // Allow #pragma omp declare variant only if the function is not used.
7579 if (FD->isUsed(false))
7580 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7581 << FD->getLocation();
7582
7583 // Check if the function was emitted already.
7584 const FunctionDecl *Definition;
7585 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7586 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7587 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7588 << FD->getLocation();
7589
7590 // The VariantRef must point to function.
7591 if (!VariantRef) {
7592 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7593 return std::nullopt;
7594 }
7595
7596 auto ShouldDelayChecks = [](Expr *&E, bool) {
7597 return E && (E->isTypeDependent() || E->isValueDependent() ||
7600 };
7601 // Do not check templates, wait until instantiation.
7602 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7603 TI.anyScoreOrCondition(ShouldDelayChecks))
7604 return std::make_pair(FD, VariantRef);
7605
7606 // Deal with non-constant score and user condition expressions.
7607 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7608 bool IsScore) -> bool {
7609 if (!E || E->isIntegerConstantExpr(getASTContext()))
7610 return false;
7611
7612 if (IsScore) {
7613 // We warn on non-constant scores and pretend they were not present.
7614 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7615 << E;
7616 E = nullptr;
7617 } else {
7618 // We could replace a non-constant user condition with "false" but we
7619 // will soon need to handle these anyway for the dynamic version of
7620 // OpenMP context selectors.
7621 Diag(E->getExprLoc(),
7622 diag::err_omp_declare_variant_user_condition_not_constant)
7623 << E;
7624 }
7625 return true;
7626 };
7627 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7628 return std::nullopt;
7629
7630 QualType AdjustedFnType = FD->getType();
7631 if (NumAppendArgs) {
7632 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7633 if (!PTy) {
7634 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7635 << SR;
7636 return std::nullopt;
7637 }
7638 // Adjust the function type to account for an extra omp_interop_t for each
7639 // specified in the append_args clause.
7640 const TypeDecl *TD = nullptr;
7641 LookupResult Result(SemaRef, &Context.Idents.get("omp_interop_t"),
7643 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
7644 NamedDecl *ND = Result.getFoundDecl();
7645 TD = dyn_cast_or_null<TypeDecl>(ND);
7646 }
7647 if (!TD) {
7648 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7649 return std::nullopt;
7650 }
7651 QualType InteropType =
7652 Context.getTypeDeclType(ElaboratedTypeKeyword::None,
7653 /*Qualifier=*/std::nullopt, TD);
7654 if (PTy->isVariadic()) {
7655 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7656 return std::nullopt;
7657 }
7659 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7660 Params.insert(Params.end(), NumAppendArgs, InteropType);
7661 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7662 PTy->getExtProtoInfo());
7663 }
7664
7665 // Convert VariantRef expression to the type of the original function to
7666 // resolve possible conflicts.
7667 ExprResult VariantRefCast = VariantRef;
7668 if (getLangOpts().CPlusPlus) {
7669 QualType FnPtrType;
7670 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7671 if (Method && !Method->isStatic()) {
7672 FnPtrType = Context.getMemberPointerType(
7673 AdjustedFnType, /*Qualifier=*/std::nullopt, Method->getParent());
7674 ExprResult ER;
7675 {
7676 // Build addr_of unary op to correctly handle type checks for member
7677 // functions.
7679 ER = SemaRef.CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7680 VariantRef);
7681 }
7682 if (!ER.isUsable()) {
7683 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7684 << VariantId << VariantRef->getSourceRange();
7685 return std::nullopt;
7686 }
7687 VariantRef = ER.get();
7688 } else {
7689 FnPtrType = Context.getPointerType(AdjustedFnType);
7690 }
7691 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7692 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7693 ImplicitConversionSequence ICS = SemaRef.TryImplicitConversion(
7694 VariantRef, FnPtrType.getUnqualifiedType(),
7695 /*SuppressUserConversions=*/false, Sema::AllowedExplicit::None,
7696 /*InOverloadResolution=*/false,
7697 /*CStyle=*/false,
7698 /*AllowObjCWritebackConversion=*/false);
7699 if (ICS.isFailure()) {
7700 Diag(VariantRef->getExprLoc(),
7701 diag::err_omp_declare_variant_incompat_types)
7702 << VariantRef->getType()
7703 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7704 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7705 return std::nullopt;
7706 }
7707 VariantRefCast = SemaRef.PerformImplicitConversion(
7708 VariantRef, FnPtrType.getUnqualifiedType(),
7710 if (!VariantRefCast.isUsable())
7711 return std::nullopt;
7712 }
7713 // Drop previously built artificial addr_of unary op for member functions.
7714 if (Method && !Method->isStatic()) {
7715 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7716 if (auto *UO = dyn_cast<UnaryOperator>(
7717 PossibleAddrOfVariantRef->IgnoreImplicit()))
7718 VariantRefCast = UO->getSubExpr();
7719 }
7720 }
7721
7722 ExprResult ER = SemaRef.CheckPlaceholderExpr(VariantRefCast.get());
7723 if (!ER.isUsable() ||
7725 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7726 << VariantId << VariantRef->getSourceRange();
7727 return std::nullopt;
7728 }
7729
7730 // The VariantRef must point to function.
7731 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7732 if (!DRE) {
7733 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7734 << VariantId << VariantRef->getSourceRange();
7735 return std::nullopt;
7736 }
7737 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7738 if (!NewFD) {
7739 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7740 << VariantId << VariantRef->getSourceRange();
7741 return std::nullopt;
7742 }
7743
7744 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7745 Diag(VariantRef->getExprLoc(),
7746 diag::err_omp_declare_variant_same_base_function)
7747 << VariantRef->getSourceRange();
7748 return std::nullopt;
7749 }
7750
7751 // Check if function types are compatible in C.
7752 if (!getLangOpts().CPlusPlus) {
7753 QualType NewType =
7754 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7755 if (NewType.isNull()) {
7756 Diag(VariantRef->getExprLoc(),
7757 diag::err_omp_declare_variant_incompat_types)
7758 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7759 << VariantRef->getSourceRange();
7760 return std::nullopt;
7761 }
7762 if (NewType->isFunctionProtoType()) {
7763 if (FD->getType()->isFunctionNoProtoType())
7764 setPrototype(SemaRef, FD, NewFD, NewType);
7765 else if (NewFD->getType()->isFunctionNoProtoType())
7766 setPrototype(SemaRef, NewFD, FD, NewType);
7767 }
7768 }
7769
7770 // Check if variant function is not marked with declare variant directive.
7771 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7772 Diag(VariantRef->getExprLoc(),
7773 diag::warn_omp_declare_variant_marked_as_declare_variant)
7774 << VariantRef->getSourceRange();
7775 SourceRange SR =
7776 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7777 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7778 return std::nullopt;
7779 }
7780
7781 enum DoesntSupport {
7782 VirtFuncs = 1,
7783 Constructors = 3,
7784 Destructors = 4,
7785 DeletedFuncs = 5,
7786 DefaultedFuncs = 6,
7787 ConstexprFuncs = 7,
7788 ConstevalFuncs = 8,
7789 };
7790 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7791 if (CXXFD->isVirtual()) {
7792 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7793 << VirtFuncs;
7794 return std::nullopt;
7795 }
7796
7797 if (isa<CXXConstructorDecl>(FD)) {
7798 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7799 << Constructors;
7800 return std::nullopt;
7801 }
7802
7803 if (isa<CXXDestructorDecl>(FD)) {
7804 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7805 << Destructors;
7806 return std::nullopt;
7807 }
7808 }
7809
7810 if (FD->isDeleted()) {
7811 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7812 << DeletedFuncs;
7813 return std::nullopt;
7814 }
7815
7816 if (FD->isDefaulted()) {
7817 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7818 << DefaultedFuncs;
7819 return std::nullopt;
7820 }
7821
7822 if (FD->isConstexpr()) {
7823 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7824 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7825 return std::nullopt;
7826 }
7827
7828 // Check general compatibility.
7829 if (SemaRef.areMultiversionVariantFunctionsCompatible(
7834 VariantRef->getExprLoc(),
7835 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7836 PartialDiagnosticAt(VariantRef->getExprLoc(),
7837 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7838 << FD->getLocation()),
7839 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7840 /*CLinkageMayDiffer=*/true))
7841 return std::nullopt;
7842 return std::make_pair(FD, cast<Expr>(DRE));
7843}
7844
7846 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7847 ArrayRef<Expr *> AdjustArgsNothing,
7848 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7849 ArrayRef<Expr *> AdjustArgsNeedDeviceAddr,
7850 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7851 SourceLocation AppendArgsLoc, SourceRange SR) {
7852
7853 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7854 // An adjust_args clause or append_args clause can only be specified if the
7855 // dispatch selector of the construct selector set appears in the match
7856 // clause.
7857
7858 SmallVector<Expr *, 8> AllAdjustArgs;
7859 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7860 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7861 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDeviceAddr);
7862
7863 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7864 VariantMatchInfo VMI;
7866 if (!llvm::is_contained(
7867 VMI.ConstructTraits,
7868 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7869 if (!AllAdjustArgs.empty())
7870 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7871 << getOpenMPClauseNameForDiag(OMPC_adjust_args);
7872 if (!AppendArgs.empty())
7873 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7874 << getOpenMPClauseNameForDiag(OMPC_append_args);
7875 return;
7876 }
7877 }
7878
7879 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7880 // Each argument can only appear in a single adjust_args clause for each
7881 // declare variant directive.
7883
7884 for (Expr *E : AllAdjustArgs) {
7885 E = E->IgnoreParenImpCasts();
7886 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7887 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7888 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7889 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7890 FD->getParamDecl(PVD->getFunctionScopeIndex())
7891 ->getCanonicalDecl() == CanonPVD) {
7892 // It's a parameter of the function, check duplicates.
7893 if (!AdjustVars.insert(CanonPVD).second) {
7894 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7895 << PVD;
7896 return;
7897 }
7898 continue;
7899 }
7900 }
7901 }
7902 // Anything that is not a function parameter is an error.
7903 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7904 return;
7905 }
7906
7907 // OpenMP 6.0 [9.6.2 (page 332, line 31-33, adjust_args clause, Restrictions]
7908 // If the `need_device_addr` adjust-op modifier is present, each list item
7909 // that appears in the clause must refer to an argument in the declaration of
7910 // the function variant that has a reference type
7911 if (getLangOpts().OpenMP >= 60) {
7912 for (Expr *E : AdjustArgsNeedDeviceAddr) {
7913 E = E->IgnoreParenImpCasts();
7914 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7915 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
7916 if (!VD->getType()->isReferenceType())
7917 Diag(E->getExprLoc(),
7918 diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
7919 }
7920 }
7921 }
7922 }
7923
7924 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7925 getASTContext(), VariantRef, &TI,
7926 const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7927 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7928 AdjustArgsNeedDevicePtr.size(),
7929 const_cast<Expr **>(AdjustArgsNeedDeviceAddr.data()),
7930 AdjustArgsNeedDeviceAddr.size(),
7931 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7932 FD->addAttr(NewAttr);
7933}
7934
7935static CapturedStmt *
7937 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7938 assert(CS && "Captured statement expected");
7939 // 1.2.2 OpenMP Language Terminology
7940 // Structured block - An executable statement with a single entry at the
7941 // top and a single exit at the bottom.
7942 // The point of exit cannot be a branch out of the structured block.
7943 // longjmp() and throw() must not violate the entry/exit criteria.
7944 CS->getCapturedDecl()->setNothrow();
7945
7946 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
7947 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7949 // 1.2.2 OpenMP Language Terminology
7950 // Structured block - An executable statement with a single entry at the
7951 // top and a single exit at the bottom.
7952 // The point of exit cannot be a branch out of the structured block.
7953 // longjmp() and throw() must not violate the entry/exit criteria.
7954 CS->getCapturedDecl()->setNothrow();
7955 }
7957 return CS;
7958}
7959
7962 Stmt *AStmt, SourceLocation StartLoc,
7963 SourceLocation EndLoc) {
7964 if (!AStmt)
7965 return StmtError();
7966
7967 setBranchProtectedScope(SemaRef, OMPD_parallel, AStmt);
7968
7969 return OMPParallelDirective::Create(
7970 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
7971 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
7972}
7973
7974namespace {
7975/// Iteration space of a single for loop.
7976struct LoopIterationSpace final {
7977 /// True if the condition operator is the strict compare operator (<, > or
7978 /// !=).
7979 bool IsStrictCompare = false;
7980 /// Condition of the loop.
7981 Expr *PreCond = nullptr;
7982 /// This expression calculates the number of iterations in the loop.
7983 /// It is always possible to calculate it before starting the loop.
7984 Expr *NumIterations = nullptr;
7985 /// The loop counter variable.
7986 Expr *CounterVar = nullptr;
7987 /// Private loop counter variable.
7988 Expr *PrivateCounterVar = nullptr;
7989 /// This is initializer for the initial value of #CounterVar.
7990 Expr *CounterInit = nullptr;
7991 /// This is step for the #CounterVar used to generate its update:
7992 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7993 Expr *CounterStep = nullptr;
7994 /// Should step be subtracted?
7995 bool Subtract = false;
7996 /// Source range of the loop init.
7997 SourceRange InitSrcRange;
7998 /// Source range of the loop condition.
7999 SourceRange CondSrcRange;
8000 /// Source range of the loop increment.
8001 SourceRange IncSrcRange;
8002 /// Minimum value that can have the loop control variable. Used to support
8003 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
8004 /// since only such variables can be used in non-loop invariant expressions.
8005 Expr *MinValue = nullptr;
8006 /// Maximum value that can have the loop control variable. Used to support
8007 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
8008 /// since only such variables can be used in non-loop invariant expressions.
8009 Expr *MaxValue = nullptr;
8010 /// true, if the lower bound depends on the outer loop control var.
8011 bool IsNonRectangularLB = false;
8012 /// true, if the upper bound depends on the outer loop control var.
8013 bool IsNonRectangularUB = false;
8014 /// Index of the loop this loop depends on and forms non-rectangular loop
8015 /// nest.
8016 unsigned LoopDependentIdx = 0;
8017 /// Final condition for the non-rectangular loop nest support. It is used to
8018 /// check that the number of iterations for this particular counter must be
8019 /// finished.
8020 Expr *FinalCondition = nullptr;
8021};
8022
8023/// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls
8024/// set are referenced. Used for verifying loop nest structure before
8025/// performing a loop collapse operation.
8026class ForSubExprChecker : public DynamicRecursiveASTVisitor {
8027 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8028 VarDecl *ForbiddenVar = nullptr;
8029 SourceRange ErrLoc;
8030
8031public:
8032 explicit ForSubExprChecker(
8033 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
8034 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
8035 // We want to visit implicit code, i.e. synthetic initialisation statements
8036 // created during range-for lowering.
8037 ShouldVisitImplicitCode = true;
8038 }
8039
8040 bool VisitDeclRefExpr(DeclRefExpr *E) override {
8041 ValueDecl *VD = E->getDecl();
8043 return true;
8044 VarDecl *V = VD->getPotentiallyDecomposedVarDecl();
8045 if (V->getType()->isReferenceType()) {
8046 VarDecl *VD = V->getDefinition();
8047 if (VD && VD->hasInit()) {
8048 Expr *I = VD->getInit();
8049 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
8050 if (!DRE)
8051 return true;
8053 }
8054 }
8055 Decl *Canon = V->getCanonicalDecl();
8056 if (CollapsedLoopVarDecls.contains(Canon)) {
8057 ForbiddenVar = V;
8058 ErrLoc = E->getSourceRange();
8059 return false;
8060 }
8061
8062 return true;
8063 }
8064
8065 VarDecl *getForbiddenVar() const { return ForbiddenVar; }
8066 SourceRange getErrRange() const { return ErrLoc; }
8067};
8068
8069/// Helper class for checking canonical form of the OpenMP loops and
8070/// extracting iteration space of each loop in the loop nest, that will be used
8071/// for IR generation.
8072class OpenMPIterationSpaceChecker {
8073 /// Reference to Sema.
8074 Sema &SemaRef;
8075 /// Does the loop associated directive support non-rectangular loops?
8076 bool SupportsNonRectangular;
8077 /// Data-sharing stack.
8078 DSAStackTy &Stack;
8079 /// A location for diagnostics (when there is no some better location).
8080 SourceLocation DefaultLoc;
8081 /// A location for diagnostics (when increment is not compatible).
8082 SourceLocation ConditionLoc;
8083 /// The set of variables declared within the (to be collapsed) loop nest.
8084 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8085 /// The set of induction variables from outer collapsed loops.
8086 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars;
8087 /// A source location for referring to loop init later.
8088 SourceRange InitSrcRange;
8089 /// A source location for referring to condition later.
8090 SourceRange ConditionSrcRange;
8091 /// A source location for referring to increment later.
8092 SourceRange IncrementSrcRange;
8093 /// Loop variable.
8094 ValueDecl *LCDecl = nullptr;
8095 /// Reference to loop variable.
8096 Expr *LCRef = nullptr;
8097 /// Lower bound (initializer for the var).
8098 Expr *LB = nullptr;
8099 /// Upper bound.
8100 Expr *UB = nullptr;
8101 /// Loop step (increment).
8102 Expr *Step = nullptr;
8103 /// This flag is true when condition is one of:
8104 /// Var < UB
8105 /// Var <= UB
8106 /// UB > Var
8107 /// UB >= Var
8108 /// This will have no value when the condition is !=
8109 std::optional<bool> TestIsLessOp;
8110 /// This flag is true when condition is strict ( < or > ).
8111 bool TestIsStrictOp = false;
8112 /// This flag is true when step is subtracted on each iteration.
8113 bool SubtractStep = false;
8114 /// The outer loop counter this loop depends on (if any).
8115 const ValueDecl *DepDecl = nullptr;
8116 /// Contains number of loop (starts from 1) on which loop counter init
8117 /// expression of this loop depends on.
8118 std::optional<unsigned> InitDependOnLC;
8119 /// Contains number of loop (starts from 1) on which loop counter condition
8120 /// expression of this loop depends on.
8121 std::optional<unsigned> CondDependOnLC;
8122 /// Checks if the provide statement depends on the loop counter.
8123 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
8124 bool IsInitializer);
8125 /// Original condition required for checking of the exit condition for
8126 /// non-rectangular loop.
8127 Expr *Condition = nullptr;
8128
8129public:
8130 OpenMPIterationSpaceChecker(
8131 Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack,
8132 SourceLocation DefaultLoc,
8133 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls,
8134 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars)
8135 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8136 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
8137 CollapsedLoopVarDecls(CollapsedLoopDecls),
8138 CollapsedLoopInductionVars(CollapsedLoopInductionVars) {}
8139 /// Check init-expr for canonical loop form and save loop counter
8140 /// variable - #Var and its initialization value - #LB.
8141 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
8142 /// Check test-expr for canonical form, save upper-bound (#UB), flags
8143 /// for less/greater and for strict/non-strict comparison.
8144 bool checkAndSetCond(Expr *S);
8145 /// Check incr-expr for canonical loop form and return true if it
8146 /// does not conform, otherwise save loop step (#Step).
8147 bool checkAndSetInc(Expr *S);
8148 /// Return the loop counter variable.
8149 ValueDecl *getLoopDecl() const { return LCDecl; }
8150 /// Return the reference expression to loop counter variable.
8151 Expr *getLoopDeclRefExpr() const { return LCRef; }
8152 /// Source range of the loop init.
8153 SourceRange getInitSrcRange() const { return InitSrcRange; }
8154 /// Source range of the loop condition.
8155 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
8156 /// Source range of the loop increment.
8157 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
8158 /// True if the step should be subtracted.
8159 bool shouldSubtractStep() const { return SubtractStep; }
8160 /// True, if the compare operator is strict (<, > or !=).
8161 bool isStrictTestOp() const { return TestIsStrictOp; }
8162 /// Build the expression to calculate the number of iterations.
8163 Expr *buildNumIterations(
8164 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8165 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8166 /// Build the precondition expression for the loops.
8167 Expr *
8168 buildPreCond(Scope *S, Expr *Cond,
8169 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8170 /// Build reference expression to the counter be used for codegen.
8171 DeclRefExpr *
8172 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8173 DSAStackTy &DSA) const;
8174 /// Build reference expression to the private counter be used for
8175 /// codegen.
8176 Expr *buildPrivateCounterVar() const;
8177 /// Build initialization of the counter be used for codegen.
8178 Expr *buildCounterInit() const;
8179 /// Build step of the counter be used for codegen.
8180 Expr *buildCounterStep() const;
8181 /// Build loop data with counter value for depend clauses in ordered
8182 /// directives.
8183 Expr *
8184 buildOrderedLoopData(Scope *S, Expr *Counter,
8185 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8186 SourceLocation Loc, Expr *Inc = nullptr,
8187 OverloadedOperatorKind OOK = OO_Amp);
8188 /// Builds the minimum value for the loop counter.
8189 std::pair<Expr *, Expr *> buildMinMaxValues(
8190 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8191 /// Builds final condition for the non-rectangular loops.
8192 Expr *buildFinalCondition(Scope *S) const;
8193 /// Return true if any expression is dependent.
8194 bool dependent() const;
8195 /// Returns true if the initializer forms non-rectangular loop.
8196 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
8197 /// Returns true if the condition forms non-rectangular loop.
8198 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
8199 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
8200 unsigned getLoopDependentIdx() const {
8201 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
8202 }
8203
8204private:
8205 /// Check the right-hand side of an assignment in the increment
8206 /// expression.
8207 bool checkAndSetIncRHS(Expr *RHS);
8208 /// Helper to set loop counter variable and its initializer.
8209 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8210 bool EmitDiags);
8211 /// Helper to set upper bound.
8212 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
8213 SourceRange SR, SourceLocation SL);
8214 /// Helper to set loop increment.
8215 bool setStep(Expr *NewStep, bool Subtract);
8216};
8217
8218bool OpenMPIterationSpaceChecker::dependent() const {
8219 if (!LCDecl) {
8220 assert(!LB && !UB && !Step);
8221 return false;
8222 }
8223 return LCDecl->getType()->isDependentType() ||
8224 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
8225 (Step && Step->isValueDependent());
8226}
8227
8228bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
8229 Expr *NewLCRefExpr,
8230 Expr *NewLB, bool EmitDiags) {
8231 // State consistency checking to ensure correct usage.
8232 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
8233 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8234 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
8235 return true;
8236 LCDecl = getCanonicalDecl(NewLCDecl);
8237 LCRef = NewLCRefExpr;
8238 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
8239 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8240 if ((Ctor->isCopyOrMoveConstructor() ||
8241 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8242 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8243 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
8244 LB = NewLB;
8245 if (EmitDiags)
8246 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
8247 return false;
8248}
8249
8250bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
8251 bool StrictOp, SourceRange SR,
8252 SourceLocation SL) {
8253 // State consistency checking to ensure correct usage.
8254 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
8255 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8256 if (!NewUB || NewUB->containsErrors())
8257 return true;
8258 UB = NewUB;
8259 if (LessOp)
8260 TestIsLessOp = LessOp;
8261 TestIsStrictOp = StrictOp;
8262 ConditionSrcRange = SR;
8263 ConditionLoc = SL;
8264 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
8265 return false;
8266}
8267
8268bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
8269 // State consistency checking to ensure correct usage.
8270 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
8271 if (!NewStep || NewStep->containsErrors())
8272 return true;
8273 if (!NewStep->isValueDependent()) {
8274 // Check that the step is integer expression.
8275 SourceLocation StepLoc = NewStep->getBeginLoc();
8277 StepLoc, getExprAsWritten(NewStep));
8278 if (Val.isInvalid())
8279 return true;
8280 NewStep = Val.get();
8281
8282 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8283 // If test-expr is of form var relational-op b and relational-op is < or
8284 // <= then incr-expr must cause var to increase on each iteration of the
8285 // loop. If test-expr is of form var relational-op b and relational-op is
8286 // > or >= then incr-expr must cause var to decrease on each iteration of
8287 // the loop.
8288 // If test-expr is of form b relational-op var and relational-op is < or
8289 // <= then incr-expr must cause var to decrease on each iteration of the
8290 // loop. If test-expr is of form b relational-op var and relational-op is
8291 // > or >= then incr-expr must cause var to increase on each iteration of
8292 // the loop.
8293 std::optional<llvm::APSInt> Result =
8294 NewStep->getIntegerConstantExpr(SemaRef.Context);
8295 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
8296 bool IsConstNeg =
8297 Result && Result->isSigned() && (Subtract != Result->isNegative());
8298 bool IsConstPos =
8299 Result && Result->isSigned() && (Subtract == Result->isNegative());
8300 bool IsConstZero = Result && !Result->getBoolValue();
8301
8302 // != with increment is treated as <; != with decrement is treated as >
8303 if (!TestIsLessOp)
8304 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8305 if (UB && (IsConstZero ||
8306 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8307 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8308 SemaRef.Diag(NewStep->getExprLoc(),
8309 diag::err_omp_loop_incr_not_compatible)
8310 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
8311 SemaRef.Diag(ConditionLoc,
8312 diag::note_omp_loop_cond_requires_compatible_incr)
8313 << *TestIsLessOp << ConditionSrcRange;
8314 return true;
8315 }
8316 if (*TestIsLessOp == Subtract) {
8317 NewStep =
8318 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
8319 .get();
8320 Subtract = !Subtract;
8321 }
8322 }
8323
8324 Step = NewStep;
8325 SubtractStep = Subtract;
8326 return false;
8327}
8328
8329namespace {
8330/// Checker for the non-rectangular loops. Checks if the initializer or
8331/// condition expression references loop counter variable.
8332class LoopCounterRefChecker final
8333 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8334 Sema &SemaRef;
8335 DSAStackTy &Stack;
8336 const ValueDecl *CurLCDecl = nullptr;
8337 const ValueDecl *DepDecl = nullptr;
8338 const ValueDecl *PrevDepDecl = nullptr;
8339 bool IsInitializer = true;
8340 bool SupportsNonRectangular;
8341 unsigned BaseLoopId = 0;
8342 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8343 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
8344 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8345 << (IsInitializer ? 0 : 1);
8346 return false;
8347 }
8348 const auto &&Data = Stack.isLoopControlVariable(VD);
8349 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8350 // The type of the loop iterator on which we depend may not have a random
8351 // access iterator type.
8352 if (Data.first && VD->getType()->isRecordType()) {
8353 SmallString<128> Name;
8354 llvm::raw_svector_ostream OS(Name);
8355 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8356 /*Qualified=*/true);
8357 SemaRef.Diag(E->getExprLoc(),
8358 diag::err_omp_wrong_dependency_iterator_type)
8359 << OS.str();
8360 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8361 return false;
8362 }
8363 if (Data.first && !SupportsNonRectangular) {
8364 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8365 return false;
8366 }
8367 if (Data.first &&
8368 (DepDecl || (PrevDepDecl &&
8369 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8370 if (!DepDecl && PrevDepDecl)
8371 DepDecl = PrevDepDecl;
8372 SmallString<128> Name;
8373 llvm::raw_svector_ostream OS(Name);
8374 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8375 /*Qualified=*/true);
8376 SemaRef.Diag(E->getExprLoc(),
8377 diag::err_omp_invariant_or_linear_dependency)
8378 << OS.str();
8379 return false;
8380 }
8381 if (Data.first) {
8382 DepDecl = VD;
8383 BaseLoopId = Data.first;
8384 }
8385 return Data.first;
8386 }
8387
8388public:
8389 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8390 const ValueDecl *VD = E->getDecl();
8391 if (isa<VarDecl>(VD))
8392 return checkDecl(E, VD);
8393 return false;
8394 }
8395 bool VisitMemberExpr(const MemberExpr *E) {
8396 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8397 const ValueDecl *VD = E->getMemberDecl();
8398 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8399 return checkDecl(E, VD);
8400 }
8401 return false;
8402 }
8403 bool VisitStmt(const Stmt *S) {
8404 bool Res = false;
8405 for (const Stmt *Child : S->children())
8406 Res = (Child && Visit(Child)) || Res;
8407 return Res;
8408 }
8409 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8410 const ValueDecl *CurLCDecl, bool IsInitializer,
8411 const ValueDecl *PrevDepDecl = nullptr,
8412 bool SupportsNonRectangular = true)
8413 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8414 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8415 SupportsNonRectangular(SupportsNonRectangular) {}
8416 unsigned getBaseLoopId() const {
8417 assert(CurLCDecl && "Expected loop dependency.");
8418 return BaseLoopId;
8419 }
8420 const ValueDecl *getDepDecl() const {
8421 assert(CurLCDecl && "Expected loop dependency.");
8422 return DepDecl;
8423 }
8424};
8425} // namespace
8426
8427std::optional<unsigned>
8428OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8429 bool IsInitializer) {
8430 // Check for the non-rectangular loops.
8431 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8432 DepDecl, SupportsNonRectangular);
8433 if (LoopStmtChecker.Visit(S)) {
8434 DepDecl = LoopStmtChecker.getDepDecl();
8435 return LoopStmtChecker.getBaseLoopId();
8436 }
8437 return std::nullopt;
8438}
8439
8440bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8441 // Check init-expr for canonical loop form and save loop counter
8442 // variable - #Var and its initialization value - #LB.
8443 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8444 // var = lb
8445 // integer-type var = lb
8446 // random-access-iterator-type var = lb
8447 // pointer-type var = lb
8448 //
8449 if (!S) {
8450 if (EmitDiags) {
8451 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8452 }
8453 return true;
8454 }
8455 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8456 if (!ExprTemp->cleanupsHaveSideEffects())
8457 S = ExprTemp->getSubExpr();
8458
8459 if (!CollapsedLoopVarDecls.empty()) {
8460 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8461 if (!FSEC.TraverseStmt(S)) {
8462 SourceRange Range = FSEC.getErrRange();
8463 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8464 << Range.getEnd() << 0 << FSEC.getForbiddenVar();
8465 return true;
8466 }
8467 }
8468
8469 // Helper lambda to check if a loop variable is already used in an outer
8470 // loop.
8471 auto CheckLoopVarReuse = [&](ValueDecl *LoopVar, SourceLocation Loc) -> bool {
8472 if (EmitDiags &&
8473 CollapsedLoopInductionVars.count(LoopVar->getCanonicalDecl())) {
8474 SemaRef.Diag(Loc, diag::err_omp_loop_var_reused_in_collapsed_loop)
8475 << LoopVar;
8476 return true;
8477 }
8478 return false;
8479 };
8480
8481 InitSrcRange = S->getSourceRange();
8482 if (Expr *E = dyn_cast<Expr>(S))
8483 S = E->IgnoreParens();
8484 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8485 if (BO->getOpcode() == BO_Assign) {
8486 Expr *LHS = BO->getLHS()->IgnoreParens();
8487 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8488 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8489 if (auto *ME =
8490 dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit()))) {
8491 ValueDecl *LoopVar = ME->getMemberDecl();
8492 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
8493 return true;
8494 return setLCDeclAndLB(LoopVar, ME, BO->getRHS(), EmitDiags);
8495 }
8496 ValueDecl *LoopVar = DRE->getDecl();
8497 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
8498 return true;
8499 return setLCDeclAndLB(LoopVar, DRE, BO->getRHS(), EmitDiags);
8500 }
8501 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8502 if (ME->isArrow() &&
8503 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) {
8504 ValueDecl *LoopVar = ME->getMemberDecl();
8505 if (CheckLoopVarReuse(LoopVar, LHS->getBeginLoc()))
8506 return true;
8507 return setLCDeclAndLB(LoopVar, ME, BO->getRHS(), EmitDiags);
8508 }
8509 }
8510 }
8511 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8512 if (DS->isSingleDecl()) {
8513 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8514 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8515 // Accept non-canonical init form here but emit ext. warning.
8516 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8517 SemaRef.Diag(S->getBeginLoc(),
8518 diag::ext_omp_loop_not_canonical_init)
8519 << S->getSourceRange();
8520 if (CheckLoopVarReuse(Var, Var->getLocation()))
8521 return true;
8522 return setLCDeclAndLB(
8523 Var,
8524 buildDeclRefExpr(SemaRef, Var,
8525 Var->getType().getNonReferenceType(),
8526 DS->getBeginLoc()),
8527 Var->getInit(), EmitDiags);
8528 }
8529 }
8530 }
8531 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8532 if (CE->getOperator() == OO_Equal) {
8533 Expr *LHS = CE->getArg(0);
8534 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8535 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8536 if (auto *ME =
8537 dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit()))) {
8538 ValueDecl *LoopVar = ME->getMemberDecl();
8539 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
8540 return true;
8541 return setLCDeclAndLB(LoopVar, ME, CE->getArg(1), EmitDiags);
8542 }
8543 ValueDecl *LoopVar = DRE->getDecl();
8544 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
8545 return true;
8546 return setLCDeclAndLB(LoopVar, DRE, CE->getArg(1), EmitDiags);
8547 }
8548 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8549 if (ME->isArrow() &&
8550 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) {
8551 ValueDecl *LoopVar = ME->getMemberDecl();
8552 if (CheckLoopVarReuse(LoopVar, LHS->getBeginLoc()))
8553 return true;
8554 return setLCDeclAndLB(LoopVar, ME, CE->getArg(1), EmitDiags);
8555 }
8556 }
8557 }
8558 }
8559
8560 if (dependent() || SemaRef.CurContext->isDependentContext())
8561 return false;
8562 if (EmitDiags) {
8563 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8564 << S->getSourceRange();
8565 }
8566 return true;
8567}
8568
8569/// Ignore parenthesizes, implicit casts, copy constructor and return the
8570/// variable (which may be the loop variable) if possible.
8571static const ValueDecl *getInitLCDecl(const Expr *E) {
8572 if (!E)
8573 return nullptr;
8574 E = getExprAsWritten(E);
8575 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8576 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8577 if ((Ctor->isCopyOrMoveConstructor() ||
8578 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8579 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8580 E = CE->getArg(0)->IgnoreParenImpCasts();
8581 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8582 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8583 return getCanonicalDecl(VD);
8584 }
8585 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8586 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8587 return getCanonicalDecl(ME->getMemberDecl());
8588 return nullptr;
8589}
8590
8591bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8592 // Check test-expr for canonical form, save upper-bound UB, flags for
8593 // less/greater and for strict/non-strict comparison.
8594 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8595 // var relational-op b
8596 // b relational-op var
8597 //
8598 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8599 if (!S) {
8600 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8601 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8602 return true;
8603 }
8604 Condition = S;
8605 S = getExprAsWritten(S);
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() << 1 << FSEC.getForbiddenVar();
8613 return true;
8614 }
8615 }
8616
8617 SourceLocation CondLoc = S->getBeginLoc();
8618 auto &&CheckAndSetCond =
8619 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8620 const Expr *RHS, SourceRange SR,
8621 SourceLocation OpLoc) -> std::optional<bool> {
8622 if (BinaryOperator::isRelationalOp(Opcode)) {
8623 if (getInitLCDecl(LHS) == LCDecl)
8624 return setUB(const_cast<Expr *>(RHS),
8625 (Opcode == BO_LT || Opcode == BO_LE),
8626 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8627 if (getInitLCDecl(RHS) == LCDecl)
8628 return setUB(const_cast<Expr *>(LHS),
8629 (Opcode == BO_GT || Opcode == BO_GE),
8630 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8631 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8632 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8633 /*LessOp=*/std::nullopt,
8634 /*StrictOp=*/true, SR, OpLoc);
8635 }
8636 return std::nullopt;
8637 };
8638 std::optional<bool> Res;
8639 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8640 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8641 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8642 RBO->getOperatorLoc());
8643 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8644 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8645 BO->getSourceRange(), BO->getOperatorLoc());
8646 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8647 if (CE->getNumArgs() == 2) {
8648 Res = CheckAndSetCond(
8649 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8650 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8651 }
8652 }
8653 if (Res)
8654 return *Res;
8655 if (dependent() || SemaRef.CurContext->isDependentContext())
8656 return false;
8657 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8658 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8659 return true;
8660}
8661
8662bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8663 // RHS of canonical loop form increment can be:
8664 // var + incr
8665 // incr + var
8666 // var - incr
8667 //
8668 RHS = RHS->IgnoreParenImpCasts();
8669 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8670 if (BO->isAdditiveOp()) {
8671 bool IsAdd = BO->getOpcode() == BO_Add;
8672 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8673 return setStep(BO->getRHS(), !IsAdd);
8674 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8675 return setStep(BO->getLHS(), /*Subtract=*/false);
8676 }
8677 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8678 bool IsAdd = CE->getOperator() == OO_Plus;
8679 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8680 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8681 return setStep(CE->getArg(1), !IsAdd);
8682 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8683 return setStep(CE->getArg(0), /*Subtract=*/false);
8684 }
8685 }
8686 if (dependent() || SemaRef.CurContext->isDependentContext())
8687 return false;
8688 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8689 << RHS->getSourceRange() << LCDecl;
8690 return true;
8691}
8692
8693bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8694 // Check incr-expr for canonical loop form and return true if it
8695 // does not conform.
8696 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8697 // ++var
8698 // var++
8699 // --var
8700 // var--
8701 // var += incr
8702 // var -= incr
8703 // var = var + incr
8704 // var = incr + var
8705 // var = var - incr
8706 //
8707 if (!S) {
8708 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8709 return true;
8710 }
8711 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8712 if (!ExprTemp->cleanupsHaveSideEffects())
8713 S = ExprTemp->getSubExpr();
8714
8715 if (!CollapsedLoopVarDecls.empty()) {
8716 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8717 if (!FSEC.TraverseStmt(S)) {
8718 SourceRange Range = FSEC.getErrRange();
8719 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8720 << Range.getEnd() << 2 << FSEC.getForbiddenVar();
8721 return true;
8722 }
8723 }
8724
8725 IncrementSrcRange = S->getSourceRange();
8726 S = S->IgnoreParens();
8727 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8728 if (UO->isIncrementDecrementOp() &&
8729 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8730 return setStep(SemaRef
8731 .ActOnIntegerConstant(UO->getBeginLoc(),
8732 (UO->isDecrementOp() ? -1 : 1))
8733 .get(),
8734 /*Subtract=*/false);
8735 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8736 switch (BO->getOpcode()) {
8737 case BO_AddAssign:
8738 case BO_SubAssign:
8739 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8740 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8741 break;
8742 case BO_Assign:
8743 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8744 return checkAndSetIncRHS(BO->getRHS());
8745 break;
8746 default:
8747 break;
8748 }
8749 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8750 switch (CE->getOperator()) {
8751 case OO_PlusPlus:
8752 case OO_MinusMinus:
8753 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8754 return setStep(SemaRef
8755 .ActOnIntegerConstant(
8756 CE->getBeginLoc(),
8757 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8758 .get(),
8759 /*Subtract=*/false);
8760 break;
8761 case OO_PlusEqual:
8762 case OO_MinusEqual:
8763 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8764 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8765 break;
8766 case OO_Equal:
8767 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8768 return checkAndSetIncRHS(CE->getArg(1));
8769 break;
8770 default:
8771 break;
8772 }
8773 }
8774 if (dependent() || SemaRef.CurContext->isDependentContext())
8775 return false;
8776 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8777 << S->getSourceRange() << LCDecl;
8778 return true;
8779}
8780
8781static ExprResult
8782tryBuildCapture(Sema &SemaRef, Expr *Capture,
8783 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8784 StringRef Name = ".capture_expr.") {
8785 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8786 return Capture;
8787 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8788 return SemaRef.PerformImplicitConversion(Capture->IgnoreImpCasts(),
8789 Capture->getType(),
8791 /*AllowExplicit=*/true);
8792 auto I = Captures.find(Capture);
8793 if (I != Captures.end())
8794 return buildCapture(SemaRef, Capture, I->second, Name);
8795 DeclRefExpr *Ref = nullptr;
8796 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8797 Captures[Capture] = Ref;
8798 return Res;
8799}
8800
8801/// Calculate number of iterations, transforming to unsigned, if number of
8802/// iterations may be larger than the original type.
8803static Expr *
8804calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8805 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8806 bool TestIsStrictOp, bool RoundToStep,
8807 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8808 std::optional<unsigned> InitDependOnLC,
8809 std::optional<unsigned> CondDependOnLC) {
8810 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8811 if (!NewStep.isUsable())
8812 return nullptr;
8813 llvm::APSInt LRes, SRes;
8814 bool IsLowerConst = false, IsStepConst = false;
8815 if (std::optional<llvm::APSInt> Res =
8816 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8817 LRes = *Res;
8818 IsLowerConst = true;
8819 }
8820 if (std::optional<llvm::APSInt> Res =
8821 Step->getIntegerConstantExpr(SemaRef.Context)) {
8822 SRes = *Res;
8823 IsStepConst = true;
8824 }
8825 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8826 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8827 (TestIsStrictOp && LRes.isStrictlyPositive()));
8828 bool NeedToReorganize = false;
8829 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8830 if (!NoNeedToConvert && IsLowerConst &&
8831 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8832 NoNeedToConvert = true;
8833 if (RoundToStep) {
8834 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8835 ? LRes.getBitWidth()
8836 : SRes.getBitWidth();
8837 LRes = LRes.extend(BW + 1);
8838 LRes.setIsSigned(true);
8839 SRes = SRes.extend(BW + 1);
8840 SRes.setIsSigned(true);
8841 LRes -= SRes;
8842 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8843 LRes = LRes.trunc(BW);
8844 }
8845 if (TestIsStrictOp) {
8846 unsigned BW = LRes.getBitWidth();
8847 LRes = LRes.extend(BW + 1);
8848 LRes.setIsSigned(true);
8849 ++LRes;
8850 NoNeedToConvert =
8851 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8852 // truncate to the original bitwidth.
8853 LRes = LRes.trunc(BW);
8854 }
8855 NeedToReorganize = NoNeedToConvert;
8856 }
8857 llvm::APSInt URes;
8858 bool IsUpperConst = false;
8859 if (std::optional<llvm::APSInt> Res =
8860 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8861 URes = *Res;
8862 IsUpperConst = true;
8863 }
8864 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8865 (!RoundToStep || IsStepConst)) {
8866 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8867 : URes.getBitWidth();
8868 LRes = LRes.extend(BW + 1);
8869 LRes.setIsSigned(true);
8870 URes = URes.extend(BW + 1);
8871 URes.setIsSigned(true);
8872 URes -= LRes;
8873 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8874 NeedToReorganize = NoNeedToConvert;
8875 }
8876 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8877 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8878 // unsigned.
8879 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8880 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8881 QualType LowerTy = Lower->getType();
8882 QualType UpperTy = Upper->getType();
8883 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8884 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8885 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8886 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8888 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8889 Upper =
8890 SemaRef
8892 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8894 .get();
8895 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8896 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8897 }
8898 }
8899 if (!Lower || !Upper || NewStep.isInvalid())
8900 return nullptr;
8901
8902 ExprResult Diff;
8903
8904 // For nested triangular loops (depth >= 2), use already computed Upper and
8905 // Lower bounds to calculate the number of iterations: Upper - Lower + 1.
8906 // Don't apply to first-level triangular loops as the standard formula handles
8907 // those correctly.
8908 if (TestIsStrictOp && InitDependOnLC.has_value() &&
8909 InitDependOnLC.value() >= 2 && !CondDependOnLC.has_value()) {
8910 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8911 if (!Diff.isUsable())
8912 return nullptr;
8913
8914 Diff =
8915 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(),
8916 SemaRef.ActOnIntegerConstant(DefaultLoc, 1).get());
8917 if (!Diff.isUsable())
8918 return nullptr;
8919
8920 return Diff.get();
8921 }
8922
8923 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8924 // 1]).
8925 if (NeedToReorganize) {
8926 Diff = Lower;
8927
8928 if (RoundToStep) {
8929 // Lower - Step
8930 Diff =
8931 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8932 if (!Diff.isUsable())
8933 return nullptr;
8934 }
8935
8936 // Lower - Step [+ 1]
8937 if (TestIsStrictOp)
8938 Diff = SemaRef.BuildBinOp(
8939 S, DefaultLoc, BO_Add, Diff.get(),
8940 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8941 if (!Diff.isUsable())
8942 return nullptr;
8943
8944 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8945 if (!Diff.isUsable())
8946 return nullptr;
8947
8948 // Upper - (Lower - Step [+ 1]).
8949 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8950 if (!Diff.isUsable())
8951 return nullptr;
8952 } else {
8953 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8954
8955 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8956 // BuildBinOp already emitted error, this one is to point user to upper
8957 // and lower bound, and to tell what is passed to 'operator-'.
8958 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8959 << Upper->getSourceRange() << Lower->getSourceRange();
8960 return nullptr;
8961 }
8962
8963 if (!Diff.isUsable())
8964 return nullptr;
8965
8966 // Upper - Lower [- 1]
8967 if (TestIsStrictOp)
8968 Diff = SemaRef.BuildBinOp(
8969 S, DefaultLoc, BO_Sub, Diff.get(),
8970 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8971 if (!Diff.isUsable())
8972 return nullptr;
8973
8974 if (RoundToStep) {
8975 // Upper - Lower [- 1] + Step
8976 Diff =
8977 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8978 if (!Diff.isUsable())
8979 return nullptr;
8980 }
8981 }
8982
8983 // Parentheses (for dumping/debugging purposes only).
8984 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8985 if (!Diff.isUsable())
8986 return nullptr;
8987
8988 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8989 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8990 if (!Diff.isUsable())
8991 return nullptr;
8992
8993 return Diff.get();
8994}
8995
8996/// Build the expression to calculate the number of iterations.
8997Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8998 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8999 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9000 QualType VarType = LCDecl->getType().getNonReferenceType();
9001 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9002 !SemaRef.getLangOpts().CPlusPlus)
9003 return nullptr;
9004 Expr *LBVal = LB;
9005 Expr *UBVal = UB;
9006 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
9007 // max(LB(MinVal), LB(MaxVal)))
9008 if (InitDependOnLC) {
9009 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
9010 if (!IS.MinValue || !IS.MaxValue)
9011 return nullptr;
9012 // OuterVar = Min
9013 ExprResult MinValue =
9014 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
9015 if (!MinValue.isUsable())
9016 return nullptr;
9017
9018 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
9019 IS.CounterVar, MinValue.get());
9020 if (!LBMinVal.isUsable())
9021 return nullptr;
9022 // OuterVar = Min, LBVal
9023 LBMinVal =
9024 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
9025 if (!LBMinVal.isUsable())
9026 return nullptr;
9027 // (OuterVar = Min, LBVal)
9028 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
9029 if (!LBMinVal.isUsable())
9030 return nullptr;
9031
9032 // OuterVar = Max
9033 ExprResult MaxValue =
9034 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
9035 if (!MaxValue.isUsable())
9036 return nullptr;
9037
9038 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
9039 IS.CounterVar, MaxValue.get());
9040 if (!LBMaxVal.isUsable())
9041 return nullptr;
9042 // OuterVar = Max, LBVal
9043 LBMaxVal =
9044 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
9045 if (!LBMaxVal.isUsable())
9046 return nullptr;
9047 // (OuterVar = Max, LBVal)
9048 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
9049 if (!LBMaxVal.isUsable())
9050 return nullptr;
9051
9052 Expr *LBMin =
9053 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
9054 Expr *LBMax =
9055 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
9056 if (!LBMin || !LBMax)
9057 return nullptr;
9058 // LB(MinVal) < LB(MaxVal)
9059 ExprResult MinLessMaxRes =
9060 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
9061 if (!MinLessMaxRes.isUsable())
9062 return nullptr;
9063 Expr *MinLessMax =
9064 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
9065 .get();
9066 if (!MinLessMax)
9067 return nullptr;
9068 if (*TestIsLessOp) {
9069 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
9070 // LB(MaxVal))
9071 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
9072 MinLessMax, LBMin, LBMax);
9073 if (!MinLB.isUsable())
9074 return nullptr;
9075 LBVal = MinLB.get();
9076 } else {
9077 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
9078 // LB(MaxVal))
9079 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
9080 MinLessMax, LBMax, LBMin);
9081 if (!MaxLB.isUsable())
9082 return nullptr;
9083 LBVal = MaxLB.get();
9084 }
9085 // OuterVar = LB
9086 LBMinVal =
9087 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
9088 if (!LBMinVal.isUsable())
9089 return nullptr;
9090 LBVal = LBMinVal.get();
9091 }
9092 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
9093 // min(UB(MinVal), UB(MaxVal))
9094 if (CondDependOnLC) {
9095 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
9096 if (!IS.MinValue || !IS.MaxValue)
9097 return nullptr;
9098 // OuterVar = Min
9099 ExprResult MinValue =
9100 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
9101 if (!MinValue.isUsable())
9102 return nullptr;
9103
9104 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
9105 IS.CounterVar, MinValue.get());
9106 if (!UBMinVal.isUsable())
9107 return nullptr;
9108 // OuterVar = Min, UBVal
9109 UBMinVal =
9110 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
9111 if (!UBMinVal.isUsable())
9112 return nullptr;
9113 // (OuterVar = Min, UBVal)
9114 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
9115 if (!UBMinVal.isUsable())
9116 return nullptr;
9117
9118 // OuterVar = Max
9119 ExprResult MaxValue =
9120 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
9121 if (!MaxValue.isUsable())
9122 return nullptr;
9123
9124 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
9125 IS.CounterVar, MaxValue.get());
9126 if (!UBMaxVal.isUsable())
9127 return nullptr;
9128 // OuterVar = Max, UBVal
9129 UBMaxVal =
9130 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
9131 if (!UBMaxVal.isUsable())
9132 return nullptr;
9133 // (OuterVar = Max, UBVal)
9134 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
9135 if (!UBMaxVal.isUsable())
9136 return nullptr;
9137
9138 Expr *UBMin =
9139 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
9140 Expr *UBMax =
9141 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
9142 if (!UBMin || !UBMax)
9143 return nullptr;
9144 // UB(MinVal) > UB(MaxVal)
9145 ExprResult MinGreaterMaxRes =
9146 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
9147 if (!MinGreaterMaxRes.isUsable())
9148 return nullptr;
9149 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
9150 Captures, ".min_greater_max")
9151 .get();
9152 if (!MinGreaterMax)
9153 return nullptr;
9154 if (*TestIsLessOp) {
9155 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
9156 // UB(MaxVal))
9157 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
9158 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
9159 if (!MaxUB.isUsable())
9160 return nullptr;
9161 UBVal = MaxUB.get();
9162 } else {
9163 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
9164 // UB(MaxVal))
9165 ExprResult MinUB = SemaRef.ActOnConditionalOp(
9166 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
9167 if (!MinUB.isUsable())
9168 return nullptr;
9169 UBVal = MinUB.get();
9170 }
9171 }
9172 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9173 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9174 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
9175 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
9176 if (!Upper || !Lower)
9177 return nullptr;
9178
9179 ExprResult Diff = calculateNumIters(
9180 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType, TestIsStrictOp,
9181 /*RoundToStep=*/true, Captures, InitDependOnLC, CondDependOnLC);
9182 if (!Diff.isUsable())
9183 return nullptr;
9184
9185 // OpenMP runtime requires 32-bit or 64-bit loop variables.
9186 QualType Type = Diff.get()->getType();
9187 ASTContext &C = SemaRef.Context;
9188 bool UseVarType = VarType->hasIntegerRepresentation() &&
9189 C.getTypeSize(Type) > C.getTypeSize(VarType);
9190 if (!Type->isIntegerType() || UseVarType) {
9191 unsigned NewSize =
9192 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
9193 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
9195 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
9196 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
9197 Diff = SemaRef.PerformImplicitConversion(Diff.get(), Type,
9199 /*AllowExplicit=*/true);
9200 if (!Diff.isUsable())
9201 return nullptr;
9202 }
9203 }
9204 if (LimitedType) {
9205 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
9206 if (NewSize != C.getTypeSize(Type)) {
9207 if (NewSize < C.getTypeSize(Type)) {
9208 assert(NewSize == 64 && "incorrect loop var size");
9209 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
9210 << InitSrcRange << ConditionSrcRange;
9211 }
9212 QualType NewType = C.getIntTypeForBitwidth(
9214 C.getTypeSize(Type) < NewSize);
9215 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
9216 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
9218 /*AllowExplicit=*/true);
9219 if (!Diff.isUsable())
9220 return nullptr;
9221 }
9222 }
9223 }
9224
9225 return Diff.get();
9226}
9227
9228std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9229 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9230 // Do not build for iterators, they cannot be used in non-rectangular loop
9231 // nests.
9232 if (LCDecl->getType()->isRecordType())
9233 return std::make_pair(nullptr, nullptr);
9234 // If we subtract, the min is in the condition, otherwise the min is in the
9235 // init value.
9236 Expr *MinExpr = nullptr;
9237 Expr *MaxExpr = nullptr;
9238 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9239 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9240 bool LBNonRect =
9241 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9242 bool UBNonRect =
9243 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9244 Expr *Lower =
9245 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
9246 Expr *Upper =
9247 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
9248 if (!Upper || !Lower)
9249 return std::make_pair(nullptr, nullptr);
9250
9251 if (*TestIsLessOp)
9252 MinExpr = Lower;
9253 else
9254 MaxExpr = Upper;
9255
9256 // Build minimum/maximum value based on number of iterations.
9257 QualType VarType = LCDecl->getType().getNonReferenceType();
9258
9259 ExprResult Diff = calculateNumIters(
9260 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType, TestIsStrictOp,
9261 /*RoundToStep=*/false, Captures, InitDependOnLC, CondDependOnLC);
9262
9263 if (!Diff.isUsable())
9264 return std::make_pair(nullptr, nullptr);
9265
9266 // ((Upper - Lower [- 1]) / Step) * Step
9267 // Parentheses (for dumping/debugging purposes only).
9268 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9269 if (!Diff.isUsable())
9270 return std::make_pair(nullptr, nullptr);
9271
9272 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
9273 if (!NewStep.isUsable())
9274 return std::make_pair(nullptr, nullptr);
9275 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
9276 if (!Diff.isUsable())
9277 return std::make_pair(nullptr, nullptr);
9278
9279 // Parentheses (for dumping/debugging purposes only).
9280 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9281 if (!Diff.isUsable())
9282 return std::make_pair(nullptr, nullptr);
9283
9284 // Convert to the ptrdiff_t, if original type is pointer.
9285 if (VarType->isAnyPointerType() &&
9286 !SemaRef.Context.hasSameType(
9287 Diff.get()->getType(),
9289 Diff = SemaRef.PerformImplicitConversion(
9290 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
9291 AssignmentAction::Converting, /*AllowExplicit=*/true);
9292 }
9293 if (!Diff.isUsable())
9294 return std::make_pair(nullptr, nullptr);
9295
9296 if (*TestIsLessOp) {
9297 // MinExpr = Lower;
9298 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
9299 Diff = SemaRef.BuildBinOp(
9300 S, DefaultLoc, BO_Add,
9301 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
9302 Diff.get());
9303 if (!Diff.isUsable())
9304 return std::make_pair(nullptr, nullptr);
9305 } else {
9306 // MaxExpr = Upper;
9307 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
9308 Diff = SemaRef.BuildBinOp(
9309 S, DefaultLoc, BO_Sub,
9310 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
9311 Diff.get());
9312 if (!Diff.isUsable())
9313 return std::make_pair(nullptr, nullptr);
9314 }
9315
9316 // Convert to the original type.
9317 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
9318 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
9320 /*AllowExplicit=*/true);
9321 if (!Diff.isUsable())
9322 return std::make_pair(nullptr, nullptr);
9323
9324 Sema::TentativeAnalysisScope Trap(SemaRef);
9325 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
9326 if (!Diff.isUsable())
9327 return std::make_pair(nullptr, nullptr);
9328
9329 if (*TestIsLessOp)
9330 MaxExpr = Diff.get();
9331 else
9332 MinExpr = Diff.get();
9333
9334 return std::make_pair(MinExpr, MaxExpr);
9335}
9336
9337Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
9338 if (InitDependOnLC || CondDependOnLC)
9339 return Condition;
9340 return nullptr;
9341}
9342
9343Expr *OpenMPIterationSpaceChecker::buildPreCond(
9344 Scope *S, Expr *Cond,
9345 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9346 // Do not build a precondition when the condition/initialization is dependent
9347 // to prevent pessimistic early loop exit.
9348 // TODO: this can be improved by calculating min/max values but not sure that
9349 // it will be very effective.
9350 if (CondDependOnLC || InitDependOnLC)
9351 return SemaRef
9353 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
9354 SemaRef.Context.BoolTy, /*Action=*/AssignmentAction::Casting,
9355 /*AllowExplicit=*/true)
9356 .get();
9357
9358 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
9359 Sema::TentativeAnalysisScope Trap(SemaRef);
9360
9361 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9362 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9363 if (!NewLB.isUsable() || !NewUB.isUsable())
9364 return nullptr;
9365
9366 ExprResult CondExpr =
9367 SemaRef.BuildBinOp(S, DefaultLoc,
9368 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9369 : (TestIsStrictOp ? BO_GT : BO_GE),
9370 NewLB.get(), NewUB.get());
9371 if (CondExpr.isUsable()) {
9372 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
9373 SemaRef.Context.BoolTy))
9374 CondExpr = SemaRef.PerformImplicitConversion(
9375 CondExpr.get(), SemaRef.Context.BoolTy,
9376 /*Action=*/AssignmentAction::Casting,
9377 /*AllowExplicit=*/true);
9378 }
9379
9380 // Otherwise use original loop condition and evaluate it in runtime.
9381 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9382}
9383
9384/// Build reference expression to the counter be used for codegen.
9385DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9386 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9387 DSAStackTy &DSA) const {
9388 auto *VD = dyn_cast<VarDecl>(LCDecl);
9389 if (!VD) {
9390 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(LCDecl);
9392 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
9393 const DSAStackTy::DSAVarData Data =
9394 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
9395 // If the loop control decl is explicitly marked as private, do not mark it
9396 // as captured again.
9397 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
9398 Captures.insert(std::make_pair(LCRef, Ref));
9399 return Ref;
9400 }
9401 return cast<DeclRefExpr>(LCRef);
9402}
9403
9404Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9405 if (LCDecl && !LCDecl->isInvalidDecl()) {
9407 VarDecl *PrivateVar = buildVarDecl(
9408 SemaRef, DefaultLoc, Type, LCDecl->getName(),
9409 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9410 isa<VarDecl>(LCDecl)
9411 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
9412 : nullptr);
9413 if (PrivateVar->isInvalidDecl())
9414 return nullptr;
9415 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
9416 }
9417 return nullptr;
9418}
9419
9420/// Build initialization of the counter to be used for codegen.
9421Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9422
9423/// Build step of the counter be used for codegen.
9424Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9425
9426Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9427 Scope *S, Expr *Counter,
9428 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9429 Expr *Inc, OverloadedOperatorKind OOK) {
9430 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
9431 if (!Cnt)
9432 return nullptr;
9433 if (Inc) {
9434 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9435 "Expected only + or - operations for depend clauses.");
9436 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9437 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
9438 if (!Cnt)
9439 return nullptr;
9440 }
9441 QualType VarType = LCDecl->getType().getNonReferenceType();
9442 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9443 !SemaRef.getLangOpts().CPlusPlus)
9444 return nullptr;
9445 // Upper - Lower
9446 Expr *Upper =
9447 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9448 Expr *Lower =
9449 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9450 if (!Upper || !Lower)
9451 return nullptr;
9452
9453 ExprResult Diff =
9454 calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9455 /*TestIsStrictOp=*/false, /*RoundToStep=*/false,
9456 Captures, InitDependOnLC, CondDependOnLC);
9457 if (!Diff.isUsable())
9458 return nullptr;
9459
9460 return Diff.get();
9461}
9462} // namespace
9463
9465 Stmt *Init) {
9466 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9467 assert(Init && "Expected loop in canonical form.");
9468 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9469 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9470 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
9471 return;
9472
9473 DSAStack->loopStart();
9475 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9476 *DSAStack, ForLoc, EmptyDeclSet,
9477 EmptyDeclSet);
9478 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9479 if (ValueDecl *D = ISC.getLoopDecl()) {
9480 auto *VD = dyn_cast<VarDecl>(D);
9481 DeclRefExpr *PrivateRef = nullptr;
9482 if (!VD) {
9484 VD = Private;
9485 } else {
9486 PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(),
9487 /*WithInit=*/false);
9488 VD = cast<VarDecl>(PrivateRef->getDecl());
9489 }
9490 }
9491 DSAStack->addLoopControlVariable(D, VD);
9492 const Decl *LD = DSAStack->getPossiblyLoopCounter();
9493 if (LD != D->getCanonicalDecl()) {
9494 DSAStack->resetPossibleLoopCounter();
9495 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9496 SemaRef.MarkDeclarationsReferencedInExpr(buildDeclRefExpr(
9497 SemaRef, const_cast<VarDecl *>(Var),
9498 Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
9499 /*RefersToCapture=*/true));
9500 }
9501 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9502 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9503 // associated for-loop of a simd construct with just one associated
9504 // for-loop may be listed in a linear clause with a constant-linear-step
9505 // that is the increment of the associated for-loop. The loop iteration
9506 // variable(s) in the associated for-loop(s) of a for or parallel for
9507 // construct may be listed in a private or lastprivate clause.
9508 DSAStackTy::DSAVarData DVar =
9509 DSAStack->getTopDSA(D, /*FromParent=*/false);
9510 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9511 // is declared in the loop and it is predetermined as a private.
9512 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9513 OpenMPClauseKind PredeterminedCKind =
9515 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9516 : OMPC_private;
9517 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
9518 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9519 };
9520 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9521 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9522 (getLangOpts().OpenMP <= 45 ||
9523 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9525 IsOpenMPTaskloopDirective(DKind) ||
9527 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9528 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9529 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9530 unsigned OMPVersion = getLangOpts().OpenMP;
9531 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9532 << getOpenMPClauseNameForDiag(DVar.CKind)
9533 << getOpenMPDirectiveName(DKind, OMPVersion)
9534 << getOpenMPClauseNameForDiag(PredeterminedCKind);
9535 if (DVar.RefExpr == nullptr)
9536 DVar.CKind = PredeterminedCKind;
9537 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
9538 } else if (LoopDeclRefExpr) {
9539 // Make the loop iteration variable private (for worksharing
9540 // constructs), linear (for simd directives with the only one
9541 // associated loop) or lastprivate (for simd directives with several
9542 // collapsed or ordered loops).
9543 if (DVar.CKind == OMPC_unknown)
9544 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9545 }
9546 }
9547 }
9548 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9549}
9550
9551namespace {
9552// Utility for OpenMP doacross clause kind
9553class OMPDoacrossKind {
9554public:
9555 bool isSource(const OMPDoacrossClause *C) {
9556 return C->getDependenceType() == OMPC_DOACROSS_source ||
9557 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9558 }
9559 bool isSink(const OMPDoacrossClause *C) {
9560 return C->getDependenceType() == OMPC_DOACROSS_sink;
9561 }
9562 bool isSinkIter(const OMPDoacrossClause *C) {
9563 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9564 }
9565};
9566} // namespace
9567/// Called on a for stmt to check and extract its iteration space
9568/// for further processing (such as collapsing).
9570 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9571 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9572 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9573 Expr *OrderedLoopCountExpr,
9574 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9576 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9577 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls,
9578 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars) {
9579 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9580 // OpenMP [2.9.1, Canonical Loop Form]
9581 // for (init-expr; test-expr; incr-expr) structured-block
9582 // for (range-decl: range-expr) structured-block
9583 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9584 S = CanonLoop->getLoopStmt();
9585 auto *For = dyn_cast_or_null<ForStmt>(S);
9586 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9587 // Ranged for is supported only in OpenMP 5.0.
9588 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9589 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
9590 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9591 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9592 << getOpenMPDirectiveName(DKind, OMPVersion) << TotalNestedLoopCount
9593 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9594 if (TotalNestedLoopCount > 1) {
9595 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9596 SemaRef.Diag(DSA.getConstructLoc(),
9597 diag::note_omp_collapse_ordered_expr)
9598 << 2 << CollapseLoopCountExpr->getSourceRange()
9599 << OrderedLoopCountExpr->getSourceRange();
9600 else if (CollapseLoopCountExpr)
9601 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9602 diag::note_omp_collapse_ordered_expr)
9603 << 0 << CollapseLoopCountExpr->getSourceRange();
9604 else if (OrderedLoopCountExpr)
9605 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9606 diag::note_omp_collapse_ordered_expr)
9607 << 1 << OrderedLoopCountExpr->getSourceRange();
9608 }
9609 return true;
9610 }
9611 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9612 "No loop body.");
9613 // Postpone analysis in dependent contexts for ranged for loops.
9614 if (CXXFor && SemaRef.CurContext->isDependentContext())
9615 return false;
9616
9617 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9618 For ? For->getForLoc() : CXXFor->getForLoc(),
9619 CollapsedLoopVarDecls,
9620 CollapsedLoopInductionVars);
9621
9622 // Check init.
9623 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9624 if (ISC.checkAndSetInit(Init))
9625 return true;
9626
9627 bool HasErrors = false;
9628
9629 // Check loop variable's type.
9630 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9631 // OpenMP [2.6, Canonical Loop Form]
9632 // Var is one of the following:
9633 // A variable of signed or unsigned integer type.
9634 // For C++, a variable of a random access iterator type.
9635 // For C, a variable of a pointer type.
9636 QualType VarType = LCDecl->getType().getNonReferenceType();
9637 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9638 !VarType->isPointerType() &&
9639 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9640 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9641 << SemaRef.getLangOpts().CPlusPlus;
9642 HasErrors = true;
9643 }
9644
9645 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9646 // a Construct
9647 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9648 // parallel for construct is (are) private.
9649 // The loop iteration variable in the associated for-loop of a simd
9650 // construct with just one associated for-loop is linear with a
9651 // constant-linear-step that is the increment of the associated for-loop.
9652 // Exclude loop var from the list of variables with implicitly defined data
9653 // sharing attributes.
9654 VarsWithImplicitDSA.erase(LCDecl);
9655
9656 assert((isOpenMPLoopDirective(DKind) ||
9658 "DSA for non-loop vars");
9659
9660 // Check test-expr.
9661 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9662
9663 // Check incr-expr.
9664 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9665 }
9666
9667 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9668 return HasErrors;
9669
9670 // Build the loop's iteration space representation.
9671 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9672 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9673 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9674 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9680 Captures);
9681 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9682 ISC.buildCounterVar(Captures, DSA);
9683 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9684 ISC.buildPrivateCounterVar();
9685 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9686 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9687 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9688 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9689 ISC.getConditionSrcRange();
9690 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9691 ISC.getIncrementSrcRange();
9692 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9693 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9694 ISC.isStrictTestOp();
9695 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9696 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9697 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9698 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9699 ISC.buildFinalCondition(DSA.getCurScope());
9700 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9701 ISC.doesInitDependOnLC();
9702 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9703 ISC.doesCondDependOnLC();
9704 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9705 ISC.getLoopDependentIdx();
9706
9707 HasErrors |=
9708 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9709 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9710 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9711 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9712 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9713 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9714 if (!HasErrors && DSA.isOrderedRegion()) {
9715 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9716 if (CurrentNestedLoopCount <
9717 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9718 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9719 CurrentNestedLoopCount,
9720 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9721 DSA.getOrderedRegionParam().second->setLoopCounter(
9722 CurrentNestedLoopCount,
9723 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9724 }
9725 }
9726 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9727 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9728 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9729 unsigned NumLoops =
9730 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9731 if (CurrentNestedLoopCount >= NumLoops) {
9732 // Erroneous case - clause has some problems.
9733 continue;
9734 }
9735 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9736 Pair.second.size() <= CurrentNestedLoopCount) {
9737 // Erroneous case - clause has some problems.
9738 DependC->setLoopData(CurrentNestedLoopCount, nullptr);
9739 continue;
9740 }
9741 OMPDoacrossKind ODK;
9742 if (DoacrossC && ODK.isSink(DoacrossC) &&
9743 Pair.second.size() <= CurrentNestedLoopCount) {
9744 // Erroneous case - clause has some problems.
9745 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
9746 continue;
9747 }
9748 Expr *CntValue;
9749 SourceLocation DepLoc =
9750 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9751 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9752 (DoacrossC && ODK.isSource(DoacrossC)))
9753 CntValue = ISC.buildOrderedLoopData(
9754 DSA.getCurScope(),
9755 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9756 DepLoc);
9757 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9758 Expr *Cnt = SemaRef
9760 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9761 .get();
9762 if (!Cnt)
9763 continue;
9764 // build CounterVar - 1
9765 Expr *Inc =
9766 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
9767 .get();
9768 CntValue = ISC.buildOrderedLoopData(
9769 DSA.getCurScope(),
9770 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9771 DepLoc, Inc, clang::OO_Minus);
9772 } else
9773 CntValue = ISC.buildOrderedLoopData(
9774 DSA.getCurScope(),
9775 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9776 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9777 Pair.second[CurrentNestedLoopCount].second);
9778 if (DependC)
9779 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9780 else
9781 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9782 }
9783 }
9784 // Record the loop induction variable for nested loop reuse checking.
9785 if (CurrentNestedLoopCount < NestedLoopCount && !HasErrors) {
9786 if (const ValueDecl *LCDecl = ISC.getLoopDecl())
9787 CollapsedLoopInductionVars.insert(LCDecl->getCanonicalDecl());
9788 }
9789 return HasErrors;
9790}
9791
9792/// Build 'VarRef = Start.
9793static ExprResult
9795 ExprResult Start, bool IsNonRectangularLB,
9796 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9797 // Build 'VarRef = Start.
9798 ExprResult NewStart = IsNonRectangularLB
9799 ? Start.get()
9800 : tryBuildCapture(SemaRef, Start.get(), Captures);
9801 if (!NewStart.isUsable())
9802 return ExprError();
9803 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9804 VarRef.get()->getType())) {
9805 NewStart = SemaRef.PerformImplicitConversion(
9806 NewStart.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9807 /*AllowExplicit=*/true);
9808 if (!NewStart.isUsable())
9809 return ExprError();
9810 }
9811
9813 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9814 return Init;
9815}
9816
9817/// Build 'VarRef = Start + Iter * Step'.
9819 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9820 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9821 bool IsNonRectangularLB,
9822 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9823 // Add parentheses (for debugging purposes only).
9824 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9825 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9826 !Step.isUsable())
9827 return ExprError();
9828
9829 ExprResult NewStep = Step;
9830 if (Captures)
9831 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9832 if (NewStep.isInvalid())
9833 return ExprError();
9835 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9836 if (!Update.isUsable())
9837 return ExprError();
9838
9839 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9840 // 'VarRef = Start (+|-) Iter * Step'.
9841 if (!Start.isUsable())
9842 return ExprError();
9843 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9844 if (!NewStart.isUsable())
9845 return ExprError();
9846 if (Captures && !IsNonRectangularLB)
9847 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9848 if (NewStart.isInvalid())
9849 return ExprError();
9850
9851 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9852 ExprResult SavedUpdate = Update;
9853 ExprResult UpdateVal;
9854 if (VarRef.get()->getType()->isOverloadableType() ||
9855 NewStart.get()->getType()->isOverloadableType() ||
9856 Update.get()->getType()->isOverloadableType()) {
9857 Sema::TentativeAnalysisScope Trap(SemaRef);
9858
9859 Update =
9860 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9861 if (Update.isUsable()) {
9862 UpdateVal =
9863 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9864 VarRef.get(), SavedUpdate.get());
9865 if (UpdateVal.isUsable()) {
9866 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9867 UpdateVal.get());
9868 }
9869 }
9870 }
9871
9872 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9873 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9874 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9875 NewStart.get(), SavedUpdate.get());
9876 if (!Update.isUsable())
9877 return ExprError();
9878
9879 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9880 VarRef.get()->getType())) {
9882 Update.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9883 /*AllowExplicit=*/true);
9884 if (!Update.isUsable())
9885 return ExprError();
9886 }
9887
9888 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9889 }
9890 return Update;
9891}
9892
9893/// Convert integer expression \a E to make it have at least \a Bits
9894/// bits.
9895static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9896 if (E == nullptr)
9897 return ExprError();
9898 ASTContext &C = SemaRef.Context;
9899 QualType OldType = E->getType();
9900 unsigned HasBits = C.getTypeSize(OldType);
9901 if (HasBits >= Bits)
9902 return ExprResult(E);
9903 // OK to convert to signed, because new type has more bits than old.
9904 QualType NewType = C.getIntTypeForBitwidth(Bits, /*Signed=*/true);
9905 return SemaRef.PerformImplicitConversion(
9906 E, NewType, AssignmentAction::Converting, /*AllowExplicit=*/true);
9907}
9908
9909/// Check if the given expression \a E is a constant integer that fits
9910/// into \a Bits bits.
9911static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9912 if (E == nullptr)
9913 return false;
9914 if (std::optional<llvm::APSInt> Result =
9915 E->getIntegerConstantExpr(SemaRef.Context))
9916 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9917 return false;
9918}
9919
9920/// Build preinits statement for the given declarations.
9922 MutableArrayRef<Decl *> PreInits) {
9923 if (!PreInits.empty()) {
9924 return new (Context) DeclStmt(
9925 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9927 }
9928 return nullptr;
9929}
9930
9931/// Append the \p Item or the content of a CompoundStmt to the list \p
9932/// TargetList.
9933///
9934/// A CompoundStmt is used as container in case multiple statements need to be
9935/// stored in lieu of using an explicit list. Flattening is necessary because
9936/// contained DeclStmts need to be visible after the execution of the list. Used
9937/// for OpenMP pre-init declarations/statements.
9939 Stmt *Item) {
9940 // nullptr represents an empty list.
9941 if (!Item)
9942 return;
9943
9944 if (auto *CS = dyn_cast<CompoundStmt>(Item))
9945 llvm::append_range(TargetList, CS->body());
9946 else
9947 TargetList.push_back(Item);
9948}
9949
9950/// Build preinits statement for the given declarations.
9951static Stmt *
9953 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9954 if (!Captures.empty()) {
9955 SmallVector<Decl *, 16> PreInits;
9956 for (const auto &Pair : Captures)
9957 PreInits.push_back(Pair.second->getDecl());
9958 return buildPreInits(Context, PreInits);
9959 }
9960 return nullptr;
9961}
9962
9963/// Build pre-init statement for the given statements.
9964static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
9965 if (PreInits.empty())
9966 return nullptr;
9967
9968 SmallVector<Stmt *> Stmts;
9969 for (Stmt *S : PreInits)
9970 appendFlattenedStmtList(Stmts, S);
9971 return CompoundStmt::Create(Context, PreInits, FPOptionsOverride(), {}, {});
9972}
9973
9974/// Build postupdate expression for the given list of postupdates expressions.
9975static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9976 Expr *PostUpdate = nullptr;
9977 if (!PostUpdates.empty()) {
9978 for (Expr *E : PostUpdates) {
9979 Expr *ConvE = S.BuildCStyleCastExpr(
9980 E->getExprLoc(),
9982 E->getExprLoc(), E)
9983 .get();
9984 PostUpdate = PostUpdate
9985 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9986 PostUpdate, ConvE)
9987 .get()
9988 : ConvE;
9989 }
9990 }
9991 return PostUpdate;
9992}
9993
9994/// Look for variables declared in the body parts of a for-loop nest. Used
9995/// for verifying loop nest structure before performing a loop collapse
9996/// operation.
9998 int NestingDepth = 0;
9999 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
10000
10001public:
10002 explicit ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl *> &VD)
10003 : VarDecls(VD) {}
10004
10005 bool VisitForStmt(ForStmt *F) override {
10006 ++NestingDepth;
10007 TraverseStmt(F->getBody());
10008 --NestingDepth;
10009 return false;
10010 }
10011
10013 ++NestingDepth;
10014 TraverseStmt(RF->getBody());
10015 --NestingDepth;
10016 return false;
10017 }
10018
10019 bool VisitVarDecl(VarDecl *D) override {
10020 Decl *C = D->getCanonicalDecl();
10021 if (NestingDepth > 0)
10022 VarDecls.insert(C);
10023 return true;
10024 }
10025};
10026
10027/// Called on a for stmt to check itself and nested loops (if any).
10028/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
10029/// number of collapsed loops otherwise.
10030static unsigned
10031checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
10032 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
10033 DSAStackTy &DSA,
10034 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
10035 OMPLoopBasedDirective::HelperExprs &Built) {
10036 // If either of the loop expressions exist and contain errors, we bail out
10037 // early because diagnostics have already been emitted and we can't reliably
10038 // check more about the loop.
10039 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->containsErrors()) ||
10040 (OrderedLoopCountExpr && OrderedLoopCountExpr->containsErrors()))
10041 return 0;
10042
10043 unsigned NestedLoopCount = 1;
10044 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
10046 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopVarDecls;
10047 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopInductionVars;
10048
10049 if (CollapseLoopCountExpr) {
10050 // Found 'collapse' clause - calculate collapse number.
10052 if (!CollapseLoopCountExpr->isValueDependent() &&
10053 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
10054 NestedLoopCount = Result.Val.getInt().getLimitedValue();
10055
10056 ForVarDeclFinder FVDF{CollapsedLoopVarDecls};
10057 FVDF.TraverseStmt(AStmt);
10058 } else {
10059 Built.clear(/*Size=*/1);
10060 return 1;
10061 }
10062 }
10063 unsigned OrderedLoopCount = 1;
10064 if (OrderedLoopCountExpr) {
10065 // Found 'ordered' clause - calculate collapse number.
10066 Expr::EvalResult EVResult;
10067 if (!OrderedLoopCountExpr->isValueDependent() &&
10068 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
10069 SemaRef.getASTContext())) {
10070 llvm::APSInt Result = EVResult.Val.getInt();
10071 if (Result.getLimitedValue() < NestedLoopCount) {
10072 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
10073 diag::err_omp_wrong_ordered_loop_count)
10074 << OrderedLoopCountExpr->getSourceRange();
10075 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
10076 diag::note_collapse_loop_count)
10077 << CollapseLoopCountExpr->getSourceRange();
10078 }
10079 OrderedLoopCount = Result.getLimitedValue();
10080 } else {
10081 Built.clear(/*Size=*/1);
10082 return 1;
10083 }
10084 }
10085 // This is helper routine for loop directives (e.g., 'for', 'simd',
10086 // 'for simd', etc.).
10087 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
10088 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
10089 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
10090 if (!OMPLoopBasedDirective::doForAllLoops(
10091 AStmt->IgnoreContainers(
10093 SupportsNonPerfectlyNested, NumLoops,
10094 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
10095 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
10096 &IterSpaces, &Captures, &CollapsedLoopVarDecls,
10097 &CollapsedLoopInductionVars](unsigned Cnt, Stmt *CurStmt) {
10099 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
10100 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
10101 VarsWithImplicitDSA, IterSpaces, Captures,
10102 CollapsedLoopVarDecls, CollapsedLoopInductionVars))
10103 return true;
10104 if (Cnt > 0 && Cnt >= NestedLoopCount &&
10105 IterSpaces[Cnt].CounterVar) {
10106 // Handle initialization of captured loop iterator variables.
10107 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
10108 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
10109 Captures[DRE] = DRE;
10110 }
10111 }
10112 return false;
10113 },
10114 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
10115 Stmt *DependentPreInits = Transform->getPreInits();
10116 if (!DependentPreInits)
10117 return;
10118
10119 // Search for pre-init declared variables that need to be captured
10120 // to be referenceable inside the directive.
10121 SmallVector<Stmt *> Constituents;
10122 appendFlattenedStmtList(Constituents, DependentPreInits);
10123 for (Stmt *S : Constituents) {
10124 if (auto *DC = dyn_cast<DeclStmt>(S)) {
10125 for (Decl *C : DC->decls()) {
10126 auto *D = cast<VarDecl>(C);
10128 SemaRef, D, D->getType().getNonReferenceType(),
10129 cast<OMPExecutableDirective>(Transform->getDirective())
10130 ->getBeginLoc());
10131 Captures[Ref] = Ref;
10132 }
10133 }
10134 }
10135 }))
10136 return 0;
10137
10138 Built.clear(/*size=*/NestedLoopCount);
10139
10140 if (SemaRef.CurContext->isDependentContext())
10141 return NestedLoopCount;
10142
10143 // An example of what is generated for the following code:
10144 //
10145 // #pragma omp simd collapse(2) ordered(2)
10146 // for (i = 0; i < NI; ++i)
10147 // for (k = 0; k < NK; ++k)
10148 // for (j = J0; j < NJ; j+=2) {
10149 // <loop body>
10150 // }
10151 //
10152 // We generate the code below.
10153 // Note: the loop body may be outlined in CodeGen.
10154 // Note: some counters may be C++ classes, operator- is used to find number of
10155 // iterations and operator+= to calculate counter value.
10156 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
10157 // or i64 is currently supported).
10158 //
10159 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
10160 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
10161 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
10162 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
10163 // // similar updates for vars in clauses (e.g. 'linear')
10164 // <loop body (using local i and j)>
10165 // }
10166 // i = NI; // assign final values of counters
10167 // j = NJ;
10168 //
10169
10170 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
10171 // the iteration counts of the collapsed for loops.
10172 // Precondition tests if there is at least one iteration (all conditions are
10173 // true).
10174 auto PreCond = ExprResult(IterSpaces[0].PreCond);
10175 Expr *N0 = IterSpaces[0].NumIterations;
10176 ExprResult LastIteration32 = widenIterationCount(
10177 /*Bits=*/32,
10178 SemaRef
10179 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
10181 /*AllowExplicit=*/true)
10182 .get(),
10183 SemaRef);
10184 ExprResult LastIteration64 = widenIterationCount(
10185 /*Bits=*/64,
10186 SemaRef
10187 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
10189 /*AllowExplicit=*/true)
10190 .get(),
10191 SemaRef);
10192
10193 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
10194 return NestedLoopCount;
10195
10196 ASTContext &C = SemaRef.Context;
10197 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
10198
10199 Scope *CurScope = DSA.getCurScope();
10200 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
10201 if (PreCond.isUsable()) {
10202 PreCond =
10203 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
10204 PreCond.get(), IterSpaces[Cnt].PreCond);
10205 }
10206 Expr *N = IterSpaces[Cnt].NumIterations;
10207 SourceLocation Loc = N->getExprLoc();
10208 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
10209 if (LastIteration32.isUsable())
10210 LastIteration32 = SemaRef.BuildBinOp(
10211 CurScope, Loc, BO_Mul, LastIteration32.get(),
10212 SemaRef
10215 /*AllowExplicit=*/true)
10216 .get());
10217 if (LastIteration64.isUsable())
10218 LastIteration64 = SemaRef.BuildBinOp(
10219 CurScope, Loc, BO_Mul, LastIteration64.get(),
10220 SemaRef
10223 /*AllowExplicit=*/true)
10224 .get());
10225 }
10226
10227 // Choose either the 32-bit or 64-bit version.
10228 ExprResult LastIteration = LastIteration64;
10229 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
10230 (LastIteration32.isUsable() &&
10231 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
10232 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
10233 fitsInto(
10234 /*Bits=*/32,
10235 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
10236 LastIteration64.get(), SemaRef))))
10237 LastIteration = LastIteration32;
10238 QualType VType = LastIteration.get()->getType();
10239 QualType RealVType = VType;
10240 QualType StrideVType = VType;
10241 if (isOpenMPTaskLoopDirective(DKind)) {
10242 VType =
10243 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
10244 StrideVType =
10245 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
10246 }
10247
10248 if (!LastIteration.isUsable())
10249 return 0;
10250
10251 // Save the number of iterations.
10252 ExprResult NumIterations = LastIteration;
10253 {
10254 LastIteration = SemaRef.BuildBinOp(
10255 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
10256 LastIteration.get(),
10257 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
10258 if (!LastIteration.isUsable())
10259 return 0;
10260 }
10261
10262 // Calculate the last iteration number beforehand instead of doing this on
10263 // each iteration. Do not do this if the number of iterations may be kfold-ed.
10264 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
10265 ExprResult CalcLastIteration;
10266 if (!IsConstant) {
10267 ExprResult SaveRef =
10268 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
10269 LastIteration = SaveRef;
10270
10271 // Prepare SaveRef + 1.
10272 NumIterations = SemaRef.BuildBinOp(
10273 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
10274 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
10275 if (!NumIterations.isUsable())
10276 return 0;
10277 }
10278
10279 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
10280
10281 // Build variables passed into runtime, necessary for worksharing directives.
10282 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
10287 // Lower bound variable, initialized with zero.
10288 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
10289 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
10290 SemaRef.AddInitializerToDecl(LBDecl,
10291 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10292 /*DirectInit=*/false);
10293
10294 // Upper bound variable, initialized with last iteration number.
10295 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
10296 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
10297 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
10298 /*DirectInit=*/false);
10299
10300 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
10301 // This will be used to implement clause 'lastprivate'.
10302 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
10303 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
10304 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
10305 SemaRef.AddInitializerToDecl(ILDecl,
10306 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10307 /*DirectInit=*/false);
10308
10309 // Stride variable returned by runtime (we initialize it to 1 by default).
10310 VarDecl *STDecl =
10311 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
10312 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
10313 SemaRef.AddInitializerToDecl(STDecl,
10314 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
10315 /*DirectInit=*/false);
10316
10317 // Build expression: UB = min(UB, LastIteration)
10318 // It is necessary for CodeGen of directives with static scheduling.
10319 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
10320 UB.get(), LastIteration.get());
10321 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10322 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
10323 LastIteration.get(), UB.get());
10324 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
10325 CondOp.get());
10326 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue=*/false);
10327
10328 // If we have a combined directive that combines 'distribute', 'for' or
10329 // 'simd' we need to be able to access the bounds of the schedule of the
10330 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
10331 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
10333 // Lower bound variable, initialized with zero.
10334 VarDecl *CombLBDecl =
10335 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
10336 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
10337 SemaRef.AddInitializerToDecl(
10338 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10339 /*DirectInit=*/false);
10340
10341 // Upper bound variable, initialized with last iteration number.
10342 VarDecl *CombUBDecl =
10343 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
10344 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
10345 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
10346 /*DirectInit=*/false);
10347
10348 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
10349 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
10350 ExprResult CombCondOp =
10351 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
10352 LastIteration.get(), CombUB.get());
10353 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
10354 CombCondOp.get());
10355 CombEUB =
10356 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue=*/false);
10357
10358 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
10359 // We expect to have at least 2 more parameters than the 'parallel'
10360 // directive does - the lower and upper bounds of the previous schedule.
10361 assert(CD->getNumParams() >= 4 &&
10362 "Unexpected number of parameters in loop combined directive");
10363
10364 // Set the proper type for the bounds given what we learned from the
10365 // enclosed loops.
10366 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
10367 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
10368
10369 // Previous lower and upper bounds are obtained from the region
10370 // parameters.
10371 PrevLB =
10372 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
10373 PrevUB =
10374 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
10375 }
10376 }
10377
10378 // Build the iteration variable and its initialization before loop.
10379 ExprResult IV;
10380 ExprResult Init, CombInit;
10381 {
10382 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
10383 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
10384 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
10389 ? LB.get()
10390 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10391 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
10392 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue=*/false);
10393
10395 Expr *CombRHS =
10400 ? CombLB.get()
10401 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10402 CombInit =
10403 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
10404 CombInit =
10405 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue=*/false);
10406 }
10407 }
10408
10409 bool UseStrictCompare =
10410 RealVType->hasUnsignedIntegerRepresentation() &&
10411 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
10412 return LIS.IsStrictCompare;
10413 });
10414 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10415 // unsigned IV)) for worksharing loops.
10416 SourceLocation CondLoc = AStmt->getBeginLoc();
10417 Expr *BoundUB = UB.get();
10418 if (UseStrictCompare) {
10419 BoundUB =
10420 SemaRef
10421 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10422 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10423 .get();
10424 BoundUB =
10425 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue=*/false).get();
10426 }
10432 ? SemaRef.BuildBinOp(CurScope, CondLoc,
10433 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
10434 BoundUB)
10435 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10436 NumIterations.get());
10437 ExprResult CombDistCond;
10439 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10440 NumIterations.get());
10441 }
10442
10443 ExprResult CombCond;
10445 Expr *BoundCombUB = CombUB.get();
10446 if (UseStrictCompare) {
10447 BoundCombUB =
10448 SemaRef
10449 .BuildBinOp(
10450 CurScope, CondLoc, BO_Add, BoundCombUB,
10451 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10452 .get();
10453 BoundCombUB =
10454 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue=*/false)
10455 .get();
10456 }
10457 CombCond =
10458 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10459 IV.get(), BoundCombUB);
10460 }
10461 // Loop increment (IV = IV + 1)
10462 SourceLocation IncLoc = AStmt->getBeginLoc();
10463 ExprResult Inc =
10464 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
10465 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
10466 if (!Inc.isUsable())
10467 return 0;
10468 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
10469 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue=*/false);
10470 if (!Inc.isUsable())
10471 return 0;
10472
10473 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10474 // Used for directives with static scheduling.
10475 // In combined construct, add combined version that use CombLB and CombUB
10476 // base variables for the update
10477 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10482 // LB + ST
10483 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
10484 if (!NextLB.isUsable())
10485 return 0;
10486 // LB = LB + ST
10487 NextLB =
10488 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
10489 NextLB =
10490 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue=*/false);
10491 if (!NextLB.isUsable())
10492 return 0;
10493 // UB + ST
10494 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
10495 if (!NextUB.isUsable())
10496 return 0;
10497 // UB = UB + ST
10498 NextUB =
10499 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
10500 NextUB =
10501 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue=*/false);
10502 if (!NextUB.isUsable())
10503 return 0;
10505 CombNextLB =
10506 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
10507 if (!NextLB.isUsable())
10508 return 0;
10509 // LB = LB + ST
10510 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
10511 CombNextLB.get());
10512 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
10513 /*DiscardedValue=*/false);
10514 if (!CombNextLB.isUsable())
10515 return 0;
10516 // UB + ST
10517 CombNextUB =
10518 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
10519 if (!CombNextUB.isUsable())
10520 return 0;
10521 // UB = UB + ST
10522 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
10523 CombNextUB.get());
10524 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
10525 /*DiscardedValue=*/false);
10526 if (!CombNextUB.isUsable())
10527 return 0;
10528 }
10529 }
10530
10531 // Create increment expression for distribute loop when combined in a same
10532 // directive with for as IV = IV + ST; ensure upper bound expression based
10533 // on PrevUB instead of NumIterations - used to implement 'for' when found
10534 // in combination with 'distribute', like in 'distribute parallel for'
10535 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10536 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10538 DistCond = SemaRef.BuildBinOp(
10539 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10540 assert(DistCond.isUsable() && "distribute cond expr was not built");
10541
10542 DistInc =
10543 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10544 assert(DistInc.isUsable() && "distribute inc expr was not built");
10545 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10546 DistInc.get());
10547 DistInc =
10548 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue=*/false);
10549 assert(DistInc.isUsable() && "distribute inc expr was not built");
10550
10551 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10552 // construct
10553 ExprResult NewPrevUB = PrevUB;
10554 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10555 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10556 PrevUB.get()->getType())) {
10557 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10558 DistEUBLoc,
10560 DistEUBLoc, NewPrevUB.get());
10561 if (!NewPrevUB.isUsable())
10562 return 0;
10563 }
10564 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10565 UB.get(), NewPrevUB.get());
10566 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10567 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10568 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10569 CondOp.get());
10570 PrevEUB =
10571 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue=*/false);
10572
10573 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10574 // parallel for is in combination with a distribute directive with
10575 // schedule(static, 1)
10576 Expr *BoundPrevUB = PrevUB.get();
10577 if (UseStrictCompare) {
10578 BoundPrevUB =
10579 SemaRef
10580 .BuildBinOp(
10581 CurScope, CondLoc, BO_Add, BoundPrevUB,
10582 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10583 .get();
10584 BoundPrevUB =
10585 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue=*/false)
10586 .get();
10587 }
10588 ParForInDistCond =
10589 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10590 IV.get(), BoundPrevUB);
10591 }
10592
10593 // Build updates and final values of the loop counters.
10594 bool HasErrors = false;
10595 Built.Counters.resize(NestedLoopCount);
10596 Built.Inits.resize(NestedLoopCount);
10597 Built.Updates.resize(NestedLoopCount);
10598 Built.Finals.resize(NestedLoopCount);
10599 Built.DependentCounters.resize(NestedLoopCount);
10600 Built.DependentInits.resize(NestedLoopCount);
10601 Built.FinalsConditions.resize(NestedLoopCount);
10602 {
10603 // We implement the following algorithm for obtaining the
10604 // original loop iteration variable values based on the
10605 // value of the collapsed loop iteration variable IV.
10606 //
10607 // Let n+1 be the number of collapsed loops in the nest.
10608 // Iteration variables (I0, I1, .... In)
10609 // Iteration counts (N0, N1, ... Nn)
10610 //
10611 // Acc = IV;
10612 //
10613 // To compute Ik for loop k, 0 <= k <= n, generate:
10614 // Prod = N(k+1) * N(k+2) * ... * Nn;
10615 // Ik = Acc / Prod;
10616 // Acc -= Ik * Prod;
10617 //
10618 ExprResult Acc = IV;
10619 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10620 LoopIterationSpace &IS = IterSpaces[Cnt];
10621 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10622 ExprResult Iter;
10623
10624 // Compute prod
10625 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10626 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10627 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10628 IterSpaces[K].NumIterations);
10629
10630 // Iter = Acc / Prod
10631 // If there is at least one more inner loop to avoid
10632 // multiplication by 1.
10633 if (Cnt + 1 < NestedLoopCount)
10634 Iter =
10635 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10636 else
10637 Iter = Acc;
10638 if (!Iter.isUsable()) {
10639 HasErrors = true;
10640 break;
10641 }
10642
10643 // Update Acc:
10644 // Acc -= Iter * Prod
10645 // Check if there is at least one more inner loop to avoid
10646 // multiplication by 1.
10647 if (Cnt + 1 < NestedLoopCount)
10648 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10649 Prod.get());
10650 else
10651 Prod = Iter;
10652 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10653
10654 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10655 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10656 DeclRefExpr *CounterVar = buildDeclRefExpr(
10657 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10658 /*RefersToCapture=*/true);
10660 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10661 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10662 if (!Init.isUsable()) {
10663 HasErrors = true;
10664 break;
10665 }
10667 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10668 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10669 if (!Update.isUsable()) {
10670 HasErrors = true;
10671 break;
10672 }
10673
10674 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10675 ExprResult Final =
10676 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10677 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10678 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10679 if (!Final.isUsable()) {
10680 HasErrors = true;
10681 break;
10682 }
10683
10684 if (!Update.isUsable() || !Final.isUsable()) {
10685 HasErrors = true;
10686 break;
10687 }
10688 // Save results
10689 Built.Counters[Cnt] = IS.CounterVar;
10690 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10691 Built.Inits[Cnt] = Init.get();
10692 Built.Updates[Cnt] = Update.get();
10693 Built.Finals[Cnt] = Final.get();
10694 Built.DependentCounters[Cnt] = nullptr;
10695 Built.DependentInits[Cnt] = nullptr;
10696 Built.FinalsConditions[Cnt] = nullptr;
10697 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10698 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10699 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10700 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10701 }
10702 }
10703 }
10704
10705 if (HasErrors)
10706 return 0;
10707
10708 // Save results
10709 Built.IterationVarRef = IV.get();
10710 Built.LastIteration = LastIteration.get();
10711 Built.NumIterations = NumIterations.get();
10712 Built.CalcLastIteration = SemaRef
10713 .ActOnFinishFullExpr(CalcLastIteration.get(),
10714 /*DiscardedValue=*/false)
10715 .get();
10716 Built.PreCond = PreCond.get();
10717 Built.PreInits = buildPreInits(C, Captures);
10718 Built.Cond = Cond.get();
10719 Built.Init = Init.get();
10720 Built.Inc = Inc.get();
10721 Built.LB = LB.get();
10722 Built.UB = UB.get();
10723 Built.IL = IL.get();
10724 Built.ST = ST.get();
10725 Built.EUB = EUB.get();
10726 Built.NLB = NextLB.get();
10727 Built.NUB = NextUB.get();
10728 Built.PrevLB = PrevLB.get();
10729 Built.PrevUB = PrevUB.get();
10730 Built.DistInc = DistInc.get();
10731 Built.PrevEUB = PrevEUB.get();
10732 Built.DistCombinedFields.LB = CombLB.get();
10733 Built.DistCombinedFields.UB = CombUB.get();
10734 Built.DistCombinedFields.EUB = CombEUB.get();
10735 Built.DistCombinedFields.Init = CombInit.get();
10736 Built.DistCombinedFields.Cond = CombCond.get();
10737 Built.DistCombinedFields.NLB = CombNextLB.get();
10738 Built.DistCombinedFields.NUB = CombNextUB.get();
10739 Built.DistCombinedFields.DistCond = CombDistCond.get();
10740 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10741
10742 return NestedLoopCount;
10743}
10744
10746 auto CollapseClauses =
10747 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10748 if (CollapseClauses.begin() != CollapseClauses.end())
10749 return (*CollapseClauses.begin())->getNumForLoops();
10750 return nullptr;
10751}
10752
10754 auto OrderedClauses =
10755 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10756 if (OrderedClauses.begin() != OrderedClauses.end())
10757 return (*OrderedClauses.begin())->getNumForLoops();
10758 return nullptr;
10759}
10760
10762 const ArrayRef<OMPClause *> Clauses) {
10763 const OMPSafelenClause *Safelen = nullptr;
10764 const OMPSimdlenClause *Simdlen = nullptr;
10765
10766 for (const OMPClause *Clause : Clauses) {
10767 if (Clause->getClauseKind() == OMPC_safelen)
10768 Safelen = cast<OMPSafelenClause>(Clause);
10769 else if (Clause->getClauseKind() == OMPC_simdlen)
10770 Simdlen = cast<OMPSimdlenClause>(Clause);
10771 if (Safelen && Simdlen)
10772 break;
10773 }
10774
10775 if (Simdlen && Safelen) {
10776 const Expr *SimdlenLength = Simdlen->getSimdlen();
10777 const Expr *SafelenLength = Safelen->getSafelen();
10778 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10779 SimdlenLength->isInstantiationDependent() ||
10780 SimdlenLength->containsUnexpandedParameterPack())
10781 return false;
10782 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10783 SafelenLength->isInstantiationDependent() ||
10784 SafelenLength->containsUnexpandedParameterPack())
10785 return false;
10786 Expr::EvalResult SimdlenResult, SafelenResult;
10787 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10788 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10789 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10790 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10791 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10792 // If both simdlen and safelen clauses are specified, the value of the
10793 // simdlen parameter must be less than or equal to the value of the safelen
10794 // parameter.
10795 if (SimdlenRes > SafelenRes) {
10796 S.Diag(SimdlenLength->getExprLoc(),
10797 diag::err_omp_wrong_simdlen_safelen_values)
10798 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10799 return true;
10800 }
10801 }
10802 return false;
10803}
10804
10806 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10807 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10808 if (!AStmt)
10809 return StmtError();
10810
10811 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_simd, AStmt);
10812
10813 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10814 OMPLoopBasedDirective::HelperExprs B;
10815 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10816 // define the nested loops number.
10817 unsigned NestedLoopCount = checkOpenMPLoop(
10818 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10819 CS, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10820 if (NestedLoopCount == 0)
10821 return StmtError();
10822
10823 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10824 return StmtError();
10825
10827 return StmtError();
10828
10829 auto *SimdDirective = OMPSimdDirective::Create(
10830 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10831 return SimdDirective;
10832}
10833
10835 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10836 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10837 if (!AStmt)
10838 return StmtError();
10839
10840 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10841 OMPLoopBasedDirective::HelperExprs B;
10842 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10843 // define the nested loops number.
10844 unsigned NestedLoopCount = checkOpenMPLoop(
10845 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10846 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10847 if (NestedLoopCount == 0)
10848 return StmtError();
10849
10850 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10851 return StmtError();
10852
10853 auto *ForDirective = OMPForDirective::Create(
10854 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10855 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10856 return ForDirective;
10857}
10858
10860 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10861 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10862 if (!AStmt)
10863 return StmtError();
10864
10865 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_for_simd, AStmt);
10866
10867 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10868 OMPLoopBasedDirective::HelperExprs B;
10869 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10870 // define the nested loops number.
10871 unsigned NestedLoopCount =
10872 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10873 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10874 VarsWithImplicitDSA, B);
10875 if (NestedLoopCount == 0)
10876 return StmtError();
10877
10878 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10879 return StmtError();
10880
10882 return StmtError();
10883
10884 return OMPForSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
10885 NestedLoopCount, Clauses, AStmt, B);
10886}
10887
10889 Stmt *AStmt, DSAStackTy *Stack) {
10890 if (!AStmt)
10891 return true;
10892
10893 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10894 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
10895 auto BaseStmt = AStmt;
10896 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10897 BaseStmt = CS->getCapturedStmt();
10898 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10899 auto S = C->children();
10900 if (S.begin() == S.end())
10901 return true;
10902 // All associated statements must be '#pragma omp section' except for
10903 // the first one.
10904 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10905 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10906 if (SectionStmt)
10907 SemaRef.Diag(SectionStmt->getBeginLoc(),
10908 diag::err_omp_sections_substmt_not_section)
10909 << getOpenMPDirectiveName(DKind, OMPVersion);
10910 return true;
10911 }
10912 cast<OMPSectionDirective>(SectionStmt)
10913 ->setHasCancel(Stack->isCancelRegion());
10914 }
10915 } else {
10916 SemaRef.Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10917 << getOpenMPDirectiveName(DKind, OMPVersion);
10918 return true;
10919 }
10920 return false;
10921}
10922
10925 Stmt *AStmt, SourceLocation StartLoc,
10926 SourceLocation EndLoc) {
10927 if (checkSectionsDirective(SemaRef, OMPD_sections, AStmt, DSAStack))
10928 return StmtError();
10929
10930 SemaRef.setFunctionHasBranchProtectedScope();
10931
10932 return OMPSectionsDirective::Create(
10933 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10934 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10935}
10936
10938 SourceLocation StartLoc,
10939 SourceLocation EndLoc) {
10940 if (!AStmt)
10941 return StmtError();
10942
10943 SemaRef.setFunctionHasBranchProtectedScope();
10944 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10945
10946 return OMPSectionDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt,
10947 DSAStack->isCancelRegion());
10948}
10949
10951 E = E->IgnoreParenCasts()->IgnoreImplicit();
10952 if (auto *CE = dyn_cast<CallExpr>(E))
10953 if (CE->getDirectCallee())
10954 return E;
10955 return nullptr;
10956}
10957
10960 Stmt *AStmt, SourceLocation StartLoc,
10961 SourceLocation EndLoc) {
10962 if (!AStmt)
10963 return StmtError();
10964
10965 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10966
10967 // 5.1 OpenMP
10968 // expression-stmt : an expression statement with one of the following forms:
10969 // expression = target-call ( [expression-list] );
10970 // target-call ( [expression-list] );
10971
10972 SourceLocation TargetCallLoc;
10973
10974 if (!SemaRef.CurContext->isDependentContext()) {
10975 Expr *TargetCall = nullptr;
10976
10977 auto *E = dyn_cast<Expr>(S);
10978 if (!E) {
10979 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10980 return StmtError();
10981 }
10982
10983 E = E->IgnoreParenCasts()->IgnoreImplicit();
10984
10985 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10986 if (BO->getOpcode() == BO_Assign)
10987 TargetCall = getDirectCallExpr(BO->getRHS());
10988 } else {
10989 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10990 if (COCE->getOperator() == OO_Equal)
10991 TargetCall = getDirectCallExpr(COCE->getArg(1));
10992 if (!TargetCall)
10993 TargetCall = getDirectCallExpr(E);
10994 }
10995 if (!TargetCall) {
10996 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10997 return StmtError();
10998 }
10999 TargetCallLoc = TargetCall->getExprLoc();
11000 }
11001
11002 SemaRef.setFunctionHasBranchProtectedScope();
11003
11004 return OMPDispatchDirective::Create(getASTContext(), StartLoc, EndLoc,
11005 Clauses, AStmt, TargetCallLoc);
11006}
11007
11010 DSAStackTy *Stack) {
11011 bool ErrorFound = false;
11012 for (OMPClause *C : Clauses) {
11013 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
11014 for (Expr *RefExpr : LPC->varlist()) {
11015 SourceLocation ELoc;
11016 SourceRange ERange;
11017 Expr *SimpleRefExpr = RefExpr;
11018 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
11019 if (ValueDecl *D = Res.first) {
11020 auto &&Info = Stack->isLoopControlVariable(D);
11021 if (!Info.first) {
11022 unsigned OMPVersion = S.getLangOpts().OpenMP;
11023 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
11024 << getOpenMPDirectiveName(K, OMPVersion);
11025 ErrorFound = true;
11026 }
11027 }
11028 }
11029 }
11030 }
11031 return ErrorFound;
11032}
11033
11035 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11036 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11037 if (!AStmt)
11038 return StmtError();
11039
11040 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11041 // A list item may not appear in a lastprivate clause unless it is the
11042 // loop iteration variable of a loop that is associated with the construct.
11043 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack))
11044 return StmtError();
11045
11046 setBranchProtectedScope(SemaRef, OMPD_loop, AStmt);
11047
11048 OMPLoopDirective::HelperExprs B;
11049 // In presence of clause 'collapse', it will define the nested loops number.
11050 unsigned NestedLoopCount = checkOpenMPLoop(
11051 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
11052 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
11053 if (NestedLoopCount == 0)
11054 return StmtError();
11055
11056 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11057 "omp loop exprs were not built");
11058
11059 return OMPGenericLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
11060 NestedLoopCount, Clauses, AStmt, B);
11061}
11062
11064 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11065 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11066 if (!AStmt)
11067 return StmtError();
11068
11069 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11070 // A list item may not appear in a lastprivate clause unless it is the
11071 // loop iteration variable of a loop that is associated with the construct.
11072 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack))
11073 return StmtError();
11074
11075 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_teams_loop, AStmt);
11076
11077 OMPLoopDirective::HelperExprs B;
11078 // In presence of clause 'collapse', it will define the nested loops number.
11079 unsigned NestedLoopCount =
11080 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
11081 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
11082 VarsWithImplicitDSA, B);
11083 if (NestedLoopCount == 0)
11084 return StmtError();
11085
11086 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11087 "omp loop exprs were not built");
11088
11089 DSAStack->setParentTeamsRegionLoc(StartLoc);
11090
11092 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11093}
11094
11096 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11097 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11098 if (!AStmt)
11099 return StmtError();
11100
11101 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11102 // A list item may not appear in a lastprivate clause unless it is the
11103 // loop iteration variable of a loop that is associated with the construct.
11104 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop,
11105 DSAStack))
11106 return StmtError();
11107
11108 CapturedStmt *CS =
11109 setBranchProtectedScope(SemaRef, OMPD_target_teams_loop, AStmt);
11110
11111 OMPLoopDirective::HelperExprs B;
11112 // In presence of clause 'collapse', it will define the nested loops number.
11113 unsigned NestedLoopCount =
11114 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
11115 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
11116 VarsWithImplicitDSA, B);
11117 if (NestedLoopCount == 0)
11118 return StmtError();
11119
11120 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11121 "omp loop exprs were not built");
11122
11124 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11126}
11127
11129 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11130 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11131 if (!AStmt)
11132 return StmtError();
11133
11134 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11135 // A list item may not appear in a lastprivate clause unless it is the
11136 // loop iteration variable of a loop that is associated with the construct.
11137 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_parallel_loop,
11138 DSAStack))
11139 return StmtError();
11140
11141 CapturedStmt *CS =
11142 setBranchProtectedScope(SemaRef, OMPD_parallel_loop, AStmt);
11143
11144 OMPLoopDirective::HelperExprs B;
11145 // In presence of clause 'collapse', it will define the nested loops number.
11146 unsigned NestedLoopCount =
11147 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
11148 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
11149 VarsWithImplicitDSA, B);
11150 if (NestedLoopCount == 0)
11151 return StmtError();
11152
11153 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11154 "omp loop exprs were not built");
11155
11157 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11158}
11159
11161 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11162 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11163 if (!AStmt)
11164 return StmtError();
11165
11166 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11167 // A list item may not appear in a lastprivate clause unless it is the
11168 // loop iteration variable of a loop that is associated with the construct.
11169 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_parallel_loop,
11170 DSAStack))
11171 return StmtError();
11172
11173 CapturedStmt *CS =
11174 setBranchProtectedScope(SemaRef, OMPD_target_parallel_loop, AStmt);
11175
11176 OMPLoopDirective::HelperExprs B;
11177 // In presence of clause 'collapse', it will define the nested loops number.
11178 unsigned NestedLoopCount =
11179 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
11180 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
11181 VarsWithImplicitDSA, B);
11182 if (NestedLoopCount == 0)
11183 return StmtError();
11184
11185 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11186 "omp loop exprs were not built");
11187
11189 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11190}
11191
11193 Stmt *AStmt,
11194 SourceLocation StartLoc,
11195 SourceLocation EndLoc) {
11196 if (!AStmt)
11197 return StmtError();
11198
11199 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11200
11201 SemaRef.setFunctionHasBranchProtectedScope();
11202
11203 // OpenMP [2.7.3, single Construct, Restrictions]
11204 // The copyprivate clause must not be used with the nowait clause.
11205 const OMPClause *Nowait = nullptr;
11206 const OMPClause *Copyprivate = nullptr;
11207 for (const OMPClause *Clause : Clauses) {
11208 if (Clause->getClauseKind() == OMPC_nowait)
11209 Nowait = Clause;
11210 else if (Clause->getClauseKind() == OMPC_copyprivate)
11211 Copyprivate = Clause;
11212 if (Copyprivate && Nowait) {
11213 Diag(Copyprivate->getBeginLoc(),
11214 diag::err_omp_single_copyprivate_with_nowait);
11215 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
11216 return StmtError();
11217 }
11218 }
11219
11220 return OMPSingleDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11221 AStmt);
11222}
11223
11225 SourceLocation StartLoc,
11226 SourceLocation EndLoc) {
11227 if (!AStmt)
11228 return StmtError();
11229
11230 SemaRef.setFunctionHasBranchProtectedScope();
11231
11232 return OMPMasterDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt);
11233}
11234
11236 Stmt *AStmt,
11237 SourceLocation StartLoc,
11238 SourceLocation EndLoc) {
11239 if (!AStmt)
11240 return StmtError();
11241
11242 SemaRef.setFunctionHasBranchProtectedScope();
11243
11244 return OMPMaskedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11245 AStmt);
11246}
11247
11249 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
11250 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
11251 if (!AStmt)
11252 return StmtError();
11253
11254 bool ErrorFound = false;
11255 llvm::APSInt Hint;
11256 SourceLocation HintLoc;
11257 bool DependentHint = false;
11258 for (const OMPClause *C : Clauses) {
11259 if (C->getClauseKind() == OMPC_hint) {
11260 if (!DirName.getName()) {
11261 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
11262 ErrorFound = true;
11263 }
11264 Expr *E = cast<OMPHintClause>(C)->getHint();
11265 if (E->isTypeDependent() || E->isValueDependent() ||
11267 DependentHint = true;
11268 } else {
11270 HintLoc = C->getBeginLoc();
11271 }
11272 }
11273 }
11274 if (ErrorFound)
11275 return StmtError();
11276 const auto Pair = DSAStack->getCriticalWithHint(DirName);
11277 if (Pair.first && DirName.getName() && !DependentHint) {
11278 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
11279 Diag(StartLoc, diag::err_omp_critical_with_hint);
11280 if (HintLoc.isValid())
11281 Diag(HintLoc, diag::note_omp_critical_hint_here)
11282 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
11283 else
11284 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
11285 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
11286 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
11287 << 1
11288 << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()),
11289 /*Radix=*/10, /*Signed=*/false);
11290 } else {
11291 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
11292 }
11293 }
11294 }
11295
11296 SemaRef.setFunctionHasBranchProtectedScope();
11297
11298 auto *Dir = OMPCriticalDirective::Create(getASTContext(), DirName, StartLoc,
11299 EndLoc, Clauses, AStmt);
11300 if (!Pair.first && DirName.getName() && !DependentHint)
11301 DSAStack->addCriticalWithHint(Dir, Hint);
11302 return Dir;
11303}
11304
11306 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11307 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11308 if (!AStmt)
11309 return StmtError();
11310
11311 setBranchProtectedScope(SemaRef, OMPD_parallel_for, AStmt);
11312
11313 OMPLoopBasedDirective::HelperExprs B;
11314 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11315 // define the nested loops number.
11316 unsigned NestedLoopCount =
11317 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
11318 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
11319 VarsWithImplicitDSA, B);
11320 if (NestedLoopCount == 0)
11321 return StmtError();
11322
11323 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11324 return StmtError();
11325
11326 return OMPParallelForDirective::Create(
11327 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11328 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11329}
11330
11332 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11333 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11334 if (!AStmt)
11335 return StmtError();
11336
11337 CapturedStmt *CS =
11338 setBranchProtectedScope(SemaRef, OMPD_parallel_for_simd, AStmt);
11339
11340 OMPLoopBasedDirective::HelperExprs B;
11341 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11342 // define the nested loops number.
11343 unsigned NestedLoopCount =
11344 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
11345 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
11346 VarsWithImplicitDSA, B);
11347 if (NestedLoopCount == 0)
11348 return StmtError();
11349
11350 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11351 return StmtError();
11352
11354 return StmtError();
11355
11356 return OMPParallelForSimdDirective::Create(
11357 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11358}
11359
11361 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11362 SourceLocation EndLoc) {
11363 if (!AStmt)
11364 return StmtError();
11365
11366 setBranchProtectedScope(SemaRef, OMPD_parallel_master, AStmt);
11367
11368 return OMPParallelMasterDirective::Create(
11369 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11370 DSAStack->getTaskgroupReductionRef());
11371}
11372
11374 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11375 SourceLocation EndLoc) {
11376 if (!AStmt)
11377 return StmtError();
11378
11379 setBranchProtectedScope(SemaRef, OMPD_parallel_masked, AStmt);
11380
11381 return OMPParallelMaskedDirective::Create(
11382 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11383 DSAStack->getTaskgroupReductionRef());
11384}
11385
11387 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11388 SourceLocation EndLoc) {
11389 if (checkSectionsDirective(SemaRef, OMPD_parallel_sections, AStmt, DSAStack))
11390 return StmtError();
11391
11392 SemaRef.setFunctionHasBranchProtectedScope();
11393
11394 return OMPParallelSectionsDirective::Create(
11395 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11396 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11397}
11398
11399/// Find and diagnose mutually exclusive clause kinds.
11401 Sema &S, ArrayRef<OMPClause *> Clauses,
11402 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11403 const OMPClause *PrevClause = nullptr;
11404 bool ErrorFound = false;
11405 for (const OMPClause *C : Clauses) {
11406 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
11407 if (!PrevClause) {
11408 PrevClause = C;
11409 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11410 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11411 << getOpenMPClauseNameForDiag(C->getClauseKind())
11412 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11413 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
11414 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11415 ErrorFound = true;
11416 }
11417 }
11418 }
11419 return ErrorFound;
11420}
11421
11423 Stmt *AStmt,
11424 SourceLocation StartLoc,
11425 SourceLocation EndLoc) {
11426 if (!AStmt)
11427 return StmtError();
11428
11429 // OpenMP 5.0, 2.10.1 task Construct
11430 // If a detach clause appears on the directive, then a mergeable clause cannot
11431 // appear on the same directive.
11433 {OMPC_detach, OMPC_mergeable}))
11434 return StmtError();
11435
11436 setBranchProtectedScope(SemaRef, OMPD_task, AStmt);
11437
11438 return OMPTaskDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11439 AStmt, DSAStack->isCancelRegion());
11440}
11441
11443 SourceLocation EndLoc) {
11444 return OMPTaskyieldDirective::Create(getASTContext(), StartLoc, EndLoc);
11445}
11446
11448 SourceLocation EndLoc) {
11449 return OMPBarrierDirective::Create(getASTContext(), StartLoc, EndLoc);
11450}
11451
11453 SourceLocation StartLoc,
11454 SourceLocation EndLoc,
11455 bool InExContext) {
11456 const OMPAtClause *AtC =
11457 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11458
11459 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11460 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11461 return StmtError();
11462 }
11463
11464 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11465 const OMPSeverityClause *SeverityC =
11466 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11467 const OMPMessageClause *MessageC =
11468 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11469 std::optional<std::string> SL =
11470 MessageC ? MessageC->tryEvaluateString(getASTContext()) : std::nullopt;
11471
11472 if (MessageC && !SL)
11473 Diag(MessageC->getMessageString()->getBeginLoc(),
11474 diag::warn_clause_expected_string)
11475 << getOpenMPClauseNameForDiag(OMPC_message) << 1;
11476 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11477 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11478 << SL.value_or("WARNING");
11479 else
11480 Diag(StartLoc, diag::err_diagnose_if_succeeded) << SL.value_or("ERROR");
11481 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11482 return StmtError();
11483 }
11484
11485 return OMPErrorDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11486}
11487
11490 SourceLocation StartLoc,
11491 SourceLocation EndLoc) {
11492 const OMPNowaitClause *NowaitC =
11493 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11494 bool HasDependC =
11495 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11496 .empty();
11497 if (NowaitC && !HasDependC) {
11498 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11499 return StmtError();
11500 }
11501
11502 return OMPTaskwaitDirective::Create(getASTContext(), StartLoc, EndLoc,
11503 Clauses);
11504}
11505
11508 Stmt *AStmt, SourceLocation StartLoc,
11509 SourceLocation EndLoc) {
11510 if (!AStmt)
11511 return StmtError();
11512
11513 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11514
11515 SemaRef.setFunctionHasBranchProtectedScope();
11516
11517 return OMPTaskgroupDirective::Create(getASTContext(), StartLoc, EndLoc,
11518 Clauses, AStmt,
11519 DSAStack->getTaskgroupReductionRef());
11520}
11521
11523 SourceLocation StartLoc,
11524 SourceLocation EndLoc) {
11525 OMPFlushClause *FC = nullptr;
11526 OMPClause *OrderClause = nullptr;
11527 for (OMPClause *C : Clauses) {
11528 if (C->getClauseKind() == OMPC_flush)
11529 FC = cast<OMPFlushClause>(C);
11530 else
11531 OrderClause = C;
11532 }
11533 unsigned OMPVersion = getLangOpts().OpenMP;
11534 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11535 SourceLocation MemOrderLoc;
11536 for (const OMPClause *C : Clauses) {
11537 if (C->getClauseKind() == OMPC_acq_rel ||
11538 C->getClauseKind() == OMPC_acquire ||
11539 C->getClauseKind() == OMPC_release ||
11540 C->getClauseKind() == OMPC_seq_cst /*OpenMP 5.1*/) {
11541 if (MemOrderKind != OMPC_unknown) {
11542 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11543 << getOpenMPDirectiveName(OMPD_flush, OMPVersion) << 1
11544 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11545 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11546 << getOpenMPClauseNameForDiag(MemOrderKind);
11547 } else {
11548 MemOrderKind = C->getClauseKind();
11549 MemOrderLoc = C->getBeginLoc();
11550 }
11551 }
11552 }
11553 if (FC && OrderClause) {
11554 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11555 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11556 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11557 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11558 return StmtError();
11559 }
11560 return OMPFlushDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11561}
11562
11564 SourceLocation StartLoc,
11565 SourceLocation EndLoc) {
11566 if (Clauses.empty()) {
11567 Diag(StartLoc, diag::err_omp_depobj_expected);
11568 return StmtError();
11569 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11570 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11571 return StmtError();
11572 }
11573 // Only depobj expression and another single clause is allowed.
11574 if (Clauses.size() > 2) {
11575 Diag(Clauses[2]->getBeginLoc(),
11576 diag::err_omp_depobj_single_clause_expected);
11577 return StmtError();
11578 } else if (Clauses.size() < 1) {
11579 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11580 return StmtError();
11581 }
11582 return OMPDepobjDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11583}
11584
11586 SourceLocation StartLoc,
11587 SourceLocation EndLoc) {
11588 // Check that exactly one clause is specified.
11589 if (Clauses.size() != 1) {
11590 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11591 diag::err_omp_scan_single_clause_expected);
11592 return StmtError();
11593 }
11594 // Check that scan directive is used in the scope of the OpenMP loop body.
11595 if (Scope *S = DSAStack->getCurScope()) {
11596 Scope *ParentS = S->getParent();
11597 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11598 !ParentS->getBreakParent()->isOpenMPLoopScope()) {
11599 unsigned OMPVersion = getLangOpts().OpenMP;
11600 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11601 << getOpenMPDirectiveName(OMPD_scan, OMPVersion) << 5);
11602 }
11603 }
11604 // Check that only one instance of scan directives is used in the same outer
11605 // region.
11606 if (DSAStack->doesParentHasScanDirective()) {
11607 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11608 Diag(DSAStack->getParentScanDirectiveLoc(),
11609 diag::note_omp_previous_directive)
11610 << "scan";
11611 return StmtError();
11612 }
11613 DSAStack->setParentHasScanDirective(StartLoc);
11614 return OMPScanDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11615}
11616
11619 Stmt *AStmt, SourceLocation StartLoc,
11620 SourceLocation EndLoc) {
11621 const OMPClause *DependFound = nullptr;
11622 const OMPClause *DependSourceClause = nullptr;
11623 const OMPClause *DependSinkClause = nullptr;
11624 const OMPClause *DoacrossFound = nullptr;
11625 const OMPClause *DoacrossSourceClause = nullptr;
11626 const OMPClause *DoacrossSinkClause = nullptr;
11627 bool ErrorFound = false;
11628 const OMPThreadsClause *TC = nullptr;
11629 const OMPSIMDClause *SC = nullptr;
11630 for (const OMPClause *C : Clauses) {
11631 auto DOC = dyn_cast<OMPDoacrossClause>(C);
11632 auto DC = dyn_cast<OMPDependClause>(C);
11633 if (DC || DOC) {
11634 DependFound = DC ? C : nullptr;
11635 DoacrossFound = DOC ? C : nullptr;
11636 OMPDoacrossKind ODK;
11637 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11638 (DOC && (ODK.isSource(DOC)))) {
11639 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11640 unsigned OMPVersion = getLangOpts().OpenMP;
11641 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11642 << getOpenMPDirectiveName(OMPD_ordered, OMPVersion)
11643 << getOpenMPClauseNameForDiag(DC ? OMPC_depend : OMPC_doacross)
11644 << 2;
11645 ErrorFound = true;
11646 } else {
11647 if (DC)
11648 DependSourceClause = C;
11649 else
11650 DoacrossSourceClause = C;
11651 }
11652 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11653 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11654 << (DC ? "depend" : "doacross") << 0;
11655 ErrorFound = true;
11656 }
11657 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11658 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11659 if (DependSourceClause || DoacrossSourceClause) {
11660 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11661 << (DC ? "depend" : "doacross") << 1;
11662 ErrorFound = true;
11663 }
11664 if (DC)
11665 DependSinkClause = C;
11666 else
11667 DoacrossSinkClause = C;
11668 }
11669 } else if (C->getClauseKind() == OMPC_threads) {
11671 } else if (C->getClauseKind() == OMPC_simd) {
11672 SC = cast<OMPSIMDClause>(C);
11673 }
11674 }
11675 if (!ErrorFound && !SC &&
11676 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11677 // OpenMP [2.8.1,simd Construct, Restrictions]
11678 // An ordered construct with the simd clause is the only OpenMP construct
11679 // that can appear in the simd region.
11680 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11681 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11682 ErrorFound = true;
11683 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11684 SourceLocation Loc =
11685 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11686 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11687 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend : OMPC_doacross)
11688 << getOpenMPClauseNameForDiag(TC ? TC->getClauseKind()
11689 : SC->getClauseKind());
11690 ErrorFound = true;
11691 } else if ((DependFound || DoacrossFound) &&
11692 !DSAStack->getParentOrderedRegionParam().first) {
11693 SourceLocation Loc =
11694 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11695 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11696 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend
11697 : OMPC_doacross);
11698 ErrorFound = true;
11699 } else if (TC || Clauses.empty()) {
11700 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11701 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11702 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11703 << (TC != nullptr);
11704 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11705 ErrorFound = true;
11706 }
11707 }
11708 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11709 return StmtError();
11710
11711 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11712 // During execution of an iteration of a worksharing-loop or a loop nest
11713 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11714 // must not execute more than one ordered region corresponding to an ordered
11715 // construct without a depend clause.
11716 if (!DependFound && !DoacrossFound) {
11717 if (DSAStack->doesParentHasOrderedDirective()) {
11718 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11719 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11720 diag::note_omp_previous_directive)
11721 << "ordered";
11722 return StmtError();
11723 }
11724 DSAStack->setParentHasOrderedDirective(StartLoc);
11725 }
11726
11727 if (AStmt) {
11728 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11729
11730 SemaRef.setFunctionHasBranchProtectedScope();
11731 }
11732
11733 return OMPOrderedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11734 AStmt);
11735}
11736
11737namespace {
11738/// Helper class for checking expression in 'omp atomic [update]'
11739/// construct.
11740class OpenMPAtomicUpdateChecker {
11741 /// Error results for atomic update expressions.
11742 enum ExprAnalysisErrorCode {
11743 /// A statement is not an expression statement.
11744 NotAnExpression,
11745 /// Expression is not builtin binary or unary operation.
11746 NotABinaryOrUnaryExpression,
11747 /// Unary operation is not post-/pre- increment/decrement operation.
11748 NotAnUnaryIncDecExpression,
11749 /// An expression is not of scalar type.
11750 NotAScalarType,
11751 /// A binary operation is not an assignment operation.
11752 NotAnAssignmentOp,
11753 /// RHS part of the binary operation is not a binary expression.
11754 NotABinaryExpression,
11755 /// RHS part is not additive/multiplicative/shift/bitwise binary
11756 /// expression.
11757 NotABinaryOperator,
11758 /// RHS binary operation does not have reference to the updated LHS
11759 /// part.
11760 NotAnUpdateExpression,
11761 /// An expression contains semantical error not related to
11762 /// 'omp atomic [update]'
11763 NotAValidExpression,
11764 /// No errors is found.
11765 NoError
11766 };
11767 /// Reference to Sema.
11768 Sema &SemaRef;
11769 /// A location for note diagnostics (when error is found).
11770 SourceLocation NoteLoc;
11771 /// 'x' lvalue part of the source atomic expression.
11772 Expr *X;
11773 /// 'expr' rvalue part of the source atomic expression.
11774 Expr *E;
11775 /// Helper expression of the form
11776 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11777 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11778 Expr *UpdateExpr;
11779 /// Is 'x' a LHS in a RHS part of full update expression. It is
11780 /// important for non-associative operations.
11781 bool IsXLHSInRHSPart;
11783 SourceLocation OpLoc;
11784 /// true if the source expression is a postfix unary operation, false
11785 /// if it is a prefix unary operation.
11786 bool IsPostfixUpdate;
11787
11788public:
11789 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11790 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11791 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11792 /// Check specified statement that it is suitable for 'atomic update'
11793 /// constructs and extract 'x', 'expr' and Operation from the original
11794 /// expression. If DiagId and NoteId == 0, then only check is performed
11795 /// without error notification.
11796 /// \param DiagId Diagnostic which should be emitted if error is found.
11797 /// \param NoteId Diagnostic note for the main error message.
11798 /// \return true if statement is not an update expression, false otherwise.
11799 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11800 /// Return the 'x' lvalue part of the source atomic expression.
11801 Expr *getX() const { return X; }
11802 /// Return the 'expr' rvalue part of the source atomic expression.
11803 Expr *getExpr() const { return E; }
11804 /// Return the update expression used in calculation of the updated
11805 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11806 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11807 Expr *getUpdateExpr() const { return UpdateExpr; }
11808 /// Return true if 'x' is LHS in RHS part of full update expression,
11809 /// false otherwise.
11810 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11811
11812 /// true if the source expression is a postfix unary operation, false
11813 /// if it is a prefix unary operation.
11814 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11815
11816private:
11817 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11818 unsigned NoteId = 0);
11819};
11820
11821bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11822 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11823 ExprAnalysisErrorCode ErrorFound = NoError;
11824 SourceLocation ErrorLoc, NoteLoc;
11825 SourceRange ErrorRange, NoteRange;
11826 // Allowed constructs are:
11827 // x = x binop expr;
11828 // x = expr binop x;
11829 if (AtomicBinOp->getOpcode() == BO_Assign) {
11830 X = AtomicBinOp->getLHS();
11831 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11832 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11833 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11834 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11835 AtomicInnerBinOp->isBitwiseOp()) {
11836 Op = AtomicInnerBinOp->getOpcode();
11837 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11838 Expr *LHS = AtomicInnerBinOp->getLHS();
11839 Expr *RHS = AtomicInnerBinOp->getRHS();
11840 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11841 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11842 /*Canonical=*/true);
11843 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11844 /*Canonical=*/true);
11845 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11846 /*Canonical=*/true);
11847 if (XId == LHSId) {
11848 E = RHS;
11849 IsXLHSInRHSPart = true;
11850 } else if (XId == RHSId) {
11851 E = LHS;
11852 IsXLHSInRHSPart = false;
11853 } else {
11854 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11855 ErrorRange = AtomicInnerBinOp->getSourceRange();
11856 NoteLoc = X->getExprLoc();
11857 NoteRange = X->getSourceRange();
11858 ErrorFound = NotAnUpdateExpression;
11859 }
11860 } else {
11861 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11862 ErrorRange = AtomicInnerBinOp->getSourceRange();
11863 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11864 NoteRange = SourceRange(NoteLoc, NoteLoc);
11865 ErrorFound = NotABinaryOperator;
11866 }
11867 } else {
11868 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11869 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11870 ErrorFound = NotABinaryExpression;
11871 }
11872 } else {
11873 ErrorLoc = AtomicBinOp->getExprLoc();
11874 ErrorRange = AtomicBinOp->getSourceRange();
11875 NoteLoc = AtomicBinOp->getOperatorLoc();
11876 NoteRange = SourceRange(NoteLoc, NoteLoc);
11877 ErrorFound = NotAnAssignmentOp;
11878 }
11879 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11880 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11881 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11882 return true;
11883 }
11884 if (SemaRef.CurContext->isDependentContext())
11885 E = X = UpdateExpr = nullptr;
11886 return ErrorFound != NoError;
11887}
11888
11889bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11890 unsigned NoteId) {
11891 ExprAnalysisErrorCode ErrorFound = NoError;
11892 SourceLocation ErrorLoc, NoteLoc;
11893 SourceRange ErrorRange, NoteRange;
11894 // Allowed constructs are:
11895 // x++;
11896 // x--;
11897 // ++x;
11898 // --x;
11899 // x binop= expr;
11900 // x = x binop expr;
11901 // x = expr binop x;
11902 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11903 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11904 if (AtomicBody->getType()->isScalarType() ||
11905 AtomicBody->isInstantiationDependent()) {
11906 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11907 AtomicBody->IgnoreParenImpCasts())) {
11908 // Check for Compound Assignment Operation
11910 AtomicCompAssignOp->getOpcode());
11911 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11912 E = AtomicCompAssignOp->getRHS();
11913 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11914 IsXLHSInRHSPart = true;
11915 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11916 AtomicBody->IgnoreParenImpCasts())) {
11917 // Check for Binary Operation
11918 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11919 return true;
11920 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11921 AtomicBody->IgnoreParenImpCasts())) {
11922 // Check for Unary Operation
11923 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11924 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11925 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11926 OpLoc = AtomicUnaryOp->getOperatorLoc();
11927 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11928 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11929 IsXLHSInRHSPart = true;
11930 } else {
11931 ErrorFound = NotAnUnaryIncDecExpression;
11932 ErrorLoc = AtomicUnaryOp->getExprLoc();
11933 ErrorRange = AtomicUnaryOp->getSourceRange();
11934 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11935 NoteRange = SourceRange(NoteLoc, NoteLoc);
11936 }
11937 } else if (!AtomicBody->isInstantiationDependent()) {
11938 ErrorFound = NotABinaryOrUnaryExpression;
11939 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11940 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11941 } else if (AtomicBody->containsErrors()) {
11942 ErrorFound = NotAValidExpression;
11943 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11944 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11945 }
11946 } else {
11947 ErrorFound = NotAScalarType;
11948 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11949 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11950 }
11951 } else {
11952 ErrorFound = NotAnExpression;
11953 NoteLoc = ErrorLoc = S->getBeginLoc();
11954 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11955 }
11956 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11957 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11958 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11959 return true;
11960 }
11961 if (SemaRef.CurContext->isDependentContext())
11962 E = X = UpdateExpr = nullptr;
11963 if (ErrorFound == NoError && E && X) {
11964 // Build an update expression of form 'OpaqueValueExpr(x) binop
11965 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11966 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11967 auto *OVEX = new (SemaRef.getASTContext())
11968 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11969 auto *OVEExpr = new (SemaRef.getASTContext())
11972 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11973 IsXLHSInRHSPart ? OVEExpr : OVEX);
11974 if (Update.isInvalid())
11975 return true;
11976 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11978 if (Update.isInvalid())
11979 return true;
11980 UpdateExpr = Update.get();
11981 }
11982 return ErrorFound != NoError;
11983}
11984
11985/// Get the node id of the fixed point of an expression \a S.
11986llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11987 llvm::FoldingSetNodeID Id;
11988 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11989 return Id;
11990}
11991
11992/// Check if two expressions are same.
11993bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11994 const Expr *RHS) {
11995 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11996}
11997
11998class OpenMPAtomicCompareChecker {
11999public:
12000 /// All kinds of errors that can occur in `atomic compare`
12001 enum ErrorTy {
12002 /// Empty compound statement.
12003 NoStmt = 0,
12004 /// More than one statement in a compound statement.
12005 MoreThanOneStmt,
12006 /// Not an assignment binary operator.
12007 NotAnAssignment,
12008 /// Not a conditional operator.
12009 NotCondOp,
12010 /// Wrong false expr. According to the spec, 'x' should be at the false
12011 /// expression of a conditional expression.
12012 WrongFalseExpr,
12013 /// The condition of a conditional expression is not a binary operator.
12014 NotABinaryOp,
12015 /// Invalid binary operator (not <, >, or ==).
12016 InvalidBinaryOp,
12017 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
12018 InvalidComparison,
12019 /// X is not a lvalue.
12020 XNotLValue,
12021 /// Not a scalar.
12022 NotScalar,
12023 /// Not an integer.
12024 NotInteger,
12025 /// 'else' statement is not expected.
12026 UnexpectedElse,
12027 /// Not an equality operator.
12028 NotEQ,
12029 /// Invalid assignment (not v == x).
12030 InvalidAssignment,
12031 /// Not if statement
12032 NotIfStmt,
12033 /// More than two statements in a compound statement.
12034 MoreThanTwoStmts,
12035 /// Not a compound statement.
12036 NotCompoundStmt,
12037 /// No else statement.
12038 NoElse,
12039 /// Not 'if (r)'.
12040 InvalidCondition,
12041 /// No error.
12042 NoError,
12043 };
12044
12045 struct ErrorInfoTy {
12046 ErrorTy Error;
12047 SourceLocation ErrorLoc;
12048 SourceRange ErrorRange;
12049 SourceLocation NoteLoc;
12050 SourceRange NoteRange;
12051 };
12052
12053 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
12054
12055 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
12056 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12057
12058 Expr *getX() const { return X; }
12059 Expr *getE() const { return E; }
12060 Expr *getD() const { return D; }
12061 Expr *getCond() const { return C; }
12062 bool isXBinopExpr() const { return IsXBinopExpr; }
12063
12064protected:
12065 /// Reference to ASTContext
12066 ASTContext &ContextRef;
12067 /// 'x' lvalue part of the source atomic expression.
12068 Expr *X = nullptr;
12069 /// 'expr' or 'e' rvalue part of the source atomic expression.
12070 Expr *E = nullptr;
12071 /// 'd' rvalue part of the source atomic expression.
12072 Expr *D = nullptr;
12073 /// 'cond' part of the source atomic expression. It is in one of the following
12074 /// forms:
12075 /// expr ordop x
12076 /// x ordop expr
12077 /// x == e
12078 /// e == x
12079 Expr *C = nullptr;
12080 /// True if the cond expr is in the form of 'x ordop expr'.
12081 bool IsXBinopExpr = true;
12082
12083 /// Check if it is a valid conditional update statement (cond-update-stmt).
12084 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
12085
12086 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
12087 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12088
12089 /// Check if all captured values have right type.
12090 bool checkType(ErrorInfoTy &ErrorInfo) const;
12091
12092 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
12093 bool ShouldBeLValue, bool ShouldBeInteger = false) {
12094 if (E->isInstantiationDependent())
12095 return true;
12096
12097 if (ShouldBeLValue && !E->isLValue()) {
12098 ErrorInfo.Error = ErrorTy::XNotLValue;
12099 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12100 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12101 return false;
12102 }
12103
12104 QualType QTy = E->getType();
12105 if (!QTy->isScalarType()) {
12106 ErrorInfo.Error = ErrorTy::NotScalar;
12107 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12108 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12109 return false;
12110 }
12111 if (ShouldBeInteger && !QTy->isIntegerType()) {
12112 ErrorInfo.Error = ErrorTy::NotInteger;
12113 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12114 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12115 return false;
12116 }
12117
12118 return true;
12119 }
12120};
12121
12122bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
12123 ErrorInfoTy &ErrorInfo) {
12124 auto *Then = S->getThen();
12125 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12126 if (CS->body_empty()) {
12127 ErrorInfo.Error = ErrorTy::NoStmt;
12128 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12129 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12130 return false;
12131 }
12132 if (CS->size() > 1) {
12133 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12134 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12135 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12136 return false;
12137 }
12138 Then = CS->body_front();
12139 }
12140
12141 auto *BO = dyn_cast<BinaryOperator>(Then);
12142 if (!BO) {
12143 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12144 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12145 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12146 return false;
12147 }
12148 if (BO->getOpcode() != BO_Assign) {
12149 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12150 ErrorInfo.ErrorLoc = BO->getExprLoc();
12151 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12152 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12153 return false;
12154 }
12155
12156 X = BO->getLHS();
12157
12158 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12159 auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
12160 Expr *LHS = nullptr;
12161 Expr *RHS = nullptr;
12162 if (Cond) {
12163 LHS = Cond->getLHS();
12164 RHS = Cond->getRHS();
12165 } else if (Call) {
12166 LHS = Call->getArg(0);
12167 RHS = Call->getArg(1);
12168 } else {
12169 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12170 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12171 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12172 return false;
12173 }
12174
12175 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12176 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12177 C = S->getCond();
12178 D = BO->getRHS();
12179 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12180 E = RHS;
12181 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12182 E = LHS;
12183 } else {
12184 ErrorInfo.Error = ErrorTy::InvalidComparison;
12185 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12186 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12187 S->getCond()->getSourceRange();
12188 return false;
12189 }
12190 } else if ((Cond &&
12191 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12192 (Call &&
12193 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12194 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12195 E = BO->getRHS();
12196 if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
12197 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12198 C = S->getCond();
12199 } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12200 checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12201 C = S->getCond();
12202 IsXBinopExpr = false;
12203 } else {
12204 ErrorInfo.Error = ErrorTy::InvalidComparison;
12205 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12206 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12207 S->getCond()->getSourceRange();
12208 return false;
12209 }
12210 } else {
12211 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12212 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12213 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12214 return false;
12215 }
12216
12217 if (S->getElse()) {
12218 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12219 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
12220 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
12221 return false;
12222 }
12223
12224 return true;
12225}
12226
12227bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
12228 ErrorInfoTy &ErrorInfo) {
12229 auto *BO = dyn_cast<BinaryOperator>(S);
12230 if (!BO) {
12231 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12232 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12233 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12234 return false;
12235 }
12236 if (BO->getOpcode() != BO_Assign) {
12237 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12238 ErrorInfo.ErrorLoc = BO->getExprLoc();
12239 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12240 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12241 return false;
12242 }
12243
12244 X = BO->getLHS();
12245
12246 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
12247 if (!CO) {
12248 ErrorInfo.Error = ErrorTy::NotCondOp;
12249 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12250 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12251 return false;
12252 }
12253
12254 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
12255 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12256 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12257 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12258 CO->getFalseExpr()->getSourceRange();
12259 return false;
12260 }
12261
12262 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
12263 auto *Call = dyn_cast<CXXOperatorCallExpr>(CO->getCond());
12264 Expr *LHS = nullptr;
12265 Expr *RHS = nullptr;
12266 if (Cond) {
12267 LHS = Cond->getLHS();
12268 RHS = Cond->getRHS();
12269 } else if (Call) {
12270 LHS = Call->getArg(0);
12271 RHS = Call->getArg(1);
12272 } else {
12273 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12274 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12275 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12276 CO->getCond()->getSourceRange();
12277 return false;
12278 }
12279
12280 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12281 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12282 C = CO->getCond();
12283 D = CO->getTrueExpr();
12284 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12285 E = RHS;
12286 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12287 E = LHS;
12288 } else {
12289 ErrorInfo.Error = ErrorTy::InvalidComparison;
12290 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12291 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12292 CO->getCond()->getSourceRange();
12293 return false;
12294 }
12295 } else if ((Cond &&
12296 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12297 (Call &&
12298 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12299 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12300
12301 E = CO->getTrueExpr();
12302 if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
12303 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12304 C = CO->getCond();
12305 } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12306 checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12307 C = CO->getCond();
12308 IsXBinopExpr = false;
12309 } else {
12310 ErrorInfo.Error = ErrorTy::InvalidComparison;
12311 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12312 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12313 CO->getCond()->getSourceRange();
12314 return false;
12315 }
12316 } else {
12317 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12318 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12319 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12320 CO->getCond()->getSourceRange();
12321 return false;
12322 }
12323
12324 return true;
12325}
12326
12327bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
12328 // 'x' and 'e' cannot be nullptr
12329 assert(X && E && "X and E cannot be nullptr");
12330
12331 if (!CheckValue(X, ErrorInfo, true))
12332 return false;
12333
12334 if (!CheckValue(E, ErrorInfo, false))
12335 return false;
12336
12337 if (D && !CheckValue(D, ErrorInfo, false))
12338 return false;
12339
12340 return true;
12341}
12342
12343bool OpenMPAtomicCompareChecker::checkStmt(
12344 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12345 auto *CS = dyn_cast<CompoundStmt>(S);
12346 if (CS) {
12347 if (CS->body_empty()) {
12348 ErrorInfo.Error = ErrorTy::NoStmt;
12349 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12350 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12351 return false;
12352 }
12353
12354 if (CS->size() != 1) {
12355 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12356 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12357 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12358 return false;
12359 }
12360 S = CS->body_front();
12361 }
12362
12363 auto Res = false;
12364
12365 if (auto *IS = dyn_cast<IfStmt>(S)) {
12366 // Check if the statement is in one of the following forms
12367 // (cond-update-stmt):
12368 // if (expr ordop x) { x = expr; }
12369 // if (x ordop expr) { x = expr; }
12370 // if (x == e) { x = d; }
12371 Res = checkCondUpdateStmt(IS, ErrorInfo);
12372 } else {
12373 // Check if the statement is in one of the following forms (cond-expr-stmt):
12374 // x = expr ordop x ? expr : x;
12375 // x = x ordop expr ? expr : x;
12376 // x = x == e ? d : x;
12377 Res = checkCondExprStmt(S, ErrorInfo);
12378 }
12379
12380 if (!Res)
12381 return false;
12382
12383 return checkType(ErrorInfo);
12384}
12385
12386class OpenMPAtomicCompareCaptureChecker final
12387 : public OpenMPAtomicCompareChecker {
12388public:
12389 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12390
12391 Expr *getV() const { return V; }
12392 Expr *getR() const { return R; }
12393 bool isFailOnly() const { return IsFailOnly; }
12394 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12395
12396 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12397 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12398
12399private:
12400 bool checkType(ErrorInfoTy &ErrorInfo);
12401
12402 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12403 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12404 // spec p.p. 82:
12405 // (1) { v = x; cond-update-stmt }
12406 // (2) { cond-update-stmt v = x; }
12407 // (3) if(x == e) { x = d; } else { v = x; }
12408 // (4) { r = x == e; if(r) { x = d; } }
12409 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12410
12411 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12412 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12413
12414 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12415 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12416 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12417
12418 /// 'v' lvalue part of the source atomic expression.
12419 Expr *V = nullptr;
12420 /// 'r' lvalue part of the source atomic expression.
12421 Expr *R = nullptr;
12422 /// If 'v' is only updated when the comparison fails.
12423 bool IsFailOnly = false;
12424 /// If original value of 'x' must be stored in 'v', not an updated one.
12425 bool IsPostfixUpdate = false;
12426};
12427
12428bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12429 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12430 return false;
12431
12432 if (V && !CheckValue(V, ErrorInfo, true))
12433 return false;
12434
12435 if (R && !CheckValue(R, ErrorInfo, true, true))
12436 return false;
12437
12438 return true;
12439}
12440
12441bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12442 ErrorInfoTy &ErrorInfo) {
12443 IsFailOnly = true;
12444
12445 auto *Then = S->getThen();
12446 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12447 if (CS->body_empty()) {
12448 ErrorInfo.Error = ErrorTy::NoStmt;
12449 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12450 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12451 return false;
12452 }
12453 if (CS->size() > 1) {
12454 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12455 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12456 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12457 return false;
12458 }
12459 Then = CS->body_front();
12460 }
12461
12462 auto *BO = dyn_cast<BinaryOperator>(Then);
12463 if (!BO) {
12464 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12465 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12466 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12467 return false;
12468 }
12469 if (BO->getOpcode() != BO_Assign) {
12470 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12471 ErrorInfo.ErrorLoc = BO->getExprLoc();
12472 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12473 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12474 return false;
12475 }
12476
12477 X = BO->getLHS();
12478 D = BO->getRHS();
12479
12480 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12481 auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
12482 Expr *LHS = nullptr;
12483 Expr *RHS = nullptr;
12484 if (Cond) {
12485 LHS = Cond->getLHS();
12486 RHS = Cond->getRHS();
12487 } else if (Call) {
12488 LHS = Call->getArg(0);
12489 RHS = Call->getArg(1);
12490 } else {
12491 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12492 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12493 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12494 return false;
12495 }
12496 if ((Cond && Cond->getOpcode() != BO_EQ) ||
12497 (Call && Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12498 ErrorInfo.Error = ErrorTy::NotEQ;
12499 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12500 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12501 return false;
12502 }
12503
12504 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12505 E = RHS;
12506 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12507 E = LHS;
12508 } else {
12509 ErrorInfo.Error = ErrorTy::InvalidComparison;
12510 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12511 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12512 return false;
12513 }
12514
12515 C = S->getCond();
12516
12517 if (!S->getElse()) {
12518 ErrorInfo.Error = ErrorTy::NoElse;
12519 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12520 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12521 return false;
12522 }
12523
12524 auto *Else = S->getElse();
12525 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12526 if (CS->body_empty()) {
12527 ErrorInfo.Error = ErrorTy::NoStmt;
12528 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12529 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12530 return false;
12531 }
12532 if (CS->size() > 1) {
12533 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12534 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12535 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12536 return false;
12537 }
12538 Else = CS->body_front();
12539 }
12540
12541 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12542 if (!ElseBO) {
12543 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12544 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12545 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12546 return false;
12547 }
12548 if (ElseBO->getOpcode() != BO_Assign) {
12549 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12550 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12551 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12552 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12553 return false;
12554 }
12555
12556 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12557 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12558 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12559 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12560 ElseBO->getRHS()->getSourceRange();
12561 return false;
12562 }
12563
12564 V = ElseBO->getLHS();
12565
12566 return checkType(ErrorInfo);
12567}
12568
12569bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12570 ErrorInfoTy &ErrorInfo) {
12571 // We don't check here as they should be already done before call this
12572 // function.
12573 auto *CS = cast<CompoundStmt>(S);
12574 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12575 auto *S1 = cast<BinaryOperator>(CS->body_front());
12576 auto *S2 = cast<IfStmt>(CS->body_back());
12577 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12578
12579 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12580 ErrorInfo.Error = ErrorTy::InvalidCondition;
12581 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12582 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12583 return false;
12584 }
12585
12586 R = S1->getLHS();
12587
12588 auto *Then = S2->getThen();
12589 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12590 if (ThenCS->body_empty()) {
12591 ErrorInfo.Error = ErrorTy::NoStmt;
12592 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12593 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12594 return false;
12595 }
12596 if (ThenCS->size() > 1) {
12597 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12598 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12599 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12600 return false;
12601 }
12602 Then = ThenCS->body_front();
12603 }
12604
12605 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12606 if (!ThenBO) {
12607 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12608 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12609 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12610 return false;
12611 }
12612 if (ThenBO->getOpcode() != BO_Assign) {
12613 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12614 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12615 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12616 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12617 return false;
12618 }
12619
12620 X = ThenBO->getLHS();
12621 D = ThenBO->getRHS();
12622
12623 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12624 if (BO->getOpcode() != BO_EQ) {
12625 ErrorInfo.Error = ErrorTy::NotEQ;
12626 ErrorInfo.ErrorLoc = BO->getExprLoc();
12627 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12628 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12629 return false;
12630 }
12631
12632 C = BO;
12633
12634 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12635 E = BO->getRHS();
12636 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12637 E = BO->getLHS();
12638 } else {
12639 ErrorInfo.Error = ErrorTy::InvalidComparison;
12640 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12641 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12642 return false;
12643 }
12644
12645 if (S2->getElse()) {
12646 IsFailOnly = true;
12647
12648 auto *Else = S2->getElse();
12649 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12650 if (ElseCS->body_empty()) {
12651 ErrorInfo.Error = ErrorTy::NoStmt;
12652 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12653 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12654 return false;
12655 }
12656 if (ElseCS->size() > 1) {
12657 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12658 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12659 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12660 return false;
12661 }
12662 Else = ElseCS->body_front();
12663 }
12664
12665 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12666 if (!ElseBO) {
12667 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12668 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12669 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12670 return false;
12671 }
12672 if (ElseBO->getOpcode() != BO_Assign) {
12673 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12674 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12675 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12676 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12677 return false;
12678 }
12679 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12680 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12681 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12682 ErrorInfo.NoteLoc = X->getExprLoc();
12683 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12684 ErrorInfo.NoteRange = X->getSourceRange();
12685 return false;
12686 }
12687
12688 V = ElseBO->getLHS();
12689 }
12690
12691 return checkType(ErrorInfo);
12692}
12693
12694bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12695 ErrorInfoTy &ErrorInfo) {
12696 // if(x == e) { x = d; } else { v = x; }
12697 if (auto *IS = dyn_cast<IfStmt>(S))
12698 return checkForm3(IS, ErrorInfo);
12699
12700 auto *CS = dyn_cast<CompoundStmt>(S);
12701 if (!CS) {
12702 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12703 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12704 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12705 return false;
12706 }
12707 if (CS->body_empty()) {
12708 ErrorInfo.Error = ErrorTy::NoStmt;
12709 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12710 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12711 return false;
12712 }
12713
12714 // { if(x == e) { x = d; } else { v = x; } }
12715 if (CS->size() == 1) {
12716 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12717 if (!IS) {
12718 ErrorInfo.Error = ErrorTy::NotIfStmt;
12719 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12720 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12721 CS->body_front()->getSourceRange();
12722 return false;
12723 }
12724
12725 return checkForm3(IS, ErrorInfo);
12726 } else if (CS->size() == 2) {
12727 auto *S1 = CS->body_front();
12728 auto *S2 = CS->body_back();
12729
12730 Stmt *UpdateStmt = nullptr;
12731 Stmt *CondUpdateStmt = nullptr;
12732 Stmt *CondExprStmt = nullptr;
12733
12734 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12735 // It could be one of the following cases:
12736 // { v = x; cond-update-stmt }
12737 // { v = x; cond-expr-stmt }
12738 // { cond-expr-stmt; v = x; }
12739 // form 45
12740 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12741 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12742 // check if form 45
12743 if (isa<IfStmt>(S2))
12744 return checkForm45(CS, ErrorInfo);
12745 // { cond-expr-stmt; v = x; }
12746 CondExprStmt = S1;
12747 UpdateStmt = S2;
12748 } else {
12749 IsPostfixUpdate = true;
12750 UpdateStmt = S1;
12751 if (isa<IfStmt>(S2)) {
12752 // { v = x; cond-update-stmt }
12753 CondUpdateStmt = S2;
12754 } else {
12755 // { v = x; cond-expr-stmt }
12756 CondExprStmt = S2;
12757 }
12758 }
12759 } else {
12760 // { cond-update-stmt v = x; }
12761 UpdateStmt = S2;
12762 CondUpdateStmt = S1;
12763 }
12764
12765 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12766 auto *IS = dyn_cast<IfStmt>(CUS);
12767 if (!IS) {
12768 ErrorInfo.Error = ErrorTy::NotIfStmt;
12769 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12770 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12771 return false;
12772 }
12773
12774 return checkCondUpdateStmt(IS, ErrorInfo);
12775 };
12776
12777 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12778 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12779 auto *BO = dyn_cast<BinaryOperator>(US);
12780 if (!BO) {
12781 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12782 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12783 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12784 return false;
12785 }
12786 if (BO->getOpcode() != BO_Assign) {
12787 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12788 ErrorInfo.ErrorLoc = BO->getExprLoc();
12789 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12790 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12791 return false;
12792 }
12793 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12794 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12795 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12796 ErrorInfo.NoteLoc = this->X->getExprLoc();
12797 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12798 ErrorInfo.NoteRange = this->X->getSourceRange();
12799 return false;
12800 }
12801
12802 this->V = BO->getLHS();
12803
12804 return true;
12805 };
12806
12807 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12808 return false;
12809 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12810 return false;
12811 if (!CheckUpdateStmt(UpdateStmt))
12812 return false;
12813 } else {
12814 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12815 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12816 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12817 return false;
12818 }
12819
12820 return checkType(ErrorInfo);
12821}
12822} // namespace
12823
12825 Stmt *AStmt,
12826 SourceLocation StartLoc,
12827 SourceLocation EndLoc) {
12828 ASTContext &Context = getASTContext();
12829 unsigned OMPVersion = getLangOpts().OpenMP;
12830 // Register location of the first atomic directive.
12831 DSAStack->addAtomicDirectiveLoc(StartLoc);
12832 if (!AStmt)
12833 return StmtError();
12834
12835 // 1.2.2 OpenMP Language Terminology
12836 // Structured block - An executable statement with a single entry at the
12837 // top and a single exit at the bottom.
12838 // The point of exit cannot be a branch out of the structured block.
12839 // longjmp() and throw() must not violate the entry/exit criteria.
12840 OpenMPClauseKind AtomicKind = OMPC_unknown;
12841 SourceLocation AtomicKindLoc;
12842 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12843 SourceLocation MemOrderLoc;
12844 bool MutexClauseEncountered = false;
12845 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12846 for (const OMPClause *C : Clauses) {
12847 switch (C->getClauseKind()) {
12848 case OMPC_read:
12849 case OMPC_write:
12850 case OMPC_update:
12851 MutexClauseEncountered = true;
12852 [[fallthrough]];
12853 case OMPC_capture:
12854 case OMPC_compare: {
12855 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12856 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12857 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12858 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12859 << getOpenMPClauseNameForDiag(AtomicKind);
12860 } else {
12861 AtomicKind = C->getClauseKind();
12862 AtomicKindLoc = C->getBeginLoc();
12863 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12864 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12865 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12866 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12867 << getOpenMPClauseNameForDiag(AtomicKind);
12868 }
12869 }
12870 break;
12871 }
12872 case OMPC_weak:
12873 case OMPC_fail: {
12874 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12875 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12876 << getOpenMPClauseNameForDiag(C->getClauseKind())
12877 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12878 return StmtError();
12879 }
12880 break;
12881 }
12882 case OMPC_seq_cst:
12883 case OMPC_acq_rel:
12884 case OMPC_acquire:
12885 case OMPC_release:
12886 case OMPC_relaxed: {
12887 if (MemOrderKind != OMPC_unknown) {
12888 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12889 << getOpenMPDirectiveName(OMPD_atomic, OMPVersion) << 0
12890 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12891 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12892 << getOpenMPClauseNameForDiag(MemOrderKind);
12893 } else {
12894 MemOrderKind = C->getClauseKind();
12895 MemOrderLoc = C->getBeginLoc();
12896 }
12897 break;
12898 }
12899 // The following clauses are allowed, but we don't need to do anything here.
12900 case OMPC_hint:
12901 break;
12902 default:
12903 llvm_unreachable("unknown clause is encountered");
12904 }
12905 }
12906 bool IsCompareCapture = false;
12907 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12908 EncounteredAtomicKinds.contains(OMPC_capture)) {
12909 IsCompareCapture = true;
12910 AtomicKind = OMPC_compare;
12911 }
12912 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12913 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12914 // release.
12915 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12916 // acquire.
12917 // If atomic-clause is update or not present then memory-order-clause must not
12918 // be acq_rel or acquire.
12919 if ((AtomicKind == OMPC_read &&
12920 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12921 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12922 AtomicKind == OMPC_unknown) &&
12923 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12924 SourceLocation Loc = AtomicKindLoc;
12925 if (AtomicKind == OMPC_unknown)
12926 Loc = StartLoc;
12927 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12928 << getOpenMPClauseNameForDiag(AtomicKind)
12929 << (AtomicKind == OMPC_unknown ? 1 : 0)
12930 << getOpenMPClauseNameForDiag(MemOrderKind);
12931 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12932 << getOpenMPClauseNameForDiag(MemOrderKind);
12933 }
12934
12935 Stmt *Body = AStmt;
12936 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12937 Body = EWC->getSubExpr();
12938
12939 Expr *X = nullptr;
12940 Expr *V = nullptr;
12941 Expr *E = nullptr;
12942 Expr *UE = nullptr;
12943 Expr *D = nullptr;
12944 Expr *CE = nullptr;
12945 Expr *R = nullptr;
12946 bool IsXLHSInRHSPart = false;
12947 bool IsPostfixUpdate = false;
12948 bool IsFailOnly = false;
12949 // OpenMP [2.12.6, atomic Construct]
12950 // In the next expressions:
12951 // * x and v (as applicable) are both l-value expressions with scalar type.
12952 // * During the execution of an atomic region, multiple syntactic
12953 // occurrences of x must designate the same storage location.
12954 // * Neither of v and expr (as applicable) may access the storage location
12955 // designated by x.
12956 // * Neither of x and expr (as applicable) may access the storage location
12957 // designated by v.
12958 // * expr is an expression with scalar type.
12959 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12960 // * binop, binop=, ++, and -- are not overloaded operators.
12961 // * The expression x binop expr must be numerically equivalent to x binop
12962 // (expr). This requirement is satisfied if the operators in expr have
12963 // precedence greater than binop, or by using parentheses around expr or
12964 // subexpressions of expr.
12965 // * The expression expr binop x must be numerically equivalent to (expr)
12966 // binop x. This requirement is satisfied if the operators in expr have
12967 // precedence equal to or greater than binop, or by using parentheses around
12968 // expr or subexpressions of expr.
12969 // * For forms that allow multiple occurrences of x, the number of times
12970 // that x is evaluated is unspecified.
12971 if (AtomicKind == OMPC_read) {
12972 enum {
12973 NotAnExpression,
12974 NotAnAssignmentOp,
12975 NotAScalarType,
12976 NotAnLValue,
12977 NoError
12978 } ErrorFound = NoError;
12979 SourceLocation ErrorLoc, NoteLoc;
12980 SourceRange ErrorRange, NoteRange;
12981 // If clause is read:
12982 // v = x;
12983 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12984 const auto *AtomicBinOp =
12985 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12986 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12987 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12988 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12989 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12990 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12991 if (!X->isLValue() || !V->isLValue()) {
12992 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12993 ErrorFound = NotAnLValue;
12994 ErrorLoc = AtomicBinOp->getExprLoc();
12995 ErrorRange = AtomicBinOp->getSourceRange();
12996 NoteLoc = NotLValueExpr->getExprLoc();
12997 NoteRange = NotLValueExpr->getSourceRange();
12998 }
12999 } else if (!X->isInstantiationDependent() ||
13000 !V->isInstantiationDependent()) {
13001 const Expr *NotScalarExpr =
13002 (X->isInstantiationDependent() || X->getType()->isScalarType())
13003 ? V
13004 : X;
13005 ErrorFound = NotAScalarType;
13006 ErrorLoc = AtomicBinOp->getExprLoc();
13007 ErrorRange = AtomicBinOp->getSourceRange();
13008 NoteLoc = NotScalarExpr->getExprLoc();
13009 NoteRange = NotScalarExpr->getSourceRange();
13010 }
13011 } else if (!AtomicBody->isInstantiationDependent()) {
13012 ErrorFound = NotAnAssignmentOp;
13013 ErrorLoc = AtomicBody->getExprLoc();
13014 ErrorRange = AtomicBody->getSourceRange();
13015 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13016 : AtomicBody->getExprLoc();
13017 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13018 : AtomicBody->getSourceRange();
13019 }
13020 } else {
13021 ErrorFound = NotAnExpression;
13022 NoteLoc = ErrorLoc = Body->getBeginLoc();
13023 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
13024 }
13025 if (ErrorFound != NoError) {
13026 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
13027 << ErrorRange;
13028 Diag(NoteLoc, diag::note_omp_atomic_read_write)
13029 << ErrorFound << NoteRange;
13030 return StmtError();
13031 }
13032 if (SemaRef.CurContext->isDependentContext())
13033 V = X = nullptr;
13034 } else if (AtomicKind == OMPC_write) {
13035 enum {
13036 NotAnExpression,
13037 NotAnAssignmentOp,
13038 NotAScalarType,
13039 NotAnLValue,
13040 NoError
13041 } ErrorFound = NoError;
13042 SourceLocation ErrorLoc, NoteLoc;
13043 SourceRange ErrorRange, NoteRange;
13044 // If clause is write:
13045 // x = expr;
13046 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
13047 const auto *AtomicBinOp =
13048 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
13049 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
13050 X = AtomicBinOp->getLHS();
13051 E = AtomicBinOp->getRHS();
13052 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
13053 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
13054 if (!X->isLValue()) {
13055 ErrorFound = NotAnLValue;
13056 ErrorLoc = AtomicBinOp->getExprLoc();
13057 ErrorRange = AtomicBinOp->getSourceRange();
13058 NoteLoc = X->getExprLoc();
13059 NoteRange = X->getSourceRange();
13060 }
13061 } else if (!X->isInstantiationDependent() ||
13063 const Expr *NotScalarExpr =
13064 (X->isInstantiationDependent() || X->getType()->isScalarType())
13065 ? E
13066 : X;
13067 ErrorFound = NotAScalarType;
13068 ErrorLoc = AtomicBinOp->getExprLoc();
13069 ErrorRange = AtomicBinOp->getSourceRange();
13070 NoteLoc = NotScalarExpr->getExprLoc();
13071 NoteRange = NotScalarExpr->getSourceRange();
13072 }
13073 } else if (!AtomicBody->isInstantiationDependent()) {
13074 ErrorFound = NotAnAssignmentOp;
13075 ErrorLoc = AtomicBody->getExprLoc();
13076 ErrorRange = AtomicBody->getSourceRange();
13077 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13078 : AtomicBody->getExprLoc();
13079 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13080 : AtomicBody->getSourceRange();
13081 }
13082 } else {
13083 ErrorFound = NotAnExpression;
13084 NoteLoc = ErrorLoc = Body->getBeginLoc();
13085 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
13086 }
13087 if (ErrorFound != NoError) {
13088 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
13089 << ErrorRange;
13090 Diag(NoteLoc, diag::note_omp_atomic_read_write)
13091 << ErrorFound << NoteRange;
13092 return StmtError();
13093 }
13094 if (SemaRef.CurContext->isDependentContext())
13095 E = X = nullptr;
13096 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
13097 // If clause is update:
13098 // x++;
13099 // x--;
13100 // ++x;
13101 // --x;
13102 // x binop= expr;
13103 // x = x binop expr;
13104 // x = expr binop x;
13105 OpenMPAtomicUpdateChecker Checker(SemaRef);
13106 if (Checker.checkStatement(
13107 Body,
13108 (AtomicKind == OMPC_update)
13109 ? diag::err_omp_atomic_update_not_expression_statement
13110 : diag::err_omp_atomic_not_expression_statement,
13111 diag::note_omp_atomic_update))
13112 return StmtError();
13113 if (!SemaRef.CurContext->isDependentContext()) {
13114 E = Checker.getExpr();
13115 X = Checker.getX();
13116 UE = Checker.getUpdateExpr();
13117 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13118 }
13119 } else if (AtomicKind == OMPC_capture) {
13120 enum {
13121 NotAnAssignmentOp,
13122 NotACompoundStatement,
13123 NotTwoSubstatements,
13124 NotASpecificExpression,
13125 NoError
13126 } ErrorFound = NoError;
13127 SourceLocation ErrorLoc, NoteLoc;
13128 SourceRange ErrorRange, NoteRange;
13129 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
13130 // If clause is a capture:
13131 // v = x++;
13132 // v = x--;
13133 // v = ++x;
13134 // v = --x;
13135 // v = x binop= expr;
13136 // v = x = x binop expr;
13137 // v = x = expr binop x;
13138 const auto *AtomicBinOp =
13139 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
13140 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
13141 V = AtomicBinOp->getLHS();
13142 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
13143 OpenMPAtomicUpdateChecker Checker(SemaRef);
13144 if (Checker.checkStatement(
13145 Body, diag::err_omp_atomic_capture_not_expression_statement,
13146 diag::note_omp_atomic_update))
13147 return StmtError();
13148 E = Checker.getExpr();
13149 X = Checker.getX();
13150 UE = Checker.getUpdateExpr();
13151 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13152 IsPostfixUpdate = Checker.isPostfixUpdate();
13153 } else if (!AtomicBody->isInstantiationDependent()) {
13154 ErrorLoc = AtomicBody->getExprLoc();
13155 ErrorRange = AtomicBody->getSourceRange();
13156 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13157 : AtomicBody->getExprLoc();
13158 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13159 : AtomicBody->getSourceRange();
13160 ErrorFound = NotAnAssignmentOp;
13161 }
13162 if (ErrorFound != NoError) {
13163 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
13164 << ErrorRange;
13165 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13166 return StmtError();
13167 }
13168 if (SemaRef.CurContext->isDependentContext())
13169 UE = V = E = X = nullptr;
13170 } else {
13171 // If clause is a capture:
13172 // { v = x; x = expr; }
13173 // { v = x; x++; }
13174 // { v = x; x--; }
13175 // { v = x; ++x; }
13176 // { v = x; --x; }
13177 // { v = x; x binop= expr; }
13178 // { v = x; x = x binop expr; }
13179 // { v = x; x = expr binop x; }
13180 // { x++; v = x; }
13181 // { x--; v = x; }
13182 // { ++x; v = x; }
13183 // { --x; v = x; }
13184 // { x binop= expr; v = x; }
13185 // { x = x binop expr; v = x; }
13186 // { x = expr binop x; v = x; }
13187 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
13188 // Check that this is { expr1; expr2; }
13189 if (CS->size() == 2) {
13190 Stmt *First = CS->body_front();
13191 Stmt *Second = CS->body_back();
13192 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
13193 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13194 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
13195 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13196 // Need to find what subexpression is 'v' and what is 'x'.
13197 OpenMPAtomicUpdateChecker Checker(SemaRef);
13198 bool IsUpdateExprFound = !Checker.checkStatement(Second);
13199 BinaryOperator *BinOp = nullptr;
13200 if (IsUpdateExprFound) {
13201 BinOp = dyn_cast<BinaryOperator>(First);
13202 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13203 }
13204 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
13205 // { v = x; x++; }
13206 // { v = x; x--; }
13207 // { v = x; ++x; }
13208 // { v = x; --x; }
13209 // { v = x; x binop= expr; }
13210 // { v = x; x = x binop expr; }
13211 // { v = x; x = expr binop x; }
13212 // Check that the first expression has form v = x.
13213 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13214 llvm::FoldingSetNodeID XId, PossibleXId;
13215 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13216 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13217 IsUpdateExprFound = XId == PossibleXId;
13218 if (IsUpdateExprFound) {
13219 V = BinOp->getLHS();
13220 X = Checker.getX();
13221 E = Checker.getExpr();
13222 UE = Checker.getUpdateExpr();
13223 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13224 IsPostfixUpdate = true;
13225 }
13226 }
13227 if (!IsUpdateExprFound) {
13228 IsUpdateExprFound = !Checker.checkStatement(First);
13229 BinOp = nullptr;
13230 if (IsUpdateExprFound) {
13231 BinOp = dyn_cast<BinaryOperator>(Second);
13232 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13233 }
13234 if (IsUpdateExprFound &&
13235 !SemaRef.CurContext->isDependentContext()) {
13236 // { x++; v = x; }
13237 // { x--; v = x; }
13238 // { ++x; v = x; }
13239 // { --x; v = x; }
13240 // { x binop= expr; v = x; }
13241 // { x = x binop expr; v = x; }
13242 // { x = expr binop x; v = x; }
13243 // Check that the second expression has form v = x.
13244 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13245 llvm::FoldingSetNodeID XId, PossibleXId;
13246 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13247 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13248 IsUpdateExprFound = XId == PossibleXId;
13249 if (IsUpdateExprFound) {
13250 V = BinOp->getLHS();
13251 X = Checker.getX();
13252 E = Checker.getExpr();
13253 UE = Checker.getUpdateExpr();
13254 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13255 IsPostfixUpdate = false;
13256 }
13257 }
13258 }
13259 if (!IsUpdateExprFound) {
13260 // { v = x; x = expr; }
13261 auto *FirstExpr = dyn_cast<Expr>(First);
13262 auto *SecondExpr = dyn_cast<Expr>(Second);
13263 if (!FirstExpr || !SecondExpr ||
13264 !(FirstExpr->isInstantiationDependent() ||
13265 SecondExpr->isInstantiationDependent())) {
13266 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
13267 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13268 ErrorFound = NotAnAssignmentOp;
13269 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13270 : First->getBeginLoc();
13271 NoteRange = ErrorRange = FirstBinOp
13272 ? FirstBinOp->getSourceRange()
13273 : SourceRange(ErrorLoc, ErrorLoc);
13274 } else {
13275 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
13276 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13277 ErrorFound = NotAnAssignmentOp;
13278 NoteLoc = ErrorLoc = SecondBinOp
13279 ? SecondBinOp->getOperatorLoc()
13280 : Second->getBeginLoc();
13281 NoteRange = ErrorRange =
13282 SecondBinOp ? SecondBinOp->getSourceRange()
13283 : SourceRange(ErrorLoc, ErrorLoc);
13284 } else {
13285 Expr *PossibleXRHSInFirst =
13286 FirstBinOp->getRHS()->IgnoreParenImpCasts();
13287 Expr *PossibleXLHSInSecond =
13288 SecondBinOp->getLHS()->IgnoreParenImpCasts();
13289 llvm::FoldingSetNodeID X1Id, X2Id;
13290 PossibleXRHSInFirst->Profile(X1Id, Context,
13291 /*Canonical=*/true);
13292 PossibleXLHSInSecond->Profile(X2Id, Context,
13293 /*Canonical=*/true);
13294 IsUpdateExprFound = X1Id == X2Id;
13295 if (IsUpdateExprFound) {
13296 V = FirstBinOp->getLHS();
13297 X = SecondBinOp->getLHS();
13298 E = SecondBinOp->getRHS();
13299 UE = nullptr;
13300 IsXLHSInRHSPart = false;
13301 IsPostfixUpdate = true;
13302 } else {
13303 ErrorFound = NotASpecificExpression;
13304 ErrorLoc = FirstBinOp->getExprLoc();
13305 ErrorRange = FirstBinOp->getSourceRange();
13306 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13307 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13308 }
13309 }
13310 }
13311 }
13312 }
13313 } else {
13314 NoteLoc = ErrorLoc = Body->getBeginLoc();
13315 NoteRange = ErrorRange =
13316 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13317 ErrorFound = NotTwoSubstatements;
13318 }
13319 } else {
13320 NoteLoc = ErrorLoc = Body->getBeginLoc();
13321 NoteRange = ErrorRange =
13322 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13323 ErrorFound = NotACompoundStatement;
13324 }
13325 }
13326 if (ErrorFound != NoError) {
13327 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
13328 << ErrorRange;
13329 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13330 return StmtError();
13331 }
13332 if (SemaRef.CurContext->isDependentContext())
13333 UE = V = E = X = nullptr;
13334 } else if (AtomicKind == OMPC_compare) {
13335 if (IsCompareCapture) {
13336 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13337 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
13338 if (!Checker.checkStmt(Body, ErrorInfo)) {
13339 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
13340 << ErrorInfo.ErrorRange;
13341 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13342 << ErrorInfo.Error << ErrorInfo.NoteRange;
13343 return StmtError();
13344 }
13345 X = Checker.getX();
13346 E = Checker.getE();
13347 D = Checker.getD();
13348 CE = Checker.getCond();
13349 V = Checker.getV();
13350 R = Checker.getR();
13351 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13352 IsXLHSInRHSPart = Checker.isXBinopExpr();
13353 IsFailOnly = Checker.isFailOnly();
13354 IsPostfixUpdate = Checker.isPostfixUpdate();
13355 } else {
13356 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13357 OpenMPAtomicCompareChecker Checker(SemaRef);
13358 if (!Checker.checkStmt(Body, ErrorInfo)) {
13359 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
13360 << ErrorInfo.ErrorRange;
13361 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13362 << ErrorInfo.Error << ErrorInfo.NoteRange;
13363 return StmtError();
13364 }
13365 X = Checker.getX();
13366 E = Checker.getE();
13367 D = Checker.getD();
13368 CE = Checker.getCond();
13369 // The weak clause may only appear if the resulting atomic operation is
13370 // an atomic conditional update for which the comparison tests for
13371 // equality. It was not possible to do this check in
13372 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
13373 // could not be performed (Clauses are not available).
13374 auto *It = find_if(Clauses, [](OMPClause *C) {
13375 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13376 });
13377 if (It != Clauses.end()) {
13378 auto *Cond = dyn_cast<BinaryOperator>(CE);
13379 if (Cond->getOpcode() != BO_EQ) {
13380 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13381 ErrorInfo.ErrorLoc = Cond->getExprLoc();
13382 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
13383 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
13384
13385 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
13386 << ErrorInfo.ErrorRange;
13387 return StmtError();
13388 }
13389 }
13390 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13391 IsXLHSInRHSPart = Checker.isXBinopExpr();
13392 }
13393 }
13394
13395 SemaRef.setFunctionHasBranchProtectedScope();
13396
13397 return OMPAtomicDirective::Create(
13398 Context, StartLoc, EndLoc, Clauses, AStmt,
13399 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
13400}
13401
13403 Stmt *AStmt,
13404 SourceLocation StartLoc,
13405 SourceLocation EndLoc) {
13406 if (!AStmt)
13407 return StmtError();
13408
13409 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target, AStmt);
13410
13411 // OpenMP [2.16, Nesting of Regions]
13412 // If specified, a teams construct must be contained within a target
13413 // construct. That target construct must contain no statements or directives
13414 // outside of the teams construct.
13415 if (DSAStack->hasInnerTeamsRegion()) {
13416 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13417 bool OMPTeamsFound = true;
13418 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
13419 auto I = CS->body_begin();
13420 while (I != CS->body_end()) {
13421 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13422 bool IsTeams = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13423 if (!IsTeams || I != CS->body_begin()) {
13424 OMPTeamsFound = false;
13425 if (IsTeams && I != CS->body_begin()) {
13426 // This is the two teams case. Since the InnerTeamsRegionLoc will
13427 // point to this second one reset the iterator to the other teams.
13428 --I;
13429 }
13430 break;
13431 }
13432 ++I;
13433 }
13434 assert(I != CS->body_end() && "Not found statement");
13435 S = *I;
13436 } else {
13437 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13438 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13439 }
13440 if (!OMPTeamsFound) {
13441 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13442 Diag(DSAStack->getInnerTeamsRegionLoc(),
13443 diag::note_omp_nested_teams_construct_here);
13444 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
13446 return StmtError();
13447 }
13448 }
13449
13450 return OMPTargetDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13451 AStmt);
13452}
13453
13455 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13456 SourceLocation EndLoc) {
13457 if (!AStmt)
13458 return StmtError();
13459
13460 setBranchProtectedScope(SemaRef, OMPD_target_parallel, AStmt);
13461
13463 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
13464 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13465}
13466
13468 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13469 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13470 if (!AStmt)
13471 return StmtError();
13472
13473 CapturedStmt *CS =
13474 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for, AStmt);
13475
13476 OMPLoopBasedDirective::HelperExprs B;
13477 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13478 // define the nested loops number.
13479 unsigned NestedLoopCount =
13480 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13481 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13482 VarsWithImplicitDSA, B);
13483 if (NestedLoopCount == 0)
13484 return StmtError();
13485
13486 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13487 return StmtError();
13488
13490 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13491 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13492}
13493
13494/// Check for existence of a map clause in the list of clauses.
13496 const OpenMPClauseKind K) {
13497 return llvm::any_of(
13498 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13499}
13500
13501template <typename... Params>
13503 const Params... ClauseTypes) {
13504 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13505}
13506
13507/// Check if the variables in the mapping clause are externally visible.
13509 for (const OMPClause *C : Clauses) {
13510 if (auto *TC = dyn_cast<OMPToClause>(C))
13511 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13512 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13513 (VD->isExternallyVisible() &&
13514 VD->getVisibility() != HiddenVisibility);
13515 });
13516 else if (auto *FC = dyn_cast<OMPFromClause>(C))
13517 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13518 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13519 (VD->isExternallyVisible() &&
13520 VD->getVisibility() != HiddenVisibility);
13521 });
13522 }
13523
13524 return true;
13525}
13526
13529 Stmt *AStmt, SourceLocation StartLoc,
13530 SourceLocation EndLoc) {
13531 if (!AStmt)
13532 return StmtError();
13533
13534 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13535
13536 // OpenMP [2.12.2, target data Construct, Restrictions]
13537 // At least one map, use_device_addr or use_device_ptr clause must appear on
13538 // the directive.
13539 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13540 (getLangOpts().OpenMP < 50 ||
13541 !hasClauses(Clauses, OMPC_use_device_addr))) {
13542 StringRef Expected;
13543 if (getLangOpts().OpenMP < 50)
13544 Expected = "'map' or 'use_device_ptr'";
13545 else
13546 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13547 unsigned OMPVersion = getLangOpts().OpenMP;
13548 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13549 << Expected << getOpenMPDirectiveName(OMPD_target_data, OMPVersion);
13550 return StmtError();
13551 }
13552
13553 SemaRef.setFunctionHasBranchProtectedScope();
13554
13555 return OMPTargetDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13556 Clauses, AStmt);
13557}
13558
13560 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13561 SourceLocation EndLoc, Stmt *AStmt) {
13562 if (!AStmt)
13563 return StmtError();
13564
13565 setBranchProtectedScope(SemaRef, OMPD_target_enter_data, AStmt);
13566
13567 // OpenMP [2.10.2, Restrictions, p. 99]
13568 // At least one map clause must appear on the directive.
13569 if (!hasClauses(Clauses, OMPC_map)) {
13570 unsigned OMPVersion = getLangOpts().OpenMP;
13571 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13572 << "'map'"
13573 << getOpenMPDirectiveName(OMPD_target_enter_data, OMPVersion);
13574 return StmtError();
13575 }
13576
13577 return OMPTargetEnterDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13578 Clauses, AStmt);
13579}
13580
13582 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13583 SourceLocation EndLoc, Stmt *AStmt) {
13584 if (!AStmt)
13585 return StmtError();
13586
13587 setBranchProtectedScope(SemaRef, OMPD_target_exit_data, AStmt);
13588
13589 // OpenMP [2.10.3, Restrictions, p. 102]
13590 // At least one map clause must appear on the directive.
13591 if (!hasClauses(Clauses, OMPC_map)) {
13592 unsigned OMPVersion = getLangOpts().OpenMP;
13593 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13594 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data, OMPVersion);
13595 return StmtError();
13596 }
13597
13598 return OMPTargetExitDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13599 Clauses, AStmt);
13600}
13601
13603 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13604 SourceLocation EndLoc, Stmt *AStmt) {
13605 if (!AStmt)
13606 return StmtError();
13607
13608 setBranchProtectedScope(SemaRef, OMPD_target_update, AStmt);
13609
13610 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13611 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13612 return StmtError();
13613 }
13614
13615 if (!isClauseMappable(Clauses)) {
13616 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13617 return StmtError();
13618 }
13619
13620 return OMPTargetUpdateDirective::Create(getASTContext(), StartLoc, EndLoc,
13621 Clauses, AStmt);
13622}
13623
13624/// Check the number of expressions specified in a multidimensional clause and
13625/// return whether an error was encountered.
13626template <typename ClauseT>
13627static bool checkExprsInMultidimClause(SemaBase &SemaRef, const ClauseT *Clause,
13628 const OMPXBareClause *BareClause) {
13629 if (!Clause)
13630 return false;
13631
13632 const uint64_t NumVars = Clause->getVarRefs().size();
13633
13634 // The ompx_bare clause allows up to three expressions.
13635 if (BareClause && NumVars > 3) {
13636 SemaRef.Diag(Clause->getBeginLoc(),
13637 diag::err_ompx_more_than_three_expr_not_allowed)
13638 << getOpenMPClauseName(Clause->getClauseKind());
13639 return true;
13640 }
13641
13642 // Only one expression is allowed otherwise.
13643 if (!BareClause && NumVars != 1) {
13644 SemaRef.Diag(Clause->getBeginLoc(), diag::err_omp_multi_expr_not_allowed)
13645 << getOpenMPClauseName(Clause->getClauseKind());
13646 return true;
13647 }
13648 return false;
13649}
13650
13651/// Check the number of expressions specified in clauses that can contain
13652/// multidimensional values, e.g., num_teams and thread_limit. The function
13653/// returns true on error.
13654static bool checkMultidimClauses(SemaBase &SemaRef,
13655 ArrayRef<OMPClause *> Clauses,
13656 bool MayHaveBareClause = false) {
13657 auto BareClauseIt =
13658 MayHaveBareClause ? llvm::find_if(Clauses, llvm::IsaPred<OMPXBareClause>)
13659 : Clauses.end();
13660 auto ThreadLimitIt =
13661 llvm::find_if(Clauses, llvm::IsaPred<OMPThreadLimitClause>);
13662 auto NumTeamsIt = llvm::find_if(Clauses, llvm::IsaPred<OMPNumTeamsClause>);
13663
13664 const auto *BareClause = BareClauseIt != Clauses.end()
13665 ? cast<OMPXBareClause>(*BareClauseIt)
13666 : nullptr;
13667 const auto *ThreadLimitClause =
13668 ThreadLimitIt != Clauses.end()
13669 ? cast<OMPThreadLimitClause>(*ThreadLimitIt)
13670 : nullptr;
13671 const auto *NumTeamsClause = NumTeamsIt != Clauses.end()
13672 ? cast<OMPNumTeamsClause>(*NumTeamsIt)
13673 : nullptr;
13674
13675 if (BareClause && (!NumTeamsClause || !ThreadLimitClause)) {
13676 SemaRef.Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
13677 return true;
13678 }
13679 return checkExprsInMultidimClause(SemaRef, ThreadLimitClause, BareClause) ||
13680 checkExprsInMultidimClause(SemaRef, NumTeamsClause, BareClause);
13681}
13682
13684 Stmt *AStmt,
13685 SourceLocation StartLoc,
13686 SourceLocation EndLoc) {
13687 if (!AStmt)
13688 return StmtError();
13689
13690 if (checkMultidimClauses(*this, Clauses))
13691 return StmtError();
13692
13693 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13694 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13695 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13696
13697 setBranchProtectedScope(SemaRef, OMPD_teams, AStmt);
13698
13699 DSAStack->setParentTeamsRegionLoc(StartLoc);
13700
13701 return OMPTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13702 AStmt);
13703}
13704
13706 SourceLocation StartLoc, SourceLocation EndLoc,
13707 OpenMPDirectiveKind CancelRegion) {
13708 if (DSAStack->isParentNowaitRegion()) {
13709 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13710 return StmtError();
13711 }
13712 if (DSAStack->isParentOrderedRegion()) {
13713 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13714 return StmtError();
13715 }
13717 EndLoc, CancelRegion);
13718}
13719
13721 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13722 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13723 if (DSAStack->isParentNowaitRegion()) {
13724 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13725 return StmtError();
13726 }
13727 if (DSAStack->isParentOrderedRegion()) {
13728 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13729 return StmtError();
13730 }
13731 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13732 return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13733 CancelRegion);
13734}
13735
13737 ArrayRef<OMPClause *> Clauses) {
13738 const OMPClause *ReductionClause = nullptr;
13739 const OMPClause *NogroupClause = nullptr;
13740 for (const OMPClause *C : Clauses) {
13741 if (C->getClauseKind() == OMPC_reduction) {
13742 ReductionClause = C;
13743 if (NogroupClause)
13744 break;
13745 continue;
13746 }
13747 if (C->getClauseKind() == OMPC_nogroup) {
13748 NogroupClause = C;
13749 if (ReductionClause)
13750 break;
13751 continue;
13752 }
13753 }
13754 if (ReductionClause && NogroupClause) {
13755 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13756 << SourceRange(NogroupClause->getBeginLoc(),
13757 NogroupClause->getEndLoc());
13758 return true;
13759 }
13760 return false;
13761}
13762
13764 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13765 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13766 if (!AStmt)
13767 return StmtError();
13768
13769 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13770 OMPLoopBasedDirective::HelperExprs B;
13771 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13772 // define the nested loops number.
13773 unsigned NestedLoopCount =
13774 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13775 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13776 *DSAStack, VarsWithImplicitDSA, B);
13777 if (NestedLoopCount == 0)
13778 return StmtError();
13779
13780 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13781 "omp for loop exprs were not built");
13782
13783 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13784 // The grainsize clause and num_tasks clause are mutually exclusive and may
13785 // not appear on the same taskloop directive.
13787 {OMPC_grainsize, OMPC_num_tasks}))
13788 return StmtError();
13789 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13790 // If a reduction clause is present on the taskloop directive, the nogroup
13791 // clause must not be specified.
13793 return StmtError();
13794
13795 SemaRef.setFunctionHasBranchProtectedScope();
13796 return OMPTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13797 NestedLoopCount, Clauses, AStmt, B,
13798 DSAStack->isCancelRegion());
13799}
13800
13802 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13803 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13804 if (!AStmt)
13805 return StmtError();
13806
13807 CapturedStmt *CS =
13808 setBranchProtectedScope(SemaRef, OMPD_taskloop_simd, AStmt);
13809
13810 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13811 OMPLoopBasedDirective::HelperExprs B;
13812 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13813 // define the nested loops number.
13814 unsigned NestedLoopCount =
13815 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13816 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13817 VarsWithImplicitDSA, B);
13818 if (NestedLoopCount == 0)
13819 return StmtError();
13820
13821 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13822 return StmtError();
13823
13824 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13825 // The grainsize clause and num_tasks clause are mutually exclusive and may
13826 // not appear on the same taskloop directive.
13828 {OMPC_grainsize, OMPC_num_tasks}))
13829 return StmtError();
13830 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13831 // If a reduction clause is present on the taskloop directive, the nogroup
13832 // clause must not be specified.
13834 return StmtError();
13836 return StmtError();
13837
13838 return OMPTaskLoopSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13839 NestedLoopCount, Clauses, AStmt, B);
13840}
13841
13843 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13844 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13845 if (!AStmt)
13846 return StmtError();
13847
13848 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13849 OMPLoopBasedDirective::HelperExprs B;
13850 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13851 // define the nested loops number.
13852 unsigned NestedLoopCount =
13853 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13854 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13855 *DSAStack, VarsWithImplicitDSA, B);
13856 if (NestedLoopCount == 0)
13857 return StmtError();
13858
13859 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13860 "omp for loop exprs were not built");
13861
13862 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13863 // The grainsize clause and num_tasks clause are mutually exclusive and may
13864 // not appear on the same taskloop directive.
13866 {OMPC_grainsize, OMPC_num_tasks}))
13867 return StmtError();
13868 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13869 // If a reduction clause is present on the taskloop directive, the nogroup
13870 // clause must not be specified.
13872 return StmtError();
13873
13874 SemaRef.setFunctionHasBranchProtectedScope();
13875 return OMPMasterTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13876 NestedLoopCount, Clauses, AStmt, B,
13877 DSAStack->isCancelRegion());
13878}
13879
13881 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13882 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13883 if (!AStmt)
13884 return StmtError();
13885
13886 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13887 OMPLoopBasedDirective::HelperExprs B;
13888 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13889 // define the nested loops number.
13890 unsigned NestedLoopCount =
13891 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13892 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13893 *DSAStack, VarsWithImplicitDSA, B);
13894 if (NestedLoopCount == 0)
13895 return StmtError();
13896
13897 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13898 "omp for loop exprs were not built");
13899
13900 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13901 // The grainsize clause and num_tasks clause are mutually exclusive and may
13902 // not appear on the same taskloop directive.
13904 {OMPC_grainsize, OMPC_num_tasks}))
13905 return StmtError();
13906 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13907 // If a reduction clause is present on the taskloop directive, the nogroup
13908 // clause must not be specified.
13910 return StmtError();
13911
13912 SemaRef.setFunctionHasBranchProtectedScope();
13913 return OMPMaskedTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13914 NestedLoopCount, Clauses, AStmt, B,
13915 DSAStack->isCancelRegion());
13916}
13917
13919 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13920 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13921 if (!AStmt)
13922 return StmtError();
13923
13924 CapturedStmt *CS =
13925 setBranchProtectedScope(SemaRef, OMPD_master_taskloop_simd, AStmt);
13926
13927 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13928 OMPLoopBasedDirective::HelperExprs B;
13929 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13930 // define the nested loops number.
13931 unsigned NestedLoopCount =
13932 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13933 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13934 VarsWithImplicitDSA, B);
13935 if (NestedLoopCount == 0)
13936 return StmtError();
13937
13938 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13939 return StmtError();
13940
13941 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13942 // The grainsize clause and num_tasks clause are mutually exclusive and may
13943 // not appear on the same taskloop directive.
13945 {OMPC_grainsize, OMPC_num_tasks}))
13946 return StmtError();
13947 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13948 // If a reduction clause is present on the taskloop directive, the nogroup
13949 // clause must not be specified.
13951 return StmtError();
13953 return StmtError();
13954
13956 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13957}
13958
13960 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13961 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13962 if (!AStmt)
13963 return StmtError();
13964
13965 CapturedStmt *CS =
13966 setBranchProtectedScope(SemaRef, OMPD_masked_taskloop_simd, AStmt);
13967
13968 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13969 OMPLoopBasedDirective::HelperExprs B;
13970 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13971 // define the nested loops number.
13972 unsigned NestedLoopCount =
13973 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13974 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13975 VarsWithImplicitDSA, B);
13976 if (NestedLoopCount == 0)
13977 return StmtError();
13978
13979 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13980 return StmtError();
13981
13982 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13983 // The grainsize clause and num_tasks clause are mutually exclusive and may
13984 // not appear on the same taskloop directive.
13986 {OMPC_grainsize, OMPC_num_tasks}))
13987 return StmtError();
13988 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13989 // If a reduction clause is present on the taskloop directive, the nogroup
13990 // clause must not be specified.
13992 return StmtError();
13994 return StmtError();
13995
13997 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13998}
13999
14001 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14002 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14003 if (!AStmt)
14004 return StmtError();
14005
14006 CapturedStmt *CS =
14007 setBranchProtectedScope(SemaRef, OMPD_parallel_master_taskloop, AStmt);
14008
14009 OMPLoopBasedDirective::HelperExprs B;
14010 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14011 // define the nested loops number.
14012 unsigned NestedLoopCount = checkOpenMPLoop(
14013 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
14014 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
14015 VarsWithImplicitDSA, B);
14016 if (NestedLoopCount == 0)
14017 return StmtError();
14018
14019 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14020 "omp for loop exprs were not built");
14021
14022 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14023 // The grainsize clause and num_tasks clause are mutually exclusive and may
14024 // not appear on the same taskloop directive.
14026 {OMPC_grainsize, OMPC_num_tasks}))
14027 return StmtError();
14028 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14029 // If a reduction clause is present on the taskloop directive, the nogroup
14030 // clause must not be specified.
14032 return StmtError();
14033
14035 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14036 DSAStack->isCancelRegion());
14037}
14038
14040 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14041 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14042 if (!AStmt)
14043 return StmtError();
14044
14045 CapturedStmt *CS =
14046 setBranchProtectedScope(SemaRef, OMPD_parallel_masked_taskloop, AStmt);
14047
14048 OMPLoopBasedDirective::HelperExprs B;
14049 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14050 // define the nested loops number.
14051 unsigned NestedLoopCount = checkOpenMPLoop(
14052 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
14053 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
14054 VarsWithImplicitDSA, B);
14055 if (NestedLoopCount == 0)
14056 return StmtError();
14057
14058 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14059 "omp for loop exprs were not built");
14060
14061 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14062 // The grainsize clause and num_tasks clause are mutually exclusive and may
14063 // not appear on the same taskloop directive.
14065 {OMPC_grainsize, OMPC_num_tasks}))
14066 return StmtError();
14067 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14068 // If a reduction clause is present on the taskloop directive, the nogroup
14069 // clause must not be specified.
14071 return StmtError();
14072
14074 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14075 DSAStack->isCancelRegion());
14076}
14077
14079 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14080 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14081 if (!AStmt)
14082 return StmtError();
14083
14085 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
14086
14087 OMPLoopBasedDirective::HelperExprs B;
14088 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14089 // define the nested loops number.
14090 unsigned NestedLoopCount = checkOpenMPLoop(
14091 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
14092 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
14093 VarsWithImplicitDSA, B);
14094 if (NestedLoopCount == 0)
14095 return StmtError();
14096
14097 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14098 return StmtError();
14099
14100 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14101 // The grainsize clause and num_tasks clause are mutually exclusive and may
14102 // not appear on the same taskloop directive.
14104 {OMPC_grainsize, OMPC_num_tasks}))
14105 return StmtError();
14106 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14107 // If a reduction clause is present on the taskloop directive, the nogroup
14108 // clause must not be specified.
14110 return StmtError();
14112 return StmtError();
14113
14115 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14116}
14117
14119 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14120 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14121 if (!AStmt)
14122 return StmtError();
14123
14125 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
14126
14127 OMPLoopBasedDirective::HelperExprs B;
14128 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14129 // define the nested loops number.
14130 unsigned NestedLoopCount = checkOpenMPLoop(
14131 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
14132 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
14133 VarsWithImplicitDSA, B);
14134 if (NestedLoopCount == 0)
14135 return StmtError();
14136
14137 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14138 return StmtError();
14139
14140 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14141 // The grainsize clause and num_tasks clause are mutually exclusive and may
14142 // not appear on the same taskloop directive.
14144 {OMPC_grainsize, OMPC_num_tasks}))
14145 return StmtError();
14146 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14147 // If a reduction clause is present on the taskloop directive, the nogroup
14148 // clause must not be specified.
14150 return StmtError();
14152 return StmtError();
14153
14155 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14156}
14157
14159 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14160 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14161 if (!AStmt)
14162 return StmtError();
14163
14164 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14165 OMPLoopBasedDirective::HelperExprs B;
14166 // In presence of clause 'collapse' with number of loops, it will
14167 // define the nested loops number.
14168 unsigned NestedLoopCount =
14169 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
14170 nullptr /*ordered not a clause on distribute*/, AStmt,
14171 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14172 if (NestedLoopCount == 0)
14173 return StmtError();
14174
14175 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14176 "omp for loop exprs were not built");
14177
14178 SemaRef.setFunctionHasBranchProtectedScope();
14179 auto *DistributeDirective = OMPDistributeDirective::Create(
14180 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14181 return DistributeDirective;
14182}
14183
14185 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14186 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14187 if (!AStmt)
14188 return StmtError();
14189
14190 CapturedStmt *CS =
14191 setBranchProtectedScope(SemaRef, OMPD_distribute_parallel_for, AStmt);
14192
14193 OMPLoopBasedDirective::HelperExprs B;
14194 // In presence of clause 'collapse' with number of loops, it will
14195 // define the nested loops number.
14196 unsigned NestedLoopCount = checkOpenMPLoop(
14197 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14198 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14199 VarsWithImplicitDSA, B);
14200 if (NestedLoopCount == 0)
14201 return StmtError();
14202
14203 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14204 "omp for loop exprs were not built");
14205
14207 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14208 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14209}
14210
14212 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14213 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14214 if (!AStmt)
14215 return StmtError();
14216
14218 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
14219
14220 OMPLoopBasedDirective::HelperExprs B;
14221 // In presence of clause 'collapse' with number of loops, it will
14222 // define the nested loops number.
14223 unsigned NestedLoopCount = checkOpenMPLoop(
14224 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14225 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14226 VarsWithImplicitDSA, B);
14227 if (NestedLoopCount == 0)
14228 return StmtError();
14229
14230 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14231 return StmtError();
14232
14234 return StmtError();
14235
14237 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14238}
14239
14241 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14242 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14243 if (!AStmt)
14244 return StmtError();
14245
14246 CapturedStmt *CS =
14247 setBranchProtectedScope(SemaRef, OMPD_distribute_simd, AStmt);
14248
14249 OMPLoopBasedDirective::HelperExprs B;
14250 // In presence of clause 'collapse' with number of loops, it will
14251 // define the nested loops number.
14252 unsigned NestedLoopCount =
14253 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
14254 nullptr /*ordered not a clause on distribute*/, CS,
14255 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14256 if (NestedLoopCount == 0)
14257 return StmtError();
14258
14259 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14260 return StmtError();
14261
14263 return StmtError();
14264
14265 return OMPDistributeSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
14266 NestedLoopCount, Clauses, AStmt, B);
14267}
14268
14270 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14271 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14272 if (!AStmt)
14273 return StmtError();
14274
14275 CapturedStmt *CS =
14276 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for_simd, AStmt);
14277
14278 OMPLoopBasedDirective::HelperExprs B;
14279 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14280 // define the nested loops number.
14281 unsigned NestedLoopCount = checkOpenMPLoop(
14282 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
14283 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
14284 VarsWithImplicitDSA, B);
14285 if (NestedLoopCount == 0)
14286 return StmtError();
14287
14288 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14289 return StmtError();
14290
14292 return StmtError();
14293
14295 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14296}
14297
14299 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14300 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14301 if (!AStmt)
14302 return StmtError();
14303
14304 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target_simd, AStmt);
14305
14306 OMPLoopBasedDirective::HelperExprs B;
14307 // In presence of clause 'collapse' with number of loops, it will define the
14308 // nested loops number.
14309 unsigned NestedLoopCount =
14310 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
14311 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
14312 VarsWithImplicitDSA, B);
14313 if (NestedLoopCount == 0)
14314 return StmtError();
14315
14316 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14317 return StmtError();
14318
14320 return StmtError();
14321
14322 return OMPTargetSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
14323 NestedLoopCount, Clauses, AStmt, B);
14324}
14325
14327 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14328 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14329 if (!AStmt)
14330 return StmtError();
14331
14332 CapturedStmt *CS =
14333 setBranchProtectedScope(SemaRef, OMPD_teams_distribute, AStmt);
14334
14335 OMPLoopBasedDirective::HelperExprs B;
14336 // In presence of clause 'collapse' with number of loops, it will
14337 // define the nested loops number.
14338 unsigned NestedLoopCount =
14339 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
14340 nullptr /*ordered not a clause on distribute*/, CS,
14341 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14342 if (NestedLoopCount == 0)
14343 return StmtError();
14344
14345 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14346 "omp teams distribute loop exprs were not built");
14347
14348 DSAStack->setParentTeamsRegionLoc(StartLoc);
14349
14351 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14352}
14353
14355 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14356 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14357 if (!AStmt)
14358 return StmtError();
14359
14360 CapturedStmt *CS =
14361 setBranchProtectedScope(SemaRef, OMPD_teams_distribute_simd, AStmt);
14362
14363 OMPLoopBasedDirective::HelperExprs B;
14364 // In presence of clause 'collapse' with number of loops, it will
14365 // define the nested loops number.
14366 unsigned NestedLoopCount = checkOpenMPLoop(
14367 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14368 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14369 VarsWithImplicitDSA, B);
14370 if (NestedLoopCount == 0)
14371 return StmtError();
14372
14373 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14374 return StmtError();
14375
14377 return StmtError();
14378
14379 DSAStack->setParentTeamsRegionLoc(StartLoc);
14380
14382 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14383}
14384
14386 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14387 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14388 if (!AStmt)
14389 return StmtError();
14390
14392 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
14393
14394 OMPLoopBasedDirective::HelperExprs B;
14395 // In presence of clause 'collapse' with number of loops, it will
14396 // define the nested loops number.
14397 unsigned NestedLoopCount = checkOpenMPLoop(
14398 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14399 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14400 VarsWithImplicitDSA, B);
14401 if (NestedLoopCount == 0)
14402 return StmtError();
14403
14404 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14405 return StmtError();
14406
14408 return StmtError();
14409
14410 DSAStack->setParentTeamsRegionLoc(StartLoc);
14411
14413 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14414}
14415
14417 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14418 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14419 if (!AStmt)
14420 return StmtError();
14421
14423 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
14424
14425 OMPLoopBasedDirective::HelperExprs B;
14426 // In presence of clause 'collapse' with number of loops, it will
14427 // define the nested loops number.
14428 unsigned NestedLoopCount = checkOpenMPLoop(
14429 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14430 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14431 VarsWithImplicitDSA, B);
14432
14433 if (NestedLoopCount == 0)
14434 return StmtError();
14435
14436 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14437 "omp for loop exprs were not built");
14438
14439 DSAStack->setParentTeamsRegionLoc(StartLoc);
14440
14442 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14443 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14444}
14445
14447 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14448 SourceLocation EndLoc) {
14449 if (!AStmt)
14450 return StmtError();
14451
14452 setBranchProtectedScope(SemaRef, OMPD_target_teams, AStmt);
14453
14454 if (checkMultidimClauses(*this, Clauses, /*MayHaveBareClause=*/true))
14455 return StmtError();
14456
14457 return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc,
14458 Clauses, AStmt);
14459}
14460
14462 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14463 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14464 if (!AStmt)
14465 return StmtError();
14466
14467 if (checkMultidimClauses(*this, Clauses))
14468 return StmtError();
14469
14470 CapturedStmt *CS =
14471 setBranchProtectedScope(SemaRef, OMPD_target_teams_distribute, AStmt);
14472
14473 OMPLoopBasedDirective::HelperExprs B;
14474 // In presence of clause 'collapse' with number of loops, it will
14475 // define the nested loops number.
14476 unsigned NestedLoopCount = checkOpenMPLoop(
14477 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14478 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14479 VarsWithImplicitDSA, B);
14480 if (NestedLoopCount == 0)
14481 return StmtError();
14482
14483 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14484 "omp target teams distribute loop exprs were not built");
14485
14487 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14488}
14489
14491 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14492 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14493 if (!AStmt)
14494 return StmtError();
14495
14496 if (checkMultidimClauses(*this, Clauses))
14497 return StmtError();
14498
14500 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14501
14502 OMPLoopBasedDirective::HelperExprs B;
14503 // In presence of clause 'collapse' with number of loops, it will
14504 // define the nested loops number.
14505 unsigned NestedLoopCount = checkOpenMPLoop(
14506 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14507 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14508 VarsWithImplicitDSA, B);
14509 if (NestedLoopCount == 0)
14510 return StmtError();
14511
14512 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14513 return StmtError();
14514
14516 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14517 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14518}
14519
14521 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14522 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14523 if (!AStmt)
14524 return StmtError();
14525
14526 if (checkMultidimClauses(*this, Clauses))
14527 return StmtError();
14528
14530 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14531
14532 OMPLoopBasedDirective::HelperExprs B;
14533 // In presence of clause 'collapse' with number of loops, it will
14534 // define the nested loops number.
14535 unsigned NestedLoopCount =
14536 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14537 getCollapseNumberExpr(Clauses),
14538 nullptr /*ordered not a clause on distribute*/, CS,
14539 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14540 if (NestedLoopCount == 0)
14541 return StmtError();
14542
14543 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14544 return StmtError();
14545
14547 return StmtError();
14548
14550 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14551}
14552
14554 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14555 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14556 if (!AStmt)
14557 return StmtError();
14558
14559 if (checkMultidimClauses(*this, Clauses))
14560 return StmtError();
14561
14563 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14564
14565 OMPLoopBasedDirective::HelperExprs B;
14566 // In presence of clause 'collapse' with number of loops, it will
14567 // define the nested loops number.
14568 unsigned NestedLoopCount = checkOpenMPLoop(
14569 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14570 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14571 VarsWithImplicitDSA, B);
14572 if (NestedLoopCount == 0)
14573 return StmtError();
14574
14575 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14576 return StmtError();
14577
14579 return StmtError();
14580
14582 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14583}
14584
14585/// Updates OriginalInits by checking Transform against loop transformation
14586/// directives and appending their pre-inits if a match is found.
14588 SmallVectorImpl<Stmt *> &PreInits) {
14589 Stmt *Dir = Transform->getDirective();
14590 switch (Dir->getStmtClass()) {
14591#define STMT(CLASS, PARENT)
14592#define ABSTRACT_STMT(CLASS)
14593#define COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT) \
14594 case Stmt::CLASS##Class: \
14595 appendFlattenedStmtList(PreInits, \
14596 static_cast<const CLASS *>(Dir)->getPreInits()); \
14597 break;
14598#define OMPCANONICALLOOPNESTTRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14599 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14600#define OMPCANONICALLOOPSEQUENCETRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14601 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14602#include "clang/AST/StmtNodes.inc"
14603#undef COMMON_OMP_LOOP_TRANSFORMATION
14604 default:
14605 llvm_unreachable("Not a loop transformation");
14606 }
14607}
14608
14609bool SemaOpenMP::checkTransformableLoopNest(
14610 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14612 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *>> &OriginalInits) {
14613 OriginalInits.emplace_back();
14614 bool Result = OMPLoopBasedDirective::doForAllLoops(
14615 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14616 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14617 Stmt *CurStmt) {
14618 VarsWithInheritedDSAType TmpDSA;
14619 unsigned SingleNumLoops =
14620 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14621 TmpDSA, LoopHelpers[Cnt]);
14622 if (SingleNumLoops == 0)
14623 return true;
14624 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14625 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14626 OriginalInits.back().push_back(For->getInit());
14627 Body = For->getBody();
14628 } else {
14629 assert(isa<CXXForRangeStmt>(CurStmt) &&
14630 "Expected canonical for or range-based for loops.");
14631 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14632 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14633 Body = CXXFor->getBody();
14634 }
14635 OriginalInits.emplace_back();
14636 return false;
14637 },
14638 [&OriginalInits](OMPLoopTransformationDirective *Transform) {
14639 updatePreInits(Transform, OriginalInits.back());
14640 });
14641 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14642 OriginalInits.pop_back();
14643 return Result;
14644}
14645
14646/// Counts the total number of OpenMP canonical nested loops, including the
14647/// outermost loop (the original loop). PRECONDITION of this visitor is that it
14648/// must be invoked from the original loop to be analyzed. The traversal stops
14649/// for Decl's and Expr's given that they may contain inner loops that must not
14650/// be counted.
14651///
14652/// Example AST structure for the code:
14653///
14654/// int main() {
14655/// #pragma omp fuse
14656/// {
14657/// for (int i = 0; i < 100; i++) { <-- Outer loop
14658/// []() {
14659/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (1)
14660/// };
14661/// for(int j = 0; j < 5; ++j) {} <-- Inner loop
14662/// }
14663/// for (int r = 0; i < 100; i++) { <-- Outer loop
14664/// struct LocalClass {
14665/// void bar() {
14666/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (2)
14667/// }
14668/// };
14669/// for(int k = 0; k < 10; ++k) {} <-- Inner loop
14670/// {x = 5; for(k = 0; k < 10; ++k) x += k; x}; <-- NOT A LOOP (3)
14671/// }
14672/// }
14673/// }
14674/// (1) because in a different function (here: a lambda)
14675/// (2) because in a different function (here: class method)
14676/// (3) because considered to be intervening-code of non-perfectly nested loop
14677/// Result: Loop 'i' contains 2 loops, Loop 'r' also contains 2 loops.
14679private:
14680 unsigned NestedLoopCount = 0;
14681
14682public:
14683 explicit NestedLoopCounterVisitor() = default;
14684
14685 unsigned getNestedLoopCount() const { return NestedLoopCount; }
14686
14687 bool VisitForStmt(ForStmt *FS) override {
14688 ++NestedLoopCount;
14689 return true;
14690 }
14691
14693 ++NestedLoopCount;
14694 return true;
14695 }
14696
14697 bool TraverseStmt(Stmt *S) override {
14698 if (!S)
14699 return true;
14700
14701 // Skip traversal of all expressions, including special cases like
14702 // LambdaExpr, StmtExpr, BlockExpr, and RequiresExpr. These expressions
14703 // may contain inner statements (and even loops), but they are not part
14704 // of the syntactic body of the surrounding loop structure.
14705 // Therefore must not be counted.
14706 if (isa<Expr>(S))
14707 return true;
14708
14709 // Only recurse into CompoundStmt (block {}) and loop bodies.
14712 }
14713
14714 // Stop traversal of the rest of statements, that break perfect
14715 // loop nesting, such as control flow (IfStmt, SwitchStmt...).
14716 return true;
14717 }
14718
14719 bool TraverseDecl(Decl *D) override {
14720 // Stop in the case of finding a declaration, it is not important
14721 // in order to find nested loops (Possible CXXRecordDecl, RecordDecl,
14722 // FunctionDecl...).
14723 return true;
14724 }
14725};
14726
14727bool SemaOpenMP::analyzeLoopSequence(Stmt *LoopSeqStmt,
14728 LoopSequenceAnalysis &SeqAnalysis,
14729 ASTContext &Context,
14730 OpenMPDirectiveKind Kind) {
14732 // Helper Lambda to handle storing initialization and body statements for
14733 // both ForStmt and CXXForRangeStmt.
14734 auto StoreLoopStatements = [](LoopAnalysis &Analysis, Stmt *LoopStmt) {
14735 if (auto *For = dyn_cast<ForStmt>(LoopStmt)) {
14736 Analysis.OriginalInits.push_back(For->getInit());
14737 Analysis.TheForStmt = For;
14738 } else {
14739 auto *CXXFor = cast<CXXForRangeStmt>(LoopStmt);
14740 Analysis.OriginalInits.push_back(CXXFor->getBeginStmt());
14741 Analysis.TheForStmt = CXXFor;
14742 }
14743 };
14744
14745 // Helper lambda functions to encapsulate the processing of different
14746 // derivations of the canonical loop sequence grammar
14747 // Modularized code for handling loop generation and transformations.
14748 auto AnalyzeLoopGeneration = [&](Stmt *Child) {
14749 auto *LoopTransform = cast<OMPLoopTransformationDirective>(Child);
14750 Stmt *TransformedStmt = LoopTransform->getTransformedStmt();
14751 unsigned NumGeneratedTopLevelLoops =
14752 LoopTransform->getNumGeneratedTopLevelLoops();
14753 // Handle the case where transformed statement is not available due to
14754 // dependent contexts
14755 if (!TransformedStmt) {
14756 if (NumGeneratedTopLevelLoops > 0) {
14757 SeqAnalysis.LoopSeqSize += NumGeneratedTopLevelLoops;
14758 return true;
14759 }
14760 // Unroll full (0 loops produced)
14761 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14762 << 0 << getOpenMPDirectiveName(Kind);
14763 return false;
14764 }
14765 // Handle loop transformations with multiple loop nests
14766 // Unroll full
14767 if (!NumGeneratedTopLevelLoops) {
14768 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14769 << 0 << getOpenMPDirectiveName(Kind);
14770 return false;
14771 }
14772 // Loop transformatons such as split or loopranged fuse
14773 if (NumGeneratedTopLevelLoops > 1) {
14774 // Get the preinits related to this loop sequence generating
14775 // loop transformation (i.e loopranged fuse, split...)
14776 // These preinits differ slightly from regular inits/pre-inits related
14777 // to single loop generating loop transformations (interchange, unroll)
14778 // given that they are not bounded to a particular loop nest
14779 // so they need to be treated independently
14780 updatePreInits(LoopTransform, SeqAnalysis.LoopSequencePreInits);
14781 return analyzeLoopSequence(TransformedStmt, SeqAnalysis, Context, Kind);
14782 }
14783 // Vast majority: (Tile, Unroll, Stripe, Reverse, Interchange, Fuse all)
14784 // Process the transformed loop statement
14785 LoopAnalysis &NewTransformedSingleLoop =
14786 SeqAnalysis.Loops.emplace_back(Child);
14787 unsigned IsCanonical = checkOpenMPLoop(
14788 Kind, nullptr, nullptr, TransformedStmt, SemaRef, *DSAStack, TmpDSA,
14789 NewTransformedSingleLoop.HelperExprs);
14790
14791 if (!IsCanonical)
14792 return false;
14793
14794 StoreLoopStatements(NewTransformedSingleLoop, TransformedStmt);
14795 updatePreInits(LoopTransform, NewTransformedSingleLoop.TransformsPreInits);
14796
14797 SeqAnalysis.LoopSeqSize++;
14798 return true;
14799 };
14800
14801 // Modularized code for handling regular canonical loops.
14802 auto AnalyzeRegularLoop = [&](Stmt *Child) {
14803 LoopAnalysis &NewRegularLoop = SeqAnalysis.Loops.emplace_back(Child);
14804 unsigned IsCanonical =
14805 checkOpenMPLoop(Kind, nullptr, nullptr, Child, SemaRef, *DSAStack,
14806 TmpDSA, NewRegularLoop.HelperExprs);
14807
14808 if (!IsCanonical)
14809 return false;
14810
14811 StoreLoopStatements(NewRegularLoop, Child);
14812 NestedLoopCounterVisitor NLCV;
14813 NLCV.TraverseStmt(Child);
14814 return true;
14815 };
14816
14817 // High level grammar validation.
14818 for (Stmt *Child : LoopSeqStmt->children()) {
14819 if (!Child)
14820 continue;
14821 // Skip over non-loop-sequence statements.
14822 if (!LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14823 Child = Child->IgnoreContainers();
14824 // Ignore empty compound statement.
14825 if (!Child)
14826 continue;
14827 // In the case of a nested loop sequence ignoring containers would not
14828 // be enough, a recurisve transversal of the loop sequence is required.
14829 if (isa<CompoundStmt>(Child)) {
14830 if (!analyzeLoopSequence(Child, SeqAnalysis, Context, Kind))
14831 return false;
14832 // Already been treated, skip this children
14833 continue;
14834 }
14835 }
14836 // Regular loop sequence handling.
14837 if (LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14838 if (LoopAnalysis::isLoopTransformation(Child)) {
14839 if (!AnalyzeLoopGeneration(Child))
14840 return false;
14841 // AnalyzeLoopGeneration updates SeqAnalysis.LoopSeqSize accordingly.
14842 } else {
14843 if (!AnalyzeRegularLoop(Child))
14844 return false;
14845 SeqAnalysis.LoopSeqSize++;
14846 }
14847 } else {
14848 // Report error for invalid statement inside canonical loop sequence.
14849 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14850 << 0 << getOpenMPDirectiveName(Kind);
14851 return false;
14852 }
14853 }
14854 return true;
14855}
14856
14857bool SemaOpenMP::checkTransformableLoopSequence(
14858 OpenMPDirectiveKind Kind, Stmt *AStmt, LoopSequenceAnalysis &SeqAnalysis,
14859 ASTContext &Context) {
14860 // Following OpenMP 6.0 API Specification, a Canonical Loop Sequence follows
14861 // the grammar:
14862 //
14863 // canonical-loop-sequence:
14864 // {
14865 // loop-sequence+
14866 // }
14867 // where loop-sequence can be any of the following:
14868 // 1. canonical-loop-sequence
14869 // 2. loop-nest
14870 // 3. loop-sequence-generating-construct (i.e OMPLoopTransformationDirective)
14871 //
14872 // To recognise and traverse this structure the helper function
14873 // analyzeLoopSequence serves as the recurisve entry point
14874 // and tries to match the input AST to the canonical loop sequence grammar
14875 // structure. This function will perform both a semantic and syntactical
14876 // analysis of the given statement according to OpenMP 6.0 definition of
14877 // the aforementioned canonical loop sequence.
14878
14879 // We expect an outer compound statement.
14880 if (!isa<CompoundStmt>(AStmt)) {
14881 Diag(AStmt->getBeginLoc(), diag::err_omp_not_a_loop_sequence)
14882 << getOpenMPDirectiveName(Kind);
14883 return false;
14884 }
14885
14886 // Recursive entry point to process the main loop sequence
14887 if (!analyzeLoopSequence(AStmt, SeqAnalysis, Context, Kind))
14888 return false;
14889
14890 // Diagnose an empty loop sequence.
14891 if (!SeqAnalysis.LoopSeqSize) {
14892 Diag(AStmt->getBeginLoc(), diag::err_omp_empty_loop_sequence)
14893 << getOpenMPDirectiveName(Kind);
14894 return false;
14895 }
14896 return true;
14897}
14898
14899/// Add preinit statements that need to be propagated from the selected loop.
14900static void addLoopPreInits(ASTContext &Context,
14901 OMPLoopBasedDirective::HelperExprs &LoopHelper,
14902 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
14903 SmallVectorImpl<Stmt *> &PreInits) {
14904
14905 // For range-based for-statements, ensure that their syntactic sugar is
14906 // executed by adding them as pre-init statements.
14907 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14908 Stmt *RangeInit = CXXRangeFor->getInit();
14909 if (RangeInit)
14910 PreInits.push_back(RangeInit);
14911
14912 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14913 PreInits.push_back(new (Context) DeclStmt(RangeStmt->getDeclGroup(),
14914 RangeStmt->getBeginLoc(),
14915 RangeStmt->getEndLoc()));
14916
14917 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14918 PreInits.push_back(new (Context) DeclStmt(RangeEnd->getDeclGroup(),
14919 RangeEnd->getBeginLoc(),
14920 RangeEnd->getEndLoc()));
14921 }
14922
14923 llvm::append_range(PreInits, OriginalInit);
14924
14925 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
14926 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
14927 PreInits.push_back(new (Context) DeclStmt(
14928 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14929 }
14930
14931 // Gather declarations for the data members used as counters.
14932 for (Expr *CounterRef : LoopHelper.Counters) {
14933 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14934 if (isa<OMPCapturedExprDecl>(CounterDecl))
14935 PreInits.push_back(new (Context) DeclStmt(
14936 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
14937 }
14938}
14939
14940/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
14941/// loop of a construct.
14942static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) {
14943 size_t NumLoops = LoopStmts.size();
14944 OMPLoopBasedDirective::doForAllLoops(
14945 AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
14946 [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
14947 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
14948 LoopStmts[Cnt] = CurStmt;
14949 return false;
14950 });
14951 assert(!is_contained(LoopStmts, nullptr) &&
14952 "Expecting a loop statement for each affected loop");
14953}
14954
14955/// Build and return a DeclRefExpr for the floor induction variable using the
14956/// SemaRef and the provided parameters.
14957static Expr *makeFloorIVRef(Sema &SemaRef, ArrayRef<VarDecl *> FloorIndVars,
14958 int I, QualType IVTy, DeclRefExpr *OrigCntVar) {
14959 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14960 OrigCntVar->getExprLoc());
14961}
14962
14964 Stmt *AStmt,
14965 SourceLocation StartLoc,
14966 SourceLocation EndLoc) {
14967 ASTContext &Context = getASTContext();
14968 Scope *CurScope = SemaRef.getCurScope();
14969
14970 const auto *SizesClause =
14971 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14972 if (!SizesClause ||
14973 llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; }))
14974 return StmtError();
14975 unsigned NumLoops = SizesClause->getNumSizes();
14976
14977 // Empty statement should only be possible if there already was an error.
14978 if (!AStmt)
14979 return StmtError();
14980
14981 // Verify and diagnose loop nest.
14983 Stmt *Body = nullptr;
14984 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
14985 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14986 OriginalInits))
14987 return StmtError();
14988
14989 // Delay tiling to when template is completely instantiated.
14990 if (SemaRef.CurContext->isDependentContext())
14991 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14992 NumLoops, AStmt, nullptr, nullptr);
14993
14994 assert(LoopHelpers.size() == NumLoops &&
14995 "Expecting loop iteration space dimensionality to match number of "
14996 "affected loops");
14997 assert(OriginalInits.size() == NumLoops &&
14998 "Expecting loop iteration space dimensionality to match number of "
14999 "affected loops");
15000
15001 // Collect all affected loop statements.
15002 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15003 collectLoopStmts(AStmt, LoopStmts);
15004
15005 SmallVector<Stmt *, 4> PreInits;
15006 CaptureVars CopyTransformer(SemaRef);
15007
15008 // Create iteration variables for the generated loops.
15009 SmallVector<VarDecl *, 4> FloorIndVars;
15010 SmallVector<VarDecl *, 4> TileIndVars;
15011 FloorIndVars.resize(NumLoops);
15012 TileIndVars.resize(NumLoops);
15013 for (unsigned I = 0; I < NumLoops; ++I) {
15014 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15015
15016 assert(LoopHelper.Counters.size() == 1 &&
15017 "Expect single-dimensional loop iteration space");
15018 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15019 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15020 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15021 QualType CntTy = IterVarRef->getType();
15022
15023 // Iteration variable for the floor (i.e. outer) loop.
15024 {
15025 std::string FloorCntName =
15026 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15027 VarDecl *FloorCntDecl =
15028 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
15029 FloorIndVars[I] = FloorCntDecl;
15030 }
15031
15032 // Iteration variable for the tile (i.e. inner) loop.
15033 {
15034 std::string TileCntName =
15035 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15036
15037 // Reuse the iteration variable created by checkOpenMPLoop. It is also
15038 // used by the expressions to derive the original iteration variable's
15039 // value from the logical iteration number.
15040 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15041 TileCntDecl->setDeclName(
15042 &SemaRef.PP.getIdentifierTable().get(TileCntName));
15043 TileIndVars[I] = TileCntDecl;
15044 }
15045
15046 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
15047 PreInits);
15048 }
15049
15050 // Once the original iteration values are set, append the innermost body.
15051 Stmt *Inner = Body;
15052
15053 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
15054 SizesClause, CurScope](int I) -> Expr * {
15055 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
15056
15057 if (DimTileSizeExpr->containsErrors())
15058 return nullptr;
15059
15060 if (isa<ConstantExpr>(DimTileSizeExpr))
15061 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
15062
15063 // When the tile size is not a constant but a variable, it is possible to
15064 // pass non-positive numbers. For instance:
15065 // \code{c}
15066 // int a = 0;
15067 // #pragma omp tile sizes(a)
15068 // for (int i = 0; i < 42; ++i)
15069 // body(i);
15070 // \endcode
15071 // Although there is no meaningful interpretation of the tile size, the body
15072 // should still be executed 42 times to avoid surprises. To preserve the
15073 // invariant that every loop iteration is executed exactly once and not
15074 // cause an infinite loop, apply a minimum tile size of one.
15075 // Build expr:
15076 // \code{c}
15077 // (TS <= 0) ? 1 : TS
15078 // \endcode
15079 QualType DimTy = DimTileSizeExpr->getType();
15080 uint64_t DimWidth = Context.getTypeSize(DimTy);
15082 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
15083 IntegerLiteral *One =
15084 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
15085 Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
15086 CurScope, {}, BO_LE,
15087 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
15088 Expr *MinOne = new (Context) ConditionalOperator(
15089 Cond, {}, One, {},
15090 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
15092 return MinOne;
15093 };
15094
15095 // Create tile loops from the inside to the outside.
15096 for (int I = NumLoops - 1; I >= 0; --I) {
15097 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15098 Expr *NumIterations = LoopHelper.NumIterations;
15099 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15100 QualType IVTy = NumIterations->getType();
15101 Stmt *LoopStmt = LoopStmts[I];
15102
15103 // Commonly used variables. One of the constraints of an AST is that every
15104 // node object must appear at most once, hence we define a lambda that
15105 // creates a new AST node at every use.
15106 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
15107 OrigCntVar]() {
15108 return buildDeclRefExpr(SemaRef, TileIndVars[I], IVTy,
15109 OrigCntVar->getExprLoc());
15110 };
15111
15112 // For init-statement: auto .tile.iv = .floor.iv
15113 SemaRef.AddInitializerToDecl(
15114 TileIndVars[I],
15115 SemaRef
15116 .DefaultLvalueConversion(
15117 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
15118 .get(),
15119 /*DirectInit=*/false);
15120 Decl *CounterDecl = TileIndVars[I];
15121 StmtResult InitStmt = new (Context)
15122 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15123 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15124 if (!InitStmt.isUsable())
15125 return StmtError();
15126
15127 // For cond-expression:
15128 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
15129 Expr *DimTileSize = MakeDimTileSize(I);
15130 if (!DimTileSize)
15131 return StmtError();
15132 ExprResult EndOfTile = SemaRef.BuildBinOp(
15133 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15134 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15135 DimTileSize);
15136 if (!EndOfTile.isUsable())
15137 return StmtError();
15138 ExprResult IsPartialTile =
15139 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15140 NumIterations, EndOfTile.get());
15141 if (!IsPartialTile.isUsable())
15142 return StmtError();
15143 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
15144 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15145 IsPartialTile.get(), NumIterations, EndOfTile.get());
15146 if (!MinTileAndIterSpace.isUsable())
15147 return StmtError();
15148 ExprResult CondExpr =
15149 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15150 MakeTileIVRef(), MinTileAndIterSpace.get());
15151 if (!CondExpr.isUsable())
15152 return StmtError();
15153
15154 // For incr-statement: ++.tile.iv
15155 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15156 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
15157 if (!IncrStmt.isUsable())
15158 return StmtError();
15159
15160 // Statements to set the original iteration variable's value from the
15161 // logical iteration number.
15162 // Generated for loop is:
15163 // \code
15164 // Original_for_init;
15165 // for (auto .tile.iv = .floor.iv;
15166 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
15167 // ++.tile.iv) {
15168 // Original_Body;
15169 // Original_counter_update;
15170 // }
15171 // \endcode
15172 // FIXME: If the innermost body is an loop itself, inserting these
15173 // statements stops it being recognized as a perfectly nested loop (e.g.
15174 // for applying tiling again). If this is the case, sink the expressions
15175 // further into the inner loop.
15176 SmallVector<Stmt *, 4> BodyParts;
15177 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15178 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15179 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15180 BodyParts.push_back(Inner);
15181 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15182 Inner->getBeginLoc(), Inner->getEndLoc());
15183 Inner = new (Context)
15184 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15185 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15186 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15187 }
15188
15189 // Create floor loops from the inside to the outside.
15190 for (int I = NumLoops - 1; I >= 0; --I) {
15191 auto &LoopHelper = LoopHelpers[I];
15192 Expr *NumIterations = LoopHelper.NumIterations;
15193 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15194 QualType IVTy = NumIterations->getType();
15195
15196 // For init-statement: auto .floor.iv = 0
15197 SemaRef.AddInitializerToDecl(
15198 FloorIndVars[I],
15199 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15200 /*DirectInit=*/false);
15201 Decl *CounterDecl = FloorIndVars[I];
15202 StmtResult InitStmt = new (Context)
15203 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15204 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15205 if (!InitStmt.isUsable())
15206 return StmtError();
15207
15208 // For cond-expression: .floor.iv < NumIterations
15209 ExprResult CondExpr = SemaRef.BuildBinOp(
15210 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15211 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15212 NumIterations);
15213 if (!CondExpr.isUsable())
15214 return StmtError();
15215
15216 // For incr-statement: .floor.iv += DimTileSize
15217 Expr *DimTileSize = MakeDimTileSize(I);
15218 if (!DimTileSize)
15219 return StmtError();
15220 ExprResult IncrStmt = SemaRef.BuildBinOp(
15221 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15222 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15223 DimTileSize);
15224 if (!IncrStmt.isUsable())
15225 return StmtError();
15226
15227 Inner = new (Context)
15228 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15229 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15230 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15231 }
15232
15233 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
15234 AStmt, Inner,
15235 buildPreInits(Context, PreInits));
15236}
15237
15239 Stmt *AStmt,
15240 SourceLocation StartLoc,
15241 SourceLocation EndLoc) {
15242 ASTContext &Context = getASTContext();
15243 Scope *CurScope = SemaRef.getCurScope();
15244
15245 const auto *SizesClause =
15246 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
15247 if (!SizesClause ||
15248 llvm::any_of(SizesClause->getSizesRefs(), [](const Expr *SizeExpr) {
15249 return !SizeExpr || SizeExpr->containsErrors();
15250 }))
15251 return StmtError();
15252 unsigned NumLoops = SizesClause->getNumSizes();
15253
15254 // Empty statement should only be possible if there already was an error.
15255 if (!AStmt)
15256 return StmtError();
15257
15258 // Verify and diagnose loop nest.
15260 Stmt *Body = nullptr;
15261 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
15262 if (!checkTransformableLoopNest(OMPD_stripe, AStmt, NumLoops, LoopHelpers,
15263 Body, OriginalInits))
15264 return StmtError();
15265
15266 // Delay striping to when template is completely instantiated.
15267 if (SemaRef.CurContext->isDependentContext())
15268 return OMPStripeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15269 NumLoops, AStmt, nullptr, nullptr);
15270
15271 assert(LoopHelpers.size() == NumLoops &&
15272 "Expecting loop iteration space dimensionality to match number of "
15273 "affected loops");
15274 assert(OriginalInits.size() == NumLoops &&
15275 "Expecting loop iteration space dimensionality to match number of "
15276 "affected loops");
15277
15278 // Collect all affected loop statements.
15279 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15280 collectLoopStmts(AStmt, LoopStmts);
15281
15282 SmallVector<Stmt *, 4> PreInits;
15283 CaptureVars CopyTransformer(SemaRef);
15284
15285 // Create iteration variables for the generated loops.
15286 SmallVector<VarDecl *, 4> FloorIndVars;
15287 SmallVector<VarDecl *, 4> StripeIndVars;
15288 FloorIndVars.resize(NumLoops);
15289 StripeIndVars.resize(NumLoops);
15290 for (unsigned I : llvm::seq<unsigned>(NumLoops)) {
15291 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15292
15293 assert(LoopHelper.Counters.size() == 1 &&
15294 "Expect single-dimensional loop iteration space");
15295 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15296 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15297 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15298 QualType CntTy = IterVarRef->getType();
15299
15300 // Iteration variable for the stripe (i.e. outer) loop.
15301 {
15302 std::string FloorCntName =
15303 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15304 VarDecl *FloorCntDecl =
15305 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
15306 FloorIndVars[I] = FloorCntDecl;
15307 }
15308
15309 // Iteration variable for the stripe (i.e. inner) loop.
15310 {
15311 std::string StripeCntName =
15312 (Twine(".stripe_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15313
15314 // Reuse the iteration variable created by checkOpenMPLoop. It is also
15315 // used by the expressions to derive the original iteration variable's
15316 // value from the logical iteration number.
15317 auto *StripeCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15318 StripeCntDecl->setDeclName(
15319 &SemaRef.PP.getIdentifierTable().get(StripeCntName));
15320 StripeIndVars[I] = StripeCntDecl;
15321 }
15322
15323 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
15324 PreInits);
15325 }
15326
15327 // Once the original iteration values are set, append the innermost body.
15328 Stmt *Inner = Body;
15329
15330 auto MakeDimStripeSize = [&](int I) -> Expr * {
15331 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
15332 if (isa<ConstantExpr>(DimStripeSizeExpr))
15333 return AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr));
15334
15335 // When the stripe size is not a constant but a variable, it is possible to
15336 // pass non-positive numbers. For instance:
15337 // \code{c}
15338 // int a = 0;
15339 // #pragma omp stripe sizes(a)
15340 // for (int i = 0; i < 42; ++i)
15341 // body(i);
15342 // \endcode
15343 // Although there is no meaningful interpretation of the stripe size, the
15344 // body should still be executed 42 times to avoid surprises. To preserve
15345 // the invariant that every loop iteration is executed exactly once and not
15346 // cause an infinite loop, apply a minimum stripe size of one.
15347 // Build expr:
15348 // \code{c}
15349 // (TS <= 0) ? 1 : TS
15350 // \endcode
15351 QualType DimTy = DimStripeSizeExpr->getType();
15352 uint64_t DimWidth = Context.getTypeSize(DimTy);
15354 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
15355 IntegerLiteral *One =
15356 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
15357 Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
15358 CurScope, {}, BO_LE,
15359 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), Zero));
15360 Expr *MinOne = new (Context) ConditionalOperator(
15361 Cond, {}, One, {},
15362 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), DimTy,
15364 return MinOne;
15365 };
15366
15367 // Create stripe loops from the inside to the outside.
15368 for (int I = NumLoops - 1; I >= 0; --I) {
15369 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15370 Expr *NumIterations = LoopHelper.NumIterations;
15371 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15372 QualType IVTy = NumIterations->getType();
15373 Stmt *LoopStmt = LoopStmts[I];
15374
15375 // For init-statement: auto .stripe.iv = .floor.iv
15376 SemaRef.AddInitializerToDecl(
15377 StripeIndVars[I],
15378 SemaRef
15379 .DefaultLvalueConversion(
15380 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
15381 .get(),
15382 /*DirectInit=*/false);
15383 Decl *CounterDecl = StripeIndVars[I];
15384 StmtResult InitStmt = new (Context)
15385 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15386 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15387 if (!InitStmt.isUsable())
15388 return StmtError();
15389
15390 // For cond-expression:
15391 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations)
15392 ExprResult EndOfStripe = SemaRef.BuildBinOp(
15393 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15394 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15395 MakeDimStripeSize(I));
15396 if (!EndOfStripe.isUsable())
15397 return StmtError();
15398 ExprResult IsPartialStripe =
15399 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15400 NumIterations, EndOfStripe.get());
15401 if (!IsPartialStripe.isUsable())
15402 return StmtError();
15403 ExprResult MinStripeAndIterSpace = SemaRef.ActOnConditionalOp(
15404 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15405 IsPartialStripe.get(), NumIterations, EndOfStripe.get());
15406 if (!MinStripeAndIterSpace.isUsable())
15407 return StmtError();
15408 ExprResult CondExpr = SemaRef.BuildBinOp(
15409 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15410 makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar),
15411 MinStripeAndIterSpace.get());
15412 if (!CondExpr.isUsable())
15413 return StmtError();
15414
15415 // For incr-statement: ++.stripe.iv
15416 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15417 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc,
15418 makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar));
15419 if (!IncrStmt.isUsable())
15420 return StmtError();
15421
15422 // Statements to set the original iteration variable's value from the
15423 // logical iteration number.
15424 // Generated for loop is:
15425 // \code
15426 // Original_for_init;
15427 // for (auto .stripe.iv = .floor.iv;
15428 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations);
15429 // ++.stripe.iv) {
15430 // Original_Body;
15431 // Original_counter_update;
15432 // }
15433 // \endcode
15434 // FIXME: If the innermost body is a loop itself, inserting these
15435 // statements stops it being recognized as a perfectly nested loop (e.g.
15436 // for applying another loop transformation). If this is the case, sink the
15437 // expressions further into the inner loop.
15438 SmallVector<Stmt *, 4> BodyParts;
15439 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15440 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15441 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15442 BodyParts.push_back(Inner);
15443 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15444 Inner->getBeginLoc(), Inner->getEndLoc());
15445 Inner = new (Context)
15446 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15447 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15448 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15449 }
15450
15451 // Create grid loops from the inside to the outside.
15452 for (int I = NumLoops - 1; I >= 0; --I) {
15453 auto &LoopHelper = LoopHelpers[I];
15454 Expr *NumIterations = LoopHelper.NumIterations;
15455 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15456 QualType IVTy = NumIterations->getType();
15457
15458 // For init-statement: auto .grid.iv = 0
15459 SemaRef.AddInitializerToDecl(
15460 FloorIndVars[I],
15461 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15462 /*DirectInit=*/false);
15463 Decl *CounterDecl = FloorIndVars[I];
15464 StmtResult InitStmt = new (Context)
15465 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15466 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15467 if (!InitStmt.isUsable())
15468 return StmtError();
15469
15470 // For cond-expression: .floor.iv < NumIterations
15471 ExprResult CondExpr = SemaRef.BuildBinOp(
15472 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15473 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15474 NumIterations);
15475 if (!CondExpr.isUsable())
15476 return StmtError();
15477
15478 // For incr-statement: .floor.iv += DimStripeSize
15479 ExprResult IncrStmt = SemaRef.BuildBinOp(
15480 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15481 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15482 MakeDimStripeSize(I));
15483 if (!IncrStmt.isUsable())
15484 return StmtError();
15485
15486 Inner = new (Context)
15487 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15488 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15489 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15490 }
15491
15492 return OMPStripeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15493 NumLoops, AStmt, Inner,
15494 buildPreInits(Context, PreInits));
15495}
15496
15498 Stmt *AStmt,
15499 SourceLocation StartLoc,
15500 SourceLocation EndLoc) {
15501 ASTContext &Context = getASTContext();
15502 Scope *CurScope = SemaRef.getCurScope();
15503 // Empty statement should only be possible if there already was an error.
15504 if (!AStmt)
15505 return StmtError();
15506
15508 {OMPC_partial, OMPC_full}))
15509 return StmtError();
15510
15511 const OMPFullClause *FullClause =
15512 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15513 const OMPPartialClause *PartialClause =
15514 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15515 assert(!(FullClause && PartialClause) &&
15516 "mutual exclusivity must have been checked before");
15517
15518 constexpr unsigned NumLoops = 1;
15519 Stmt *Body = nullptr;
15521 NumLoops);
15522 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
15523 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15524 Body, OriginalInits))
15525 return StmtError();
15526
15527 unsigned NumGeneratedTopLevelLoops = PartialClause ? 1 : 0;
15528
15529 // Delay unrolling to when template is completely instantiated.
15530 if (SemaRef.CurContext->isDependentContext())
15531 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15532 NumGeneratedTopLevelLoops, nullptr,
15533 nullptr);
15534
15535 assert(LoopHelpers.size() == NumLoops &&
15536 "Expecting a single-dimensional loop iteration space");
15537 assert(OriginalInits.size() == NumLoops &&
15538 "Expecting a single-dimensional loop iteration space");
15539 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15540
15541 if (FullClause) {
15543 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
15544 /*SuppressExprDiags=*/true)
15545 .isUsable()) {
15546 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
15547 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
15548 << "#pragma omp unroll full";
15549 return StmtError();
15550 }
15551 }
15552
15553 // The generated loop may only be passed to other loop-associated directive
15554 // when a partial clause is specified. Without the requirement it is
15555 // sufficient to generate loop unroll metadata at code-generation.
15556 if (NumGeneratedTopLevelLoops == 0)
15557 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15558 NumGeneratedTopLevelLoops, nullptr,
15559 nullptr);
15560
15561 // Otherwise, we need to provide a de-sugared/transformed AST that can be
15562 // associated with another loop directive.
15563 //
15564 // The canonical loop analysis return by checkTransformableLoopNest assumes
15565 // the following structure to be the same loop without transformations or
15566 // directives applied: \code OriginalInits; LoopHelper.PreInits;
15567 // LoopHelper.Counters;
15568 // for (; IV < LoopHelper.NumIterations; ++IV) {
15569 // LoopHelper.Updates;
15570 // Body;
15571 // }
15572 // \endcode
15573 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
15574 // and referenced by LoopHelper.IterationVarRef.
15575 //
15576 // The unrolling directive transforms this into the following loop:
15577 // \code
15578 // OriginalInits; \
15579 // LoopHelper.PreInits; > NewPreInits
15580 // LoopHelper.Counters; /
15581 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
15582 // #pragma clang loop unroll_count(Factor)
15583 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
15584 // {
15585 // LoopHelper.Updates;
15586 // Body;
15587 // }
15588 // }
15589 // \endcode
15590 // where UIV is a new logical iteration counter. IV must be the same VarDecl
15591 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
15592 // references it. If the partially unrolled loop is associated with another
15593 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
15594 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
15595 // OpenMP canonical loop. The inner loop is not an associable canonical loop
15596 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
15597 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
15598 // property of the OMPLoopBasedDirective instead of statements in
15599 // CompoundStatement. This is to allow the loop to become a non-outermost loop
15600 // of a canonical loop nest where these PreInits are emitted before the
15601 // outermost directive.
15602
15603 // Find the loop statement.
15604 Stmt *LoopStmt = nullptr;
15605 collectLoopStmts(AStmt, {LoopStmt});
15606
15607 // Determine the PreInit declarations.
15608 SmallVector<Stmt *, 4> PreInits;
15609 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15610
15611 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15612 QualType IVTy = IterationVarRef->getType();
15613 assert(LoopHelper.Counters.size() == 1 &&
15614 "Expecting a single-dimensional loop iteration space");
15615 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15616
15617 // Determine the unroll factor.
15618 uint64_t Factor;
15619 SourceLocation FactorLoc;
15620 if (Expr *FactorVal = PartialClause->getFactor();
15621 FactorVal && !FactorVal->containsErrors()) {
15622 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15623 FactorLoc = FactorVal->getExprLoc();
15624 } else {
15625 // TODO: Use a better profitability model.
15626 Factor = 2;
15627 }
15628 assert(Factor > 0 && "Expected positive unroll factor");
15629 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
15631 getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor),
15632 IVTy, FactorLoc);
15633 };
15634
15635 // Iteration variable SourceLocations.
15636 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15637 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15638 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15639
15640 // Internal variable names.
15641 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15642 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
15643 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
15644
15645 // Create the iteration variable for the unrolled loop.
15646 VarDecl *OuterIVDecl =
15647 buildVarDecl(SemaRef, {}, IVTy, OuterIVName, nullptr, OrigVar);
15648 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
15649 return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc);
15650 };
15651
15652 // Iteration variable for the inner loop: Reuse the iteration variable created
15653 // by checkOpenMPLoop.
15654 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15655 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(InnerIVName));
15656 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
15657 return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc);
15658 };
15659
15660 // Make a copy of the NumIterations expression for each use: By the AST
15661 // constraints, every expression object in a DeclContext must be unique.
15662 CaptureVars CopyTransformer(SemaRef);
15663 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15664 return AssertSuccess(
15665 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15666 };
15667
15668 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15669 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(MakeOuterRef());
15670 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(),
15671 /*DirectInit=*/false);
15672 StmtResult InnerInit = new (Context)
15673 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15674 if (!InnerInit.isUsable())
15675 return StmtError();
15676
15677 // Inner For cond-expression:
15678 // \code
15679 // .unroll_inner.iv < .unrolled.iv + Factor &&
15680 // .unroll_inner.iv < NumIterations
15681 // \endcode
15682 // This conjunction of two conditions allows ScalarEvolution to derive the
15683 // maximum trip count of the inner loop.
15684 ExprResult EndOfTile =
15685 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15686 MakeOuterRef(), MakeFactorExpr());
15687 if (!EndOfTile.isUsable())
15688 return StmtError();
15689 ExprResult InnerCond1 =
15690 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15691 MakeInnerRef(), EndOfTile.get());
15692 if (!InnerCond1.isUsable())
15693 return StmtError();
15694 ExprResult InnerCond2 =
15695 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15696 MakeInnerRef(), MakeNumIterations());
15697 if (!InnerCond2.isUsable())
15698 return StmtError();
15699 ExprResult InnerCond =
15700 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15701 InnerCond1.get(), InnerCond2.get());
15702 if (!InnerCond.isUsable())
15703 return StmtError();
15704
15705 // Inner For incr-statement: ++.unroll_inner.iv
15706 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
15707 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
15708 if (!InnerIncr.isUsable())
15709 return StmtError();
15710
15711 // Inner For statement.
15712 SmallVector<Stmt *> InnerBodyStmts;
15713 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15714 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15715 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15716 InnerBodyStmts.push_back(Body);
15717 CompoundStmt *InnerBody =
15719 Body->getBeginLoc(), Body->getEndLoc());
15720 ForStmt *InnerFor = new (Context)
15721 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15722 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15723 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15724
15725 // Unroll metadata for the inner loop.
15726 // This needs to take into account the remainder portion of the unrolled loop,
15727 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15728 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15729 // the maximum trip count, which will also generate a remainder loop. Just
15730 // `unroll(enable)` (which could have been useful if the user has not
15731 // specified a concrete factor; even though the outer loop cannot be
15732 // influenced anymore, would avoid more code bloat than necessary) will refuse
15733 // the loop because "Won't unroll; remainder loop could not be generated when
15734 // assuming runtime trip count". Even if it did work, it must not choose a
15735 // larger unroll factor than the maximum loop length, or it would always just
15736 // execute the remainder loop.
15737 LoopHintAttr *UnrollHintAttr =
15738 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15739 LoopHintAttr::Numeric, MakeFactorExpr());
15740 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
15741 getASTContext(), StartLoc, {UnrollHintAttr}, InnerFor);
15742
15743 // Outer For init-statement: auto .unrolled.iv = 0
15744 SemaRef.AddInitializerToDecl(
15745 OuterIVDecl,
15746 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15747 /*DirectInit=*/false);
15748 StmtResult OuterInit = new (Context)
15749 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15750 if (!OuterInit.isUsable())
15751 return StmtError();
15752
15753 // Outer For cond-expression: .unrolled.iv < NumIterations
15754 ExprResult OuterConde =
15755 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15756 MakeOuterRef(), MakeNumIterations());
15757 if (!OuterConde.isUsable())
15758 return StmtError();
15759
15760 // Outer For incr-statement: .unrolled.iv += Factor
15761 ExprResult OuterIncr =
15762 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15763 MakeOuterRef(), MakeFactorExpr());
15764 if (!OuterIncr.isUsable())
15765 return StmtError();
15766
15767 // Outer For statement.
15768 ForStmt *OuterFor = new (Context)
15769 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15770 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15771 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15772
15773 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15774 NumGeneratedTopLevelLoops, OuterFor,
15775 buildPreInits(Context, PreInits));
15776}
15777
15779 SourceLocation StartLoc,
15780 SourceLocation EndLoc) {
15781 ASTContext &Context = getASTContext();
15782 Scope *CurScope = SemaRef.getCurScope();
15783
15784 // Empty statement should only be possible if there already was an error.
15785 if (!AStmt)
15786 return StmtError();
15787
15788 constexpr unsigned NumLoops = 1;
15789 Stmt *Body = nullptr;
15791 NumLoops);
15792 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
15793 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
15794 Body, OriginalInits))
15795 return StmtError();
15796
15797 // Delay applying the transformation to when template is completely
15798 // instantiated.
15799 if (SemaRef.CurContext->isDependentContext())
15800 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
15801 NumLoops, nullptr, nullptr);
15802
15803 assert(LoopHelpers.size() == NumLoops &&
15804 "Expecting a single-dimensional loop iteration space");
15805 assert(OriginalInits.size() == NumLoops &&
15806 "Expecting a single-dimensional loop iteration space");
15807 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15808
15809 // Find the loop statement.
15810 Stmt *LoopStmt = nullptr;
15811 collectLoopStmts(AStmt, {LoopStmt});
15812
15813 // Determine the PreInit declarations.
15814 SmallVector<Stmt *> PreInits;
15815 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15816
15817 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15818 QualType IVTy = IterationVarRef->getType();
15819 uint64_t IVWidth = Context.getTypeSize(IVTy);
15820 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15821
15822 // Iteration variable SourceLocations.
15823 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15824 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15825 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15826
15827 // Locations pointing to the transformation.
15828 SourceLocation TransformLoc = StartLoc;
15829 SourceLocation TransformLocBegin = StartLoc;
15830 SourceLocation TransformLocEnd = EndLoc;
15831
15832 // Internal variable names.
15833 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15834 SmallString<64> ForwardIVName(".forward.iv.");
15835 ForwardIVName += OrigVarName;
15836 SmallString<64> ReversedIVName(".reversed.iv.");
15837 ReversedIVName += OrigVarName;
15838
15839 // LoopHelper.Updates will read the logical iteration number from
15840 // LoopHelper.IterationVarRef, compute the value of the user loop counter of
15841 // that logical iteration from it, then assign it to the user loop counter
15842 // variable. We cannot directly use LoopHelper.IterationVarRef as the
15843 // induction variable of the generated loop because it may cause an underflow:
15844 // \code{.c}
15845 // for (unsigned i = 0; i < n; ++i)
15846 // body(i);
15847 // \endcode
15848 //
15849 // Naive reversal:
15850 // \code{.c}
15851 // for (unsigned i = n-1; i >= 0; --i)
15852 // body(i);
15853 // \endcode
15854 //
15855 // Instead, we introduce a new iteration variable representing the logical
15856 // iteration counter of the original loop, convert it to the logical iteration
15857 // number of the reversed loop, then let LoopHelper.Updates compute the user's
15858 // loop iteration variable from it.
15859 // \code{.cpp}
15860 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
15861 // auto .reversed.iv = n - .forward.iv - 1;
15862 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates
15863 // body(i); // Body
15864 // }
15865 // \endcode
15866
15867 // Subexpressions with more than one use. One of the constraints of an AST is
15868 // that every node object must appear at most once, hence we define a lambda
15869 // that creates a new AST node at every use.
15870 CaptureVars CopyTransformer(SemaRef);
15871 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15872 return AssertSuccess(
15873 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15874 };
15875
15876 // Create the iteration variable for the forward loop (from 0 to n-1).
15877 VarDecl *ForwardIVDecl =
15878 buildVarDecl(SemaRef, {}, IVTy, ForwardIVName, nullptr, OrigVar);
15879 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
15880 OrigVarLoc]() {
15881 return buildDeclRefExpr(SemaRef, ForwardIVDecl, IVTy, OrigVarLoc);
15882 };
15883
15884 // Iteration variable for the reversed induction variable (from n-1 downto 0):
15885 // Reuse the iteration variable created by checkOpenMPLoop.
15886 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15887 ReversedIVDecl->setDeclName(
15888 &SemaRef.PP.getIdentifierTable().get(ReversedIVName));
15889
15890 // For init-statement:
15891 // \code{.cpp}
15892 // auto .forward.iv = 0;
15893 // \endcode
15894 auto *Zero = IntegerLiteral::Create(Context, llvm::APInt::getZero(IVWidth),
15895 ForwardIVDecl->getType(), OrigVarLoc);
15896 SemaRef.AddInitializerToDecl(ForwardIVDecl, Zero, /*DirectInit=*/false);
15897 StmtResult Init = new (Context)
15898 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15899 if (!Init.isUsable())
15900 return StmtError();
15901
15902 // Forward iv cond-expression:
15903 // \code{.cpp}
15904 // .forward.iv < MakeNumIterations()
15905 // \endcode
15907 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15908 MakeForwardRef(), MakeNumIterations());
15909 if (!Cond.isUsable())
15910 return StmtError();
15911
15912 // Forward incr-statement:
15913 // \code{.c}
15914 // ++.forward.iv
15915 // \endcode
15916 ExprResult Incr = SemaRef.BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
15917 UO_PreInc, MakeForwardRef());
15918 if (!Incr.isUsable())
15919 return StmtError();
15920
15921 // Reverse the forward-iv:
15922 // \code{.cpp}
15923 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
15924 // \endcode
15925 auto *One = IntegerLiteral::Create(Context, llvm::APInt(IVWidth, 1), IVTy,
15926 TransformLoc);
15927 ExprResult Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub,
15928 MakeNumIterations(), One);
15929 if (!Minus.isUsable())
15930 return StmtError();
15931 Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.get(),
15932 MakeForwardRef());
15933 if (!Minus.isUsable())
15934 return StmtError();
15935 StmtResult InitReversed = new (Context) DeclStmt(
15936 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
15937 if (!InitReversed.isUsable())
15938 return StmtError();
15939 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.get(),
15940 /*DirectInit=*/false);
15941
15942 // The new loop body.
15943 SmallVector<Stmt *, 4> BodyStmts;
15944 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
15945 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
15946 BodyStmts.push_back(InitReversed.get());
15947 llvm::append_range(BodyStmts, LoopHelper.Updates);
15948 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15949 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15950 BodyStmts.push_back(Body);
15951 auto *ReversedBody =
15952 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
15953 Body->getBeginLoc(), Body->getEndLoc());
15954
15955 // Finally create the reversed For-statement.
15956 auto *ReversedFor = new (Context)
15957 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
15958 ReversedBody, LoopHelper.Init->getBeginLoc(),
15959 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15960 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt, NumLoops,
15961 ReversedFor,
15962 buildPreInits(Context, PreInits));
15963}
15964
15965/// Build the AST for \#pragma omp split counts(c1, c2, ...).
15966///
15967/// Splits the single associated loop into N consecutive loops, where N is the
15968/// number of count expressions.
15970 Stmt *AStmt,
15971 SourceLocation StartLoc,
15972 SourceLocation EndLoc) {
15973 ASTContext &Context = getASTContext();
15974 Scope *CurScope = SemaRef.getCurScope();
15975
15976 // Empty statement should only be possible if there already was an error.
15977 if (!AStmt)
15978 return StmtError();
15979
15980 const auto *CountsClause =
15981 OMPExecutableDirective::getSingleClause<OMPCountsClause>(Clauses);
15982 if (!CountsClause)
15983 return StmtError();
15984
15985 // Split applies to a single loop; check it is transformable and get helpers.
15986 constexpr unsigned NumLoops = 1;
15987 Stmt *Body = nullptr;
15989 NumLoops);
15990 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
15991 if (!checkTransformableLoopNest(OMPD_split, AStmt, NumLoops, LoopHelpers,
15992 Body, OriginalInits))
15993 return StmtError();
15994
15995 // Delay applying the transformation to when template is completely
15996 // instantiated.
15997 if (SemaRef.CurContext->isDependentContext())
15998 return OMPSplitDirective::Create(Context, StartLoc, EndLoc, Clauses,
15999 NumLoops, AStmt, nullptr, nullptr);
16000
16001 assert(LoopHelpers.size() == NumLoops &&
16002 "Expecting a single-dimensional loop iteration space");
16003 assert(OriginalInits.size() == NumLoops &&
16004 "Expecting a single-dimensional loop iteration space");
16005 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
16006
16007 // Find the loop statement.
16008 Stmt *LoopStmt = nullptr;
16009 collectLoopStmts(AStmt, {LoopStmt});
16010
16011 // Determine the PreInit declarations.
16012 SmallVector<Stmt *> PreInits;
16013 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
16014
16015 // Type and name of the original loop variable; we create one IV per segment
16016 // and assign it to the original var so the body sees the same name.
16017 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
16018 QualType IVTy = IterationVarRef->getType();
16019 uint64_t IVWidth = Context.getTypeSize(IVTy);
16020 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
16021
16022 // Iteration variable SourceLocations.
16023 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
16024 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
16025 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
16026 // Internal variable names.
16027 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
16028
16029 if (!CountsClause->hasOmpFill())
16030 return StmtError();
16031 unsigned FillIdx = *CountsClause->getOmpFillIndex();
16032
16033 unsigned NumItems = CountsClause->getNumCounts();
16034 SmallVector<uint64_t, 4> CountValues(NumItems, 0);
16035 ArrayRef<Expr *> Refs = CountsClause->getCountsRefs();
16036 for (unsigned I = 0; I < NumItems; ++I) {
16037 if (I == FillIdx)
16038 continue;
16039 Expr *CountExpr = Refs[I];
16040 if (!CountExpr)
16041 return OMPSplitDirective::Create(Context, StartLoc, EndLoc, Clauses,
16042 NumLoops, AStmt, nullptr, nullptr);
16043 std::optional<llvm::APSInt> OptVal =
16044 CountExpr->getIntegerConstantExpr(Context);
16045 if (!OptVal || OptVal->isNegative())
16046 return OMPSplitDirective::Create(Context, StartLoc, EndLoc, Clauses,
16047 NumLoops, AStmt, nullptr, nullptr);
16048 CountValues[I] = OptVal->getZExtValue();
16049 }
16050
16051 Expr *NumIterExpr = LoopHelper.NumIterations;
16052
16053 uint64_t RightSum = 0;
16054 for (unsigned I = FillIdx + 1; I < NumItems; ++I)
16055 RightSum += CountValues[I];
16056
16057 auto MakeIntLit = [&](uint64_t Val) {
16058 return IntegerLiteral::Create(Context, llvm::APInt(IVWidth, Val), IVTy,
16059 OrigVarLoc);
16060 };
16061
16062 size_t NumSegments = NumItems;
16063 SmallVector<Stmt *, 4> SplitLoops;
16064
16065 auto *IterVarDecl = cast<VarDecl>(IterationVarRef->getDecl());
16066 SplitLoops.push_back(new (Context) DeclStmt(DeclGroupRef(IterVarDecl),
16067 IterationVarRef->getBeginLoc(),
16068 IterationVarRef->getEndLoc()));
16069
16070 uint64_t LeftAccum = 0;
16071 uint64_t RightRemaining = RightSum;
16072
16073 for (size_t Seg = 0; Seg < NumSegments; ++Seg) {
16074 Expr *StartExpr = nullptr;
16075 Expr *EndExpr = nullptr;
16076
16077 if (Seg < FillIdx) {
16078 StartExpr = MakeIntLit(LeftAccum);
16079 LeftAccum += CountValues[Seg];
16080 EndExpr = MakeIntLit(LeftAccum);
16081 } else if (Seg == FillIdx) {
16082 StartExpr = MakeIntLit(LeftAccum);
16083 if (RightRemaining == 0) {
16084 EndExpr = NumIterExpr;
16085 } else {
16086 ExprResult Sub =
16087 SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Sub, NumIterExpr,
16088 MakeIntLit(RightRemaining));
16089 if (!Sub.isUsable())
16090 return StmtError();
16091 EndExpr = Sub.get();
16092 }
16093 } else {
16094 if (RightRemaining == RightSum) {
16095 if (RightSum == 0)
16096 StartExpr = NumIterExpr;
16097 else {
16098 ExprResult Sub =
16099 SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Sub, NumIterExpr,
16100 MakeIntLit(RightRemaining));
16101 if (!Sub.isUsable())
16102 return StmtError();
16103 StartExpr = Sub.get();
16104 }
16105 } else {
16106 ExprResult Sub =
16107 SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Sub, NumIterExpr,
16108 MakeIntLit(RightRemaining));
16109 if (!Sub.isUsable())
16110 return StmtError();
16111 StartExpr = Sub.get();
16112 }
16113 RightRemaining -= CountValues[Seg];
16114 if (RightRemaining == 0)
16115 EndExpr = NumIterExpr;
16116 else {
16117 ExprResult Sub =
16118 SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Sub, NumIterExpr,
16119 MakeIntLit(RightRemaining));
16120 if (!Sub.isUsable())
16121 return StmtError();
16122 EndExpr = Sub.get();
16123 }
16124 }
16125
16126 SmallString<64> IVName(".split.iv.");
16127 IVName += (Twine(Seg) + "." + OrigVarName).str();
16128 VarDecl *IVDecl = buildVarDecl(SemaRef, {}, IVTy, IVName, nullptr, OrigVar);
16129 auto MakeIVRef = [&SemaRef = this->SemaRef, IVDecl, IVTy, OrigVarLoc]() {
16130 return buildDeclRefExpr(SemaRef, IVDecl, IVTy, OrigVarLoc);
16131 };
16132
16133 SemaRef.AddInitializerToDecl(IVDecl, StartExpr, /*DirectInit=*/false);
16134 StmtResult InitStmt = new (Context)
16135 DeclStmt(DeclGroupRef(IVDecl), OrigVarLocBegin, OrigVarLocEnd);
16136 if (!InitStmt.isUsable())
16137 return StmtError();
16138
16139 ExprResult CondExpr = SemaRef.BuildBinOp(
16140 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeIVRef(), EndExpr);
16141 if (!CondExpr.isUsable())
16142 return StmtError();
16143
16144 ExprResult IncrExpr = SemaRef.BuildUnaryOp(
16145 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeIVRef());
16146 if (!IncrExpr.isUsable())
16147 return StmtError();
16148
16149 ExprResult IVAssign = SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Assign,
16150 IterationVarRef, MakeIVRef());
16151 if (!IVAssign.isUsable())
16152 return StmtError();
16153
16154 SmallVector<Stmt *, 4> BodyStmts;
16155 BodyStmts.push_back(IVAssign.get());
16156 BodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
16157 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
16158 if (Seg == 0) {
16159 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
16160 } else {
16161 VarDecl *LoopVar = CXXRangeFor->getLoopVariable();
16163 SemaRef, LoopVar, LoopVar->getType().getNonReferenceType(),
16164 OrigVarLoc);
16165 ExprResult LVAssign = SemaRef.BuildBinOp(
16166 CurScope, OrigVarLoc, BO_Assign, LVRef, LoopVar->getInit());
16167 if (!LVAssign.isUsable())
16168 return StmtError();
16169 BodyStmts.push_back(LVAssign.get());
16170 }
16171 }
16172 BodyStmts.push_back(Body);
16173
16174 auto *LoopBody =
16175 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
16176 Body->getBeginLoc(), Body->getEndLoc());
16177
16178 auto *For = new (Context)
16179 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
16180 IncrExpr.get(), LoopBody, LoopHelper.Init->getBeginLoc(),
16181 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16182 SplitLoops.push_back(For);
16183 }
16184
16185 auto *SplitStmt = CompoundStmt::Create(
16186 Context, SplitLoops, FPOptionsOverride(),
16187 SplitLoops.front()->getBeginLoc(), SplitLoops.back()->getEndLoc());
16188
16189 return OMPSplitDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
16190 AStmt, SplitStmt,
16191 buildPreInits(Context, PreInits));
16192}
16193
16195 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
16196 SourceLocation EndLoc) {
16197 ASTContext &Context = getASTContext();
16198 DeclContext *CurContext = SemaRef.CurContext;
16199 Scope *CurScope = SemaRef.getCurScope();
16200
16201 // Empty statement should only be possible if there already was an error.
16202 if (!AStmt)
16203 return StmtError();
16204
16205 // interchange without permutation clause swaps two loops.
16206 const OMPPermutationClause *PermutationClause =
16207 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
16208 size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2;
16209
16210 // Verify and diagnose loop nest.
16212 Stmt *Body = nullptr;
16213 SmallVector<SmallVector<Stmt *>, 2> OriginalInits;
16214 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
16215 LoopHelpers, Body, OriginalInits))
16216 return StmtError();
16217
16218 // Delay interchange to when template is completely instantiated.
16219 if (CurContext->isDependentContext())
16220 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
16221 NumLoops, AStmt, nullptr, nullptr);
16222
16223 // An invalid expression in the permutation clause is set to nullptr in
16224 // ActOnOpenMPPermutationClause.
16225 if (PermutationClause &&
16226 llvm::is_contained(PermutationClause->getArgsRefs(), nullptr))
16227 return StmtError();
16228
16229 assert(LoopHelpers.size() == NumLoops &&
16230 "Expecting loop iteration space dimensionaly to match number of "
16231 "affected loops");
16232 assert(OriginalInits.size() == NumLoops &&
16233 "Expecting loop iteration space dimensionaly to match number of "
16234 "affected loops");
16235
16236 // Decode the permutation clause.
16237 SmallVector<uint64_t, 2> Permutation;
16238 if (!PermutationClause) {
16239 Permutation = {1, 0};
16240 } else {
16241 ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs();
16242 llvm::BitVector Flags(PermArgs.size());
16243 for (Expr *PermArg : PermArgs) {
16244 std::optional<llvm::APSInt> PermCstExpr =
16245 PermArg->getIntegerConstantExpr(Context);
16246 if (!PermCstExpr)
16247 continue;
16248 uint64_t PermInt = PermCstExpr->getZExtValue();
16249 assert(1 <= PermInt && PermInt <= NumLoops &&
16250 "Must be a permutation; diagnostic emitted in "
16251 "ActOnOpenMPPermutationClause");
16252 if (Flags[PermInt - 1]) {
16253 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
16254 Diag(PermArg->getExprLoc(),
16255 diag::err_omp_interchange_permutation_value_repeated)
16256 << PermInt << ExprRange;
16257 continue;
16258 }
16259 Flags[PermInt - 1] = true;
16260
16261 Permutation.push_back(PermInt - 1);
16262 }
16263
16264 if (Permutation.size() != NumLoops)
16265 return StmtError();
16266 }
16267
16268 // Nothing to transform with trivial permutation.
16269 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](auto P) {
16270 auto [Idx, Arg] = P;
16271 return Idx == Arg;
16272 }))
16273 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
16274 NumLoops, AStmt, AStmt, nullptr);
16275
16276 // Find the affected loops.
16277 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
16278 collectLoopStmts(AStmt, LoopStmts);
16279
16280 // Collect pre-init statements on the order before the permuation.
16281 SmallVector<Stmt *> PreInits;
16282 for (auto I : llvm::seq<int>(NumLoops)) {
16283 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
16284
16285 assert(LoopHelper.Counters.size() == 1 &&
16286 "Single-dimensional loop iteration space expected");
16287
16288 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
16289 PreInits);
16290 }
16291
16292 SmallVector<VarDecl *> PermutedIndVars(NumLoops);
16293 CaptureVars CopyTransformer(SemaRef);
16294
16295 // Create the permuted loops from the inside to the outside of the
16296 // interchanged loop nest. Body of the innermost new loop is the original
16297 // innermost body.
16298 Stmt *Inner = Body;
16299 for (auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
16300 // Get the original loop that belongs to this new position.
16301 uint64_t SourceIdx = Permutation[TargetIdx];
16302 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
16303 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
16304 assert(SourceHelper.Counters.size() == 1 &&
16305 "Single-dimensional loop iteration space expected");
16306 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.Counters.front());
16307
16308 // Normalized loop counter variable: From 0 to n-1, always an integer type.
16309 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(SourceHelper.IterationVarRef);
16310 QualType IVTy = IterVarRef->getType();
16311 assert(IVTy->isIntegerType() &&
16312 "Expected the logical iteration counter to be an integer");
16313
16314 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
16315 SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
16316
16317 // Make a copy of the NumIterations expression for each use: By the AST
16318 // constraints, every expression object in a DeclContext must be unique.
16319 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
16320 return AssertSuccess(
16321 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
16322 };
16323
16324 // Iteration variable for the permuted loop. Reuse the one from
16325 // checkOpenMPLoop which will also be used to update the original loop
16326 // variable.
16327 SmallString<64> PermutedCntName(".permuted_");
16328 PermutedCntName.append({llvm::utostr(TargetIdx), ".iv.", OrigVarName});
16329 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->getDecl());
16330 PermutedCntDecl->setDeclName(
16331 &SemaRef.PP.getIdentifierTable().get(PermutedCntName));
16332 PermutedIndVars[TargetIdx] = PermutedCntDecl;
16333 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
16334 return buildDeclRefExpr(SemaRef, PermutedCntDecl, IVTy, OrigVarLoc);
16335 };
16336
16337 // For init-statement:
16338 // \code
16339 // auto .permuted_{target}.iv = 0
16340 // \endcode
16341 ExprResult Zero = SemaRef.ActOnIntegerConstant(OrigVarLoc, 0);
16342 if (!Zero.isUsable())
16343 return StmtError();
16344 SemaRef.AddInitializerToDecl(PermutedCntDecl, Zero.get(),
16345 /*DirectInit=*/false);
16346 StmtResult InitStmt = new (Context)
16347 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
16348 OrigCntVar->getEndLoc());
16349 if (!InitStmt.isUsable())
16350 return StmtError();
16351
16352 // For cond-expression:
16353 // \code
16354 // .permuted_{target}.iv < MakeNumIterations()
16355 // \endcode
16356 ExprResult CondExpr =
16357 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
16358 MakePermutedRef(), MakeNumIterations());
16359 if (!CondExpr.isUsable())
16360 return StmtError();
16361
16362 // For incr-statement:
16363 // \code
16364 // ++.tile.iv
16365 // \endcode
16366 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
16367 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
16368 if (!IncrStmt.isUsable())
16369 return StmtError();
16370
16371 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
16372 SourceHelper.Updates.end());
16373 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
16374 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
16375 BodyParts.push_back(Inner);
16376 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
16377 Inner->getBeginLoc(), Inner->getEndLoc());
16378 Inner = new (Context) ForStmt(
16379 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
16380 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
16381 SourceHelper.Inc->getEndLoc());
16382 }
16383
16384 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
16385 NumLoops, AStmt, Inner,
16386 buildPreInits(Context, PreInits));
16387}
16388
16390 Stmt *AStmt,
16391 SourceLocation StartLoc,
16392 SourceLocation EndLoc) {
16393
16394 ASTContext &Context = getASTContext();
16395 DeclContext *CurrContext = SemaRef.CurContext;
16396 Scope *CurScope = SemaRef.getCurScope();
16397 CaptureVars CopyTransformer(SemaRef);
16398
16399 // Ensure the structured block is not empty
16400 if (!AStmt)
16401 return StmtError();
16402
16403 // Defer transformation in dependent contexts
16404 // The NumLoopNests argument is set to a placeholder 1 (even though
16405 // using looprange fuse could yield up to 3 top level loop nests)
16406 // because a dependent context could prevent determining its true value
16407 if (CurrContext->isDependentContext())
16408 return OMPFuseDirective::Create(Context, StartLoc, EndLoc, Clauses,
16409 /* NumLoops */ 1, AStmt, nullptr, nullptr);
16410
16411 // Validate that the potential loop sequence is transformable for fusion
16412 // Also collect the HelperExprs, Loop Stmts, Inits, and Number of loops
16413 LoopSequenceAnalysis SeqAnalysis;
16414 if (!checkTransformableLoopSequence(OMPD_fuse, AStmt, SeqAnalysis, Context))
16415 return StmtError();
16416
16417 // SeqAnalysis.LoopSeqSize exists mostly to handle dependent contexts,
16418 // otherwise it must be the same as SeqAnalysis.Loops.size().
16419 assert(SeqAnalysis.LoopSeqSize == SeqAnalysis.Loops.size() &&
16420 "Inconsistent size of the loop sequence and the number of loops "
16421 "found in the sequence");
16422
16423 // Handle clauses, which can be any of the following: [looprange, apply]
16424 const auto *LRC =
16425 OMPExecutableDirective::getSingleClause<OMPLoopRangeClause>(Clauses);
16426
16427 // The clause arguments are invalidated if any error arises
16428 // such as non-constant or non-positive arguments
16429 if (LRC && (!LRC->getFirst() || !LRC->getCount()))
16430 return StmtError();
16431
16432 // Delayed semantic check of LoopRange constraint
16433 // Evaluates the loop range arguments and returns the first and count values
16434 auto EvaluateLoopRangeArguments = [&Context](Expr *First, Expr *Count,
16435 uint64_t &FirstVal,
16436 uint64_t &CountVal) {
16437 llvm::APSInt FirstInt = First->EvaluateKnownConstInt(Context);
16438 llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Context);
16439 FirstVal = FirstInt.getZExtValue();
16440 CountVal = CountInt.getZExtValue();
16441 };
16442
16443 // OpenMP [6.0, Restrictions]
16444 // first + count - 1 must not evaluate to a value greater than the
16445 // loop sequence length of the associated canonical loop sequence.
16446 auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal,
16447 unsigned NumLoops) -> bool {
16448 return FirstVal + CountVal - 1 <= NumLoops;
16449 };
16450 uint64_t FirstVal = 1, CountVal = 0, LastVal = SeqAnalysis.LoopSeqSize;
16451
16452 // Validates the loop range after evaluating the semantic information
16453 // and ensures that the range is valid for the given loop sequence size.
16454 // Expressions are evaluated at compile time to obtain constant values.
16455 if (LRC) {
16456 EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal,
16457 CountVal);
16458 if (CountVal == 1)
16459 SemaRef.Diag(LRC->getCountLoc(), diag::warn_omp_redundant_fusion)
16460 << getOpenMPDirectiveName(OMPD_fuse);
16461
16462 if (!ValidLoopRange(FirstVal, CountVal, SeqAnalysis.LoopSeqSize)) {
16463 SemaRef.Diag(LRC->getFirstLoc(), diag::err_omp_invalid_looprange)
16464 << getOpenMPDirectiveName(OMPD_fuse) << FirstVal
16465 << (FirstVal + CountVal - 1) << SeqAnalysis.LoopSeqSize;
16466 return StmtError();
16467 }
16468
16469 LastVal = FirstVal + CountVal - 1;
16470 }
16471
16472 // Complete fusion generates a single canonical loop nest
16473 // However looprange clause may generate several loop nests
16474 unsigned NumGeneratedTopLevelLoops =
16475 LRC ? SeqAnalysis.LoopSeqSize - CountVal + 1 : 1;
16476
16477 // Emit a warning for redundant loop fusion when the sequence contains only
16478 // one loop.
16479 if (SeqAnalysis.LoopSeqSize == 1)
16480 SemaRef.Diag(AStmt->getBeginLoc(), diag::warn_omp_redundant_fusion)
16481 << getOpenMPDirectiveName(OMPD_fuse);
16482
16483 // Select the type with the largest bit width among all induction variables
16484 QualType IVType =
16485 SeqAnalysis.Loops[FirstVal - 1].HelperExprs.IterationVarRef->getType();
16486 for (unsigned I : llvm::seq<unsigned>(FirstVal, LastVal)) {
16487 QualType CurrentIVType =
16488 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef->getType();
16489 if (Context.getTypeSize(CurrentIVType) > Context.getTypeSize(IVType)) {
16490 IVType = CurrentIVType;
16491 }
16492 }
16493 uint64_t IVBitWidth = Context.getIntWidth(IVType);
16494
16495 // Create pre-init declarations for all loops lower bounds, upper bounds,
16496 // strides and num-iterations for every top level loop in the fusion
16497 SmallVector<VarDecl *, 4> LBVarDecls;
16498 SmallVector<VarDecl *, 4> STVarDecls;
16499 SmallVector<VarDecl *, 4> NIVarDecls;
16500 SmallVector<VarDecl *, 4> UBVarDecls;
16501 SmallVector<VarDecl *, 4> IVVarDecls;
16502
16503 // Helper lambda to create variables for bounds, strides, and other
16504 // expressions. Generates both the variable declaration and the corresponding
16505 // initialization statement.
16506 auto CreateHelperVarAndStmt =
16507 [&, &SemaRef = SemaRef](Expr *ExprToCopy, const std::string &BaseName,
16508 unsigned I, bool NeedsNewVD = false) {
16509 Expr *TransformedExpr =
16510 AssertSuccess(CopyTransformer.TransformExpr(ExprToCopy));
16511 if (!TransformedExpr)
16512 return std::pair<VarDecl *, StmtResult>(nullptr, StmtError());
16513
16514 auto Name = (Twine(".omp.") + BaseName + std::to_string(I)).str();
16515
16516 VarDecl *VD;
16517 if (NeedsNewVD) {
16518 VD = buildVarDecl(SemaRef, SourceLocation(), IVType, Name);
16519 SemaRef.AddInitializerToDecl(VD, TransformedExpr, false);
16520 } else {
16521 // Create a unique variable name
16522 DeclRefExpr *DRE = cast<DeclRefExpr>(TransformedExpr);
16523 VD = cast<VarDecl>(DRE->getDecl());
16524 VD->setDeclName(&SemaRef.PP.getIdentifierTable().get(Name));
16525 }
16526 // Create the corresponding declaration statement
16527 StmtResult DeclStmt = new (Context) class DeclStmt(
16529 return std::make_pair(VD, DeclStmt);
16530 };
16531
16532 // PreInits hold a sequence of variable declarations that must be executed
16533 // before the fused loop begins. These include bounds, strides, and other
16534 // helper variables required for the transformation. Other loop transforms
16535 // also contain their own preinits
16536 SmallVector<Stmt *> PreInits;
16537
16538 // Update the general preinits using the preinits generated by loop sequence
16539 // generating loop transformations. These preinits differ slightly from
16540 // single-loop transformation preinits, as they can be detached from a
16541 // specific loop inside multiple generated loop nests. This happens
16542 // because certain helper variables, like '.omp.fuse.max', are introduced to
16543 // handle fused iteration spaces and may not be directly tied to a single
16544 // original loop. The preinit structure must ensure that hidden variables
16545 // like '.omp.fuse.max' are still properly handled.
16546 // Transformations that apply this concept: Loopranged Fuse, Split
16547 llvm::append_range(PreInits, SeqAnalysis.LoopSequencePreInits);
16548
16549 // Process each single loop to generate and collect declarations
16550 // and statements for all helper expressions related to
16551 // particular single loop nests
16552
16553 // Also In the case of the fused loops, we keep track of their original
16554 // inits by appending them to their preinits statement, and in the case of
16555 // transformations, also append their preinits (which contain the original
16556 // loop initialization statement or other statements)
16557
16558 // Firstly we need to set TransformIndex to match the begining of the
16559 // looprange section
16560 unsigned int TransformIndex = 0;
16561 for (unsigned I : llvm::seq<unsigned>(FirstVal - 1)) {
16562 if (SeqAnalysis.Loops[I].isLoopTransformation())
16563 ++TransformIndex;
16564 }
16565
16566 for (unsigned int I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16567 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16568 addLoopPreInits(Context, SeqAnalysis.Loops[I].HelperExprs,
16569 SeqAnalysis.Loops[I].TheForStmt,
16570 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16571 } else if (SeqAnalysis.Loops[I].isLoopTransformation()) {
16572 // For transformed loops, insert both pre-inits and original inits.
16573 // Order matters: pre-inits may define variables used in the original
16574 // inits such as upper bounds...
16575 SmallVector<Stmt *> &TransformPreInit =
16576 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16577 llvm::append_range(PreInits, TransformPreInit);
16578
16579 addLoopPreInits(Context, SeqAnalysis.Loops[I].HelperExprs,
16580 SeqAnalysis.Loops[I].TheForStmt,
16581 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16582 }
16583 auto [UBVD, UBDStmt] =
16584 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.UB, "ub", J);
16585 auto [LBVD, LBDStmt] =
16586 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.LB, "lb", J);
16587 auto [STVD, STDStmt] =
16588 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.ST, "st", J);
16589 auto [NIVD, NIDStmt] = CreateHelperVarAndStmt(
16590 SeqAnalysis.Loops[I].HelperExprs.NumIterations, "ni", J, true);
16591 auto [IVVD, IVDStmt] = CreateHelperVarAndStmt(
16592 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef, "iv", J);
16593
16594 assert(LBVD && STVD && NIVD && IVVD &&
16595 "OpenMP Fuse Helper variables creation failed");
16596
16597 UBVarDecls.push_back(UBVD);
16598 LBVarDecls.push_back(LBVD);
16599 STVarDecls.push_back(STVD);
16600 NIVarDecls.push_back(NIVD);
16601 IVVarDecls.push_back(IVVD);
16602
16603 PreInits.push_back(LBDStmt.get());
16604 PreInits.push_back(STDStmt.get());
16605 PreInits.push_back(NIDStmt.get());
16606 PreInits.push_back(IVDStmt.get());
16607 }
16608
16609 auto MakeVarDeclRef = [&SemaRef = this->SemaRef](VarDecl *VD) {
16610 return buildDeclRefExpr(SemaRef, VD, VD->getType(), VD->getLocation(),
16611 false);
16612 };
16613
16614 // Following up the creation of the final fused loop will be performed
16615 // which has the following shape (considering the selected loops):
16616 //
16617 // for (fuse.index = 0; fuse.index < max(ni0, ni1..., nik); ++fuse.index) {
16618 // if (fuse.index < ni0){
16619 // iv0 = lb0 + st0 * fuse.index;
16620 // original.index0 = iv0
16621 // body(0);
16622 // }
16623 // if (fuse.index < ni1){
16624 // iv1 = lb1 + st1 * fuse.index;
16625 // original.index1 = iv1
16626 // body(1);
16627 // }
16628 //
16629 // ...
16630 //
16631 // if (fuse.index < nik){
16632 // ivk = lbk + stk * fuse.index;
16633 // original.indexk = ivk
16634 // body(k); Expr *InitVal = IntegerLiteral::Create(Context,
16635 // llvm::APInt(IVWidth, 0),
16636 // }
16637
16638 // 1. Create the initialized fuse index
16639 StringRef IndexName = ".omp.fuse.index";
16640 Expr *InitVal = IntegerLiteral::Create(Context, llvm::APInt(IVBitWidth, 0),
16641 IVType, SourceLocation());
16642 VarDecl *IndexDecl =
16643 buildVarDecl(SemaRef, {}, IVType, IndexName, nullptr, nullptr);
16644 SemaRef.AddInitializerToDecl(IndexDecl, InitVal, false);
16645 StmtResult InitStmt = new (Context)
16647
16648 if (!InitStmt.isUsable())
16649 return StmtError();
16650
16651 auto MakeIVRef = [&SemaRef = this->SemaRef, IndexDecl, IVType,
16652 Loc = InitVal->getExprLoc()]() {
16653 return buildDeclRefExpr(SemaRef, IndexDecl, IVType, Loc, false);
16654 };
16655
16656 // 2. Iteratively compute the max number of logical iterations Max(NI_1, NI_2,
16657 // ..., NI_k)
16658 //
16659 // This loop accumulates the maximum value across multiple expressions,
16660 // ensuring each step constructs a unique AST node for correctness. By using
16661 // intermediate temporary variables and conditional operators, we maintain
16662 // distinct nodes and avoid duplicating subtrees, For instance, max(a,b,c):
16663 // omp.temp0 = max(a, b)
16664 // omp.temp1 = max(omp.temp0, c)
16665 // omp.fuse.max = max(omp.temp1, omp.temp0)
16666
16667 ExprResult MaxExpr;
16668 // I is the range of loops in the sequence that we fuse.
16669 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16670 DeclRefExpr *NIRef = MakeVarDeclRef(NIVarDecls[J]);
16671 QualType NITy = NIRef->getType();
16672
16673 if (MaxExpr.isUnset()) {
16674 // Initialize MaxExpr with the first NI expression
16675 MaxExpr = NIRef;
16676 } else {
16677 // Create a new acummulator variable t_i = MaxExpr
16678 std::string TempName = (Twine(".omp.temp.") + Twine(J)).str();
16679 VarDecl *TempDecl =
16680 buildVarDecl(SemaRef, {}, NITy, TempName, nullptr, nullptr);
16681 TempDecl->setInit(MaxExpr.get());
16682 DeclRefExpr *TempRef =
16683 buildDeclRefExpr(SemaRef, TempDecl, NITy, SourceLocation(), false);
16684 DeclRefExpr *TempRef2 =
16685 buildDeclRefExpr(SemaRef, TempDecl, NITy, SourceLocation(), false);
16686 // Add a DeclStmt to PreInits to ensure the variable is declared.
16687 StmtResult TempStmt = new (Context)
16689
16690 if (!TempStmt.isUsable())
16691 return StmtError();
16692 PreInits.push_back(TempStmt.get());
16693
16694 // Build MaxExpr <-(MaxExpr > NIRef ? MaxExpr : NIRef)
16696 SemaRef.BuildBinOp(nullptr, SourceLocation(), BO_GT, TempRef, NIRef);
16697 // Handle any errors in Comparison creation
16698 if (!Comparison.isUsable())
16699 return StmtError();
16700
16701 DeclRefExpr *NIRef2 = MakeVarDeclRef(NIVarDecls[J]);
16702 // Update MaxExpr using a conditional expression to hold the max value
16703 MaxExpr = new (Context) ConditionalOperator(
16704 Comparison.get(), SourceLocation(), TempRef2, SourceLocation(),
16705 NIRef2->getExprStmt(), NITy, VK_LValue, OK_Ordinary);
16706
16707 if (!MaxExpr.isUsable())
16708 return StmtError();
16709 }
16710 }
16711 if (!MaxExpr.isUsable())
16712 return StmtError();
16713
16714 // 3. Declare the max variable
16715 const std::string MaxName = Twine(".omp.fuse.max").str();
16716 VarDecl *MaxDecl =
16717 buildVarDecl(SemaRef, {}, IVType, MaxName, nullptr, nullptr);
16718 MaxDecl->setInit(MaxExpr.get());
16719 DeclRefExpr *MaxRef = buildDeclRefExpr(SemaRef, MaxDecl, IVType, {}, false);
16720 StmtResult MaxStmt = new (Context)
16722
16723 if (MaxStmt.isInvalid())
16724 return StmtError();
16725 PreInits.push_back(MaxStmt.get());
16726
16727 // 4. Create condition Expr: index < n_max
16728 ExprResult CondExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_LT,
16729 MakeIVRef(), MaxRef);
16730 if (!CondExpr.isUsable())
16731 return StmtError();
16732
16733 // 5. Increment Expr: ++index
16734 ExprResult IncrExpr =
16735 SemaRef.BuildUnaryOp(CurScope, SourceLocation(), UO_PreInc, MakeIVRef());
16736 if (!IncrExpr.isUsable())
16737 return StmtError();
16738
16739 // 6. Build the Fused Loop Body
16740 // The final fused loop iterates over the maximum logical range. Inside the
16741 // loop, each original loop's index is calculated dynamically, and its body
16742 // is executed conditionally.
16743 //
16744 // Each sub-loop's body is guarded by a conditional statement to ensure
16745 // it executes only within its logical iteration range:
16746 //
16747 // if (fuse.index < ni_k){
16748 // iv_k = lb_k + st_k * fuse.index;
16749 // original.index = iv_k
16750 // body(k);
16751 // }
16752
16753 CompoundStmt *FusedBody = nullptr;
16754 SmallVector<Stmt *, 4> FusedBodyStmts;
16755 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16756 // Assingment of the original sub-loop index to compute the logical index
16757 // IV_k = LB_k + omp.fuse.index * ST_k
16758 ExprResult IdxExpr =
16759 SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Mul,
16760 MakeVarDeclRef(STVarDecls[J]), MakeIVRef());
16761 if (!IdxExpr.isUsable())
16762 return StmtError();
16763 IdxExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Add,
16764 MakeVarDeclRef(LBVarDecls[J]), IdxExpr.get());
16765
16766 if (!IdxExpr.isUsable())
16767 return StmtError();
16768 IdxExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Assign,
16769 MakeVarDeclRef(IVVarDecls[J]), IdxExpr.get());
16770 if (!IdxExpr.isUsable())
16771 return StmtError();
16772
16773 // Update the original i_k = IV_k
16774 SmallVector<Stmt *, 4> BodyStmts;
16775 BodyStmts.push_back(IdxExpr.get());
16776 llvm::append_range(BodyStmts, SeqAnalysis.Loops[I].HelperExprs.Updates);
16777
16778 // If the loop is a CXXForRangeStmt then the iterator variable is needed
16779 if (auto *SourceCXXFor =
16780 dyn_cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt))
16781 BodyStmts.push_back(SourceCXXFor->getLoopVarStmt());
16782
16783 Stmt *Body =
16784 (isa<ForStmt>(SeqAnalysis.Loops[I].TheForStmt))
16785 ? cast<ForStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody()
16786 : cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody();
16787 BodyStmts.push_back(Body);
16788
16789 CompoundStmt *CombinedBody =
16790 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
16793 SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_LT, MakeIVRef(),
16794 MakeVarDeclRef(NIVarDecls[J]));
16795
16796 if (!Condition.isUsable())
16797 return StmtError();
16798
16799 IfStmt *IfStatement = IfStmt::Create(
16800 Context, SourceLocation(), IfStatementKind::Ordinary, nullptr, nullptr,
16801 Condition.get(), SourceLocation(), SourceLocation(), CombinedBody,
16802 SourceLocation(), nullptr);
16803
16804 FusedBodyStmts.push_back(IfStatement);
16805 }
16806 FusedBody = CompoundStmt::Create(Context, FusedBodyStmts, FPOptionsOverride(),
16808
16809 // 7. Construct the final fused loop
16810 ForStmt *FusedForStmt = new (Context)
16811 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr, IncrExpr.get(),
16812 FusedBody, InitStmt.get()->getBeginLoc(), SourceLocation(),
16813 IncrExpr.get()->getEndLoc());
16814
16815 // In the case of looprange, the result of fuse won't simply
16816 // be a single loop (ForStmt), but rather a loop sequence
16817 // (CompoundStmt) of 3 parts: the pre-fusion loops, the fused loop
16818 // and the post-fusion loops, preserving its original order.
16819 //
16820 // Note: If looprange clause produces a single fused loop nest then
16821 // this compound statement wrapper is unnecessary (Therefore this
16822 // treatment is skipped)
16823
16824 Stmt *FusionStmt = FusedForStmt;
16825 if (LRC && CountVal != SeqAnalysis.LoopSeqSize) {
16826 SmallVector<Stmt *, 4> FinalLoops;
16827
16828 // Reset the transform index
16829 TransformIndex = 0;
16830
16831 // Collect all non-fused loops before and after the fused region.
16832 // Pre-fusion and post-fusion loops are inserted in order exploiting their
16833 // symmetry, along with their corresponding transformation pre-inits if
16834 // needed. The fused loop is added between the two regions.
16835 for (unsigned I : llvm::seq<unsigned>(SeqAnalysis.LoopSeqSize)) {
16836 if (I >= FirstVal - 1 && I < FirstVal + CountVal - 1) {
16837 // Update the Transformation counter to skip already treated
16838 // loop transformations
16839 if (!SeqAnalysis.Loops[I].isLoopTransformation())
16840 ++TransformIndex;
16841 continue;
16842 }
16843
16844 // No need to handle:
16845 // Regular loops: they are kept intact as-is.
16846 // Loop-sequence-generating transformations: already handled earlier.
16847 // Only TransformSingleLoop requires inserting pre-inits here
16848 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16849 const auto &TransformPreInit =
16850 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16851 if (!TransformPreInit.empty())
16852 llvm::append_range(PreInits, TransformPreInit);
16853 }
16854
16855 FinalLoops.push_back(SeqAnalysis.Loops[I].TheForStmt);
16856 }
16857
16858 FinalLoops.insert(FinalLoops.begin() + (FirstVal - 1), FusedForStmt);
16859 FusionStmt = CompoundStmt::Create(Context, FinalLoops, FPOptionsOverride(),
16861 }
16862 return OMPFuseDirective::Create(Context, StartLoc, EndLoc, Clauses,
16863 NumGeneratedTopLevelLoops, AStmt, FusionStmt,
16864 buildPreInits(Context, PreInits));
16865}
16866
16868 Expr *Expr,
16869 SourceLocation StartLoc,
16870 SourceLocation LParenLoc,
16871 SourceLocation EndLoc) {
16872 OMPClause *Res = nullptr;
16873 switch (Kind) {
16874 case OMPC_final:
16875 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
16876 break;
16877 case OMPC_safelen:
16878 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
16879 break;
16880 case OMPC_simdlen:
16881 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
16882 break;
16883 case OMPC_allocator:
16884 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
16885 break;
16886 case OMPC_collapse:
16887 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
16888 break;
16889 case OMPC_ordered:
16890 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
16891 break;
16892 case OMPC_nowait:
16893 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc, LParenLoc, Expr);
16894 break;
16895 case OMPC_priority:
16896 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
16897 break;
16898 case OMPC_hint:
16899 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
16900 break;
16901 case OMPC_depobj:
16902 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
16903 break;
16904 case OMPC_detach:
16905 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
16906 break;
16907 case OMPC_novariants:
16908 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
16909 break;
16910 case OMPC_nocontext:
16911 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
16912 break;
16913 case OMPC_filter:
16914 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
16915 break;
16916 case OMPC_partial:
16917 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
16918 break;
16919 case OMPC_message:
16920 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
16921 break;
16922 case OMPC_align:
16923 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
16924 break;
16925 case OMPC_ompx_dyn_cgroup_mem:
16926 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
16927 break;
16928 case OMPC_holds:
16929 Res = ActOnOpenMPHoldsClause(Expr, StartLoc, LParenLoc, EndLoc);
16930 break;
16931 case OMPC_transparent:
16932 Res = ActOnOpenMPTransparentClause(Expr, StartLoc, LParenLoc, EndLoc);
16933 break;
16934 case OMPC_dyn_groupprivate:
16935 case OMPC_grainsize:
16936 case OMPC_num_tasks:
16937 case OMPC_num_threads:
16938 case OMPC_device:
16939 case OMPC_if:
16940 case OMPC_default:
16941 case OMPC_proc_bind:
16942 case OMPC_schedule:
16943 case OMPC_private:
16944 case OMPC_firstprivate:
16945 case OMPC_lastprivate:
16946 case OMPC_shared:
16947 case OMPC_reduction:
16948 case OMPC_task_reduction:
16949 case OMPC_in_reduction:
16950 case OMPC_linear:
16951 case OMPC_aligned:
16952 case OMPC_copyin:
16953 case OMPC_copyprivate:
16954 case OMPC_untied:
16955 case OMPC_mergeable:
16956 case OMPC_threadprivate:
16957 case OMPC_groupprivate:
16958 case OMPC_sizes:
16959 case OMPC_allocate:
16960 case OMPC_flush:
16961 case OMPC_read:
16962 case OMPC_write:
16963 case OMPC_update:
16964 case OMPC_capture:
16965 case OMPC_compare:
16966 case OMPC_seq_cst:
16967 case OMPC_acq_rel:
16968 case OMPC_acquire:
16969 case OMPC_release:
16970 case OMPC_relaxed:
16971 case OMPC_depend:
16972 case OMPC_threads:
16973 case OMPC_simd:
16974 case OMPC_map:
16975 case OMPC_nogroup:
16976 case OMPC_dist_schedule:
16977 case OMPC_defaultmap:
16978 case OMPC_unknown:
16979 case OMPC_uniform:
16980 case OMPC_to:
16981 case OMPC_from:
16982 case OMPC_use_device_ptr:
16983 case OMPC_use_device_addr:
16984 case OMPC_is_device_ptr:
16985 case OMPC_unified_address:
16986 case OMPC_unified_shared_memory:
16987 case OMPC_reverse_offload:
16988 case OMPC_dynamic_allocators:
16989 case OMPC_atomic_default_mem_order:
16990 case OMPC_self_maps:
16991 case OMPC_device_type:
16992 case OMPC_match:
16993 case OMPC_nontemporal:
16994 case OMPC_order:
16995 case OMPC_at:
16996 case OMPC_severity:
16997 case OMPC_destroy:
16998 case OMPC_inclusive:
16999 case OMPC_exclusive:
17000 case OMPC_uses_allocators:
17001 case OMPC_affinity:
17002 case OMPC_when:
17003 case OMPC_bind:
17004 case OMPC_num_teams:
17005 case OMPC_thread_limit:
17006 default:
17007 llvm_unreachable("Clause is not allowed.");
17008 }
17009 return Res;
17010}
17011
17012// An OpenMP directive such as 'target parallel' has two captured regions:
17013// for the 'target' and 'parallel' respectively. This function returns
17014// the region in which to capture expressions associated with a clause.
17015// A return value of OMPD_unknown signifies that the expression should not
17016// be captured.
17018 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
17019 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
17020 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
17021 "Invalid directive with CKind-clause");
17022
17023 // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
17024 if (NameModifier != OMPD_unknown &&
17025 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
17026 return OMPD_unknown;
17027
17028 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(DKind);
17029
17030 // [5.2:341:24-30]
17031 // If the clauses have expressions on them, such as for various clauses where
17032 // the argument of the clause is an expression, or lower-bound, length, or
17033 // stride expressions inside array sections (or subscript and stride
17034 // expressions in subscript-triplet for Fortran), or linear-step or alignment
17035 // expressions, the expressions are evaluated immediately before the construct
17036 // to which the clause has been split or duplicated per the above rules
17037 // (therefore inside of the outer leaf constructs). However, the expressions
17038 // inside the num_teams and thread_limit clauses are always evaluated before
17039 // the outermost leaf construct.
17040
17041 // Process special cases first.
17042 switch (CKind) {
17043 case OMPC_if:
17044 switch (DKind) {
17045 case OMPD_teams_loop:
17046 case OMPD_target_teams_loop:
17047 // For [target] teams loop, assume capture region is 'teams' so it's
17048 // available for codegen later to use if/when necessary.
17049 return OMPD_teams;
17050 case OMPD_target_update:
17051 case OMPD_target_enter_data:
17052 case OMPD_target_exit_data:
17053 return OMPD_task;
17054 default:
17055 break;
17056 }
17057 break;
17058 case OMPC_num_teams:
17059 case OMPC_thread_limit:
17060 case OMPC_ompx_dyn_cgroup_mem:
17061 case OMPC_dyn_groupprivate:
17062 // TODO: This may need to consider teams too.
17063 if (Leafs[0] == OMPD_target)
17064 return OMPD_target;
17065 break;
17066 case OMPC_device:
17067 if (Leafs[0] == OMPD_target ||
17068 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
17069 OMPD_target_enter_data, OMPD_target_exit_data},
17070 DKind))
17071 return OMPD_task;
17072 break;
17073 case OMPC_novariants:
17074 case OMPC_nocontext:
17075 if (DKind == OMPD_dispatch)
17076 return OMPD_task;
17077 break;
17078 case OMPC_when:
17079 if (DKind == OMPD_metadirective)
17080 return OMPD_metadirective;
17081 break;
17082 case OMPC_filter:
17083 return OMPD_unknown;
17084 default:
17085 break;
17086 }
17087
17088 // If none of the special cases above applied, and DKind is a capturing
17089 // directive, find the innermost enclosing leaf construct that allows the
17090 // clause, and returns the corresponding capture region.
17091
17092 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
17093 // Find the index in "Leafs" of the last leaf that allows the given
17094 // clause. The search will only include indexes [0, EndIdx).
17095 // EndIdx may be set to the index of the NameModifier, if present.
17096 int InnermostIdx = [&]() {
17097 for (int I = EndIdx - 1; I >= 0; --I) {
17098 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
17099 return I;
17100 }
17101 return -1;
17102 }();
17103
17104 // Find the nearest enclosing capture region.
17106 for (int I = InnermostIdx - 1; I >= 0; --I) {
17107 if (!isOpenMPCapturingDirective(Leafs[I]))
17108 continue;
17109 Regions.clear();
17110 getOpenMPCaptureRegions(Regions, Leafs[I]);
17111 if (Regions[0] != OMPD_unknown)
17112 return Regions.back();
17113 }
17114 return OMPD_unknown;
17115 };
17116
17117 if (isOpenMPCapturingDirective(DKind)) {
17118 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
17119 for (int I = 0, E = Leafs.size(); I != E; ++I) {
17120 if (Leafs[I] == Dir)
17121 return I + 1;
17122 }
17123 return 0;
17124 };
17125
17126 int End = NameModifier == OMPD_unknown ? Leafs.size()
17127 : GetLeafIndex(NameModifier);
17128 return GetEnclosingRegion(End, CKind);
17129 }
17130
17131 return OMPD_unknown;
17132}
17133
17135 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
17136 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
17137 SourceLocation ColonLoc, SourceLocation EndLoc) {
17138 Expr *ValExpr = Condition;
17139 Stmt *HelperValStmt = nullptr;
17140 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17141 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17142 !Condition->isInstantiationDependent() &&
17143 !Condition->containsUnexpandedParameterPack()) {
17144 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
17145 if (Val.isInvalid())
17146 return nullptr;
17147
17148 ValExpr = Val.get();
17149
17150 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17151 CaptureRegion = getOpenMPCaptureRegionForClause(
17152 DKind, OMPC_if, getLangOpts().OpenMP, NameModifier);
17153 if (CaptureRegion != OMPD_unknown &&
17154 !SemaRef.CurContext->isDependentContext()) {
17155 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17156 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17157 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17158 HelperValStmt = buildPreInits(getASTContext(), Captures);
17159 }
17160 }
17161
17162 return new (getASTContext())
17163 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
17164 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
17165}
17166
17168 SourceLocation StartLoc,
17169 SourceLocation LParenLoc,
17170 SourceLocation EndLoc) {
17171 Expr *ValExpr = Condition;
17172 Stmt *HelperValStmt = nullptr;
17173 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17174 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17175 !Condition->isInstantiationDependent() &&
17176 !Condition->containsUnexpandedParameterPack()) {
17177 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
17178 if (Val.isInvalid())
17179 return nullptr;
17180
17181 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
17182
17183 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17184 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final,
17185 getLangOpts().OpenMP);
17186 if (CaptureRegion != OMPD_unknown &&
17187 !SemaRef.CurContext->isDependentContext()) {
17188 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17189 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17190 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17191 HelperValStmt = buildPreInits(getASTContext(), Captures);
17192 }
17193 }
17194
17195 return new (getASTContext()) OMPFinalClause(
17196 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17197}
17198
17201 Expr *Op) {
17202 if (!Op)
17203 return ExprError();
17204
17205 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
17206 public:
17207 IntConvertDiagnoser()
17208 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {}
17209 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
17210 QualType T) override {
17211 return S.Diag(Loc, diag::err_omp_not_integral) << T;
17212 }
17213 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
17214 QualType T) override {
17215 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
17216 }
17217 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
17218 QualType T,
17219 QualType ConvTy) override {
17220 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
17221 }
17222 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
17223 QualType ConvTy) override {
17224 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
17225 << ConvTy->isEnumeralType() << ConvTy;
17226 }
17227 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
17228 QualType T) override {
17229 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
17230 }
17231 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
17232 QualType ConvTy) override {
17233 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
17234 << ConvTy->isEnumeralType() << ConvTy;
17235 }
17236 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
17237 QualType) override {
17238 llvm_unreachable("conversion functions are permitted");
17239 }
17240 } ConvertDiagnoser;
17241 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
17242}
17243
17244static bool
17246 bool StrictlyPositive, bool BuildCapture = false,
17247 OpenMPDirectiveKind DKind = OMPD_unknown,
17248 OpenMPDirectiveKind *CaptureRegion = nullptr,
17249 Stmt **HelperValStmt = nullptr) {
17250 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
17251 !ValExpr->isInstantiationDependent()) {
17252 SourceLocation Loc = ValExpr->getExprLoc();
17254 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
17255 if (Value.isInvalid())
17256 return false;
17257
17258 ValExpr = Value.get();
17259 // The expression must evaluate to a non-negative integer value.
17260 if (std::optional<llvm::APSInt> Result =
17261 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
17262 if (Result->isSigned() &&
17263 !((!StrictlyPositive && Result->isNonNegative()) ||
17264 (StrictlyPositive && Result->isStrictlyPositive()))) {
17265 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
17266 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
17267 << ValExpr->getSourceRange();
17268 return false;
17269 }
17270 }
17271 if (!BuildCapture)
17272 return true;
17273 *CaptureRegion =
17274 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
17275 if (*CaptureRegion != OMPD_unknown &&
17276 !SemaRef.CurContext->isDependentContext()) {
17277 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17278 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17279 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17280 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
17281 }
17282 }
17283 return true;
17284}
17285
17286static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First,
17287 unsigned Last,
17288 ArrayRef<unsigned> Exclude = {}) {
17289 SmallString<256> Buffer;
17290 llvm::raw_svector_ostream Out(Buffer);
17291 unsigned Skipped = Exclude.size();
17292 for (unsigned I = First; I < Last; ++I) {
17293 if (llvm::is_contained(Exclude, I)) {
17294 --Skipped;
17295 continue;
17296 }
17297 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
17298 if (I + Skipped + 2 == Last)
17299 Out << " or ";
17300 else if (I + Skipped + 1 != Last)
17301 Out << ", ";
17302 }
17303 return std::string(Out.str());
17304}
17305
17307 OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads,
17308 SourceLocation StartLoc, SourceLocation LParenLoc,
17309 SourceLocation ModifierLoc, SourceLocation EndLoc) {
17310 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 60) &&
17311 "Unexpected num_threads modifier in OpenMP < 60.");
17312
17313 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTHREADS_unknown) {
17314 std::string Values = getListOfPossibleValues(OMPC_num_threads, /*First=*/0,
17316 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
17317 << Values << getOpenMPClauseNameForDiag(OMPC_num_threads);
17318 return nullptr;
17319 }
17320
17321 Expr *ValExpr = NumThreads;
17322 Stmt *HelperValStmt = nullptr;
17323
17324 // OpenMP [2.5, Restrictions]
17325 // The num_threads expression must evaluate to a positive integer value.
17326 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads,
17327 /*StrictlyPositive=*/true))
17328 return nullptr;
17329
17330 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17332 DKind, OMPC_num_threads, getLangOpts().OpenMP);
17333 if (CaptureRegion != OMPD_unknown &&
17334 !SemaRef.CurContext->isDependentContext()) {
17335 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17336 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17337 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17338 HelperValStmt = buildPreInits(getASTContext(), Captures);
17339 }
17340
17341 return new (getASTContext())
17342 OMPNumThreadsClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
17343 StartLoc, LParenLoc, ModifierLoc, EndLoc);
17344}
17345
17347 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
17348 bool SuppressExprDiags) {
17349 if (!E)
17350 return ExprError();
17351 if (E->isValueDependent() || E->isTypeDependent() ||
17353 return E;
17354
17355 llvm::APSInt Result;
17356 ExprResult ICE;
17357 if (SuppressExprDiags) {
17358 // Use a custom diagnoser that suppresses 'note' diagnostics about the
17359 // expression.
17360 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
17361 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
17363 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
17364 llvm_unreachable("Diagnostic suppressed");
17365 }
17366 } Diagnoser;
17367 ICE = SemaRef.VerifyIntegerConstantExpression(E, &Result, Diagnoser,
17369 } else {
17370 ICE =
17371 SemaRef.VerifyIntegerConstantExpression(E, &Result,
17372 /*FIXME*/ AllowFoldKind::Allow);
17373 }
17374 if (ICE.isInvalid())
17375 return ExprError();
17376
17377 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
17378 (!StrictlyPositive && !Result.isNonNegative())) {
17379 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
17380 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
17381 << E->getSourceRange();
17382 return ExprError();
17383 }
17384 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
17385 CKind == OMPC_allocate) &&
17386 !Result.isPowerOf2()) {
17387 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
17388 << E->getSourceRange();
17389 return ExprError();
17390 }
17391
17392 if (!Result.isRepresentableByInt64()) {
17393 Diag(E->getExprLoc(), diag::err_omp_large_expression_in_clause)
17395 return ExprError();
17396 }
17397
17398 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
17399 DSAStack->setAssociatedLoops(Result.getExtValue());
17400 else if (CKind == OMPC_ordered)
17401 DSAStack->setAssociatedLoops(Result.getExtValue());
17402 return ICE;
17403}
17404
17405void SemaOpenMP::setOpenMPDeviceNum(int Num) { DeviceNum = Num; }
17406
17407void SemaOpenMP::setOpenMPDeviceNumID(StringRef ID) { DeviceNumID = ID; }
17408
17409int SemaOpenMP::getOpenMPDeviceNum() const { return DeviceNum; }
17410
17412 llvm::APSInt Result;
17413 Expr::EvalResult EvalResult;
17414 // Evaluate the expression to an integer value
17415 if (!DeviceNumExpr->isValueDependent() &&
17416 DeviceNumExpr->EvaluateAsInt(EvalResult, SemaRef.Context)) {
17417 // The device expression must evaluate to a non-negative integer value.
17418 Result = EvalResult.Val.getInt();
17419 if (Result.isNonNegative()) {
17420 setOpenMPDeviceNum(Result.getZExtValue());
17421 } else {
17422 Diag(DeviceNumExpr->getExprLoc(),
17423 diag::err_omp_negative_expression_in_clause)
17424 << "device_num" << 0 << DeviceNumExpr->getSourceRange();
17425 }
17426 } else if (auto *DeclRef = dyn_cast<DeclRefExpr>(DeviceNumExpr)) {
17427 // Check if the expression is an identifier
17428 IdentifierInfo *IdInfo = DeclRef->getDecl()->getIdentifier();
17429 if (IdInfo) {
17430 setOpenMPDeviceNumID(IdInfo->getName());
17431 }
17432 } else {
17433 Diag(DeviceNumExpr->getExprLoc(), diag::err_expected_expression);
17434 }
17435}
17436
17438 SourceLocation StartLoc,
17439 SourceLocation LParenLoc,
17440 SourceLocation EndLoc) {
17441 // OpenMP [2.8.1, simd construct, Description]
17442 // The parameter of the safelen clause must be a constant
17443 // positive integer expression.
17444 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
17445 if (Safelen.isInvalid())
17446 return nullptr;
17447 return new (getASTContext())
17448 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
17449}
17450
17452 SourceLocation StartLoc,
17453 SourceLocation LParenLoc,
17454 SourceLocation EndLoc) {
17455 // OpenMP [2.8.1, simd construct, Description]
17456 // The parameter of the simdlen clause must be a constant
17457 // positive integer expression.
17458 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
17459 if (Simdlen.isInvalid())
17460 return nullptr;
17461 return new (getASTContext())
17462 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
17463}
17464
17465/// Tries to find omp_allocator_handle_t type.
17467 DSAStackTy *Stack) {
17468 if (!Stack->getOMPAllocatorHandleT().isNull())
17469 return true;
17470
17471 // Set the allocator handle type.
17472 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
17473 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
17474 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
17475 S.Diag(Loc, diag::err_omp_implied_type_not_found)
17476 << "omp_allocator_handle_t";
17477 return false;
17478 }
17479 QualType AllocatorHandleEnumTy = PT.get();
17480 AllocatorHandleEnumTy.addConst();
17481 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
17482
17483 // Fill the predefined allocator map.
17484 bool ErrorFound = false;
17485 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
17486 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
17487 StringRef Allocator =
17488 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
17489 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
17490 auto *VD = dyn_cast_or_null<ValueDecl>(
17491 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
17492 if (!VD) {
17493 ErrorFound = true;
17494 break;
17495 }
17496 QualType AllocatorType =
17498 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
17499 if (!Res.isUsable()) {
17500 ErrorFound = true;
17501 break;
17502 }
17503 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
17505 /*AllowExplicit=*/true);
17506 if (!Res.isUsable()) {
17507 ErrorFound = true;
17508 break;
17509 }
17510 Stack->setAllocator(AllocatorKind, Res.get());
17511 }
17512 if (ErrorFound) {
17513 S.Diag(Loc, diag::err_omp_implied_type_not_found)
17514 << "omp_allocator_handle_t";
17515 return false;
17516 }
17517
17518 return true;
17519}
17520
17522 SourceLocation StartLoc,
17523 SourceLocation LParenLoc,
17524 SourceLocation EndLoc) {
17525 // OpenMP [2.11.3, allocate Directive, Description]
17526 // allocator is an expression of omp_allocator_handle_t type.
17528 return nullptr;
17529
17530 ExprResult Allocator = SemaRef.DefaultLvalueConversion(A);
17531 if (Allocator.isInvalid())
17532 return nullptr;
17533 Allocator = SemaRef.PerformImplicitConversion(
17534 Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
17536 /*AllowExplicit=*/true);
17537 if (Allocator.isInvalid())
17538 return nullptr;
17539 return new (getASTContext())
17540 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
17541}
17542
17544 SourceLocation StartLoc,
17545 SourceLocation LParenLoc,
17546 SourceLocation EndLoc) {
17547 // OpenMP [2.7.1, loop construct, Description]
17548 // OpenMP [2.8.1, simd construct, Description]
17549 // OpenMP [2.9.6, distribute construct, Description]
17550 // The parameter of the collapse clause must be a constant
17551 // positive integer expression.
17552 ExprResult NumForLoopsResult =
17553 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
17554 if (NumForLoopsResult.isInvalid())
17555 return nullptr;
17556 return new (getASTContext())
17557 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
17558}
17559
17561 SourceLocation EndLoc,
17562 SourceLocation LParenLoc,
17563 Expr *NumForLoops) {
17564 // OpenMP [2.7.1, loop construct, Description]
17565 // OpenMP [2.8.1, simd construct, Description]
17566 // OpenMP [2.9.6, distribute construct, Description]
17567 // The parameter of the ordered clause must be a constant
17568 // positive integer expression if any.
17569 if (NumForLoops && LParenLoc.isValid()) {
17570 ExprResult NumForLoopsResult =
17571 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
17572 if (NumForLoopsResult.isInvalid())
17573 return nullptr;
17574 NumForLoops = NumForLoopsResult.get();
17575 } else {
17576 NumForLoops = nullptr;
17577 }
17578 auto *Clause =
17579 OMPOrderedClause::Create(getASTContext(), NumForLoops,
17580 NumForLoops ? DSAStack->getAssociatedLoops() : 0,
17581 StartLoc, LParenLoc, EndLoc);
17582 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
17583 return Clause;
17584}
17585
17587 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
17588 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17589 OMPClause *Res = nullptr;
17590 switch (Kind) {
17591 case OMPC_proc_bind:
17592 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
17593 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17594 break;
17595 case OMPC_atomic_default_mem_order:
17597 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
17598 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17599 break;
17600 case OMPC_fail:
17601 Res = ActOnOpenMPFailClause(static_cast<OpenMPClauseKind>(Argument),
17602 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17603 break;
17604 case OMPC_update:
17605 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
17606 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17607 break;
17608 case OMPC_bind:
17609 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
17610 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17611 break;
17612 case OMPC_at:
17613 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
17614 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17615 break;
17616 case OMPC_severity:
17618 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
17619 LParenLoc, EndLoc);
17620 break;
17621 case OMPC_threadset:
17622 Res = ActOnOpenMPThreadsetClause(static_cast<OpenMPThreadsetKind>(Argument),
17623 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17624 break;
17625 case OMPC_if:
17626 case OMPC_final:
17627 case OMPC_num_threads:
17628 case OMPC_safelen:
17629 case OMPC_simdlen:
17630 case OMPC_sizes:
17631 case OMPC_allocator:
17632 case OMPC_collapse:
17633 case OMPC_schedule:
17634 case OMPC_private:
17635 case OMPC_firstprivate:
17636 case OMPC_lastprivate:
17637 case OMPC_shared:
17638 case OMPC_reduction:
17639 case OMPC_task_reduction:
17640 case OMPC_in_reduction:
17641 case OMPC_linear:
17642 case OMPC_aligned:
17643 case OMPC_copyin:
17644 case OMPC_copyprivate:
17645 case OMPC_ordered:
17646 case OMPC_nowait:
17647 case OMPC_untied:
17648 case OMPC_mergeable:
17649 case OMPC_threadprivate:
17650 case OMPC_groupprivate:
17651 case OMPC_allocate:
17652 case OMPC_flush:
17653 case OMPC_depobj:
17654 case OMPC_read:
17655 case OMPC_write:
17656 case OMPC_capture:
17657 case OMPC_compare:
17658 case OMPC_seq_cst:
17659 case OMPC_acq_rel:
17660 case OMPC_acquire:
17661 case OMPC_release:
17662 case OMPC_relaxed:
17663 case OMPC_depend:
17664 case OMPC_device:
17665 case OMPC_threads:
17666 case OMPC_simd:
17667 case OMPC_map:
17668 case OMPC_num_teams:
17669 case OMPC_thread_limit:
17670 case OMPC_priority:
17671 case OMPC_grainsize:
17672 case OMPC_nogroup:
17673 case OMPC_num_tasks:
17674 case OMPC_hint:
17675 case OMPC_dist_schedule:
17676 case OMPC_default:
17677 case OMPC_defaultmap:
17678 case OMPC_unknown:
17679 case OMPC_uniform:
17680 case OMPC_to:
17681 case OMPC_from:
17682 case OMPC_use_device_ptr:
17683 case OMPC_use_device_addr:
17684 case OMPC_is_device_ptr:
17685 case OMPC_has_device_addr:
17686 case OMPC_unified_address:
17687 case OMPC_unified_shared_memory:
17688 case OMPC_reverse_offload:
17689 case OMPC_dynamic_allocators:
17690 case OMPC_self_maps:
17691 case OMPC_device_type:
17692 case OMPC_match:
17693 case OMPC_nontemporal:
17694 case OMPC_destroy:
17695 case OMPC_novariants:
17696 case OMPC_nocontext:
17697 case OMPC_detach:
17698 case OMPC_inclusive:
17699 case OMPC_exclusive:
17700 case OMPC_uses_allocators:
17701 case OMPC_affinity:
17702 case OMPC_when:
17703 case OMPC_message:
17704 default:
17705 llvm_unreachable("Clause is not allowed.");
17706 }
17707 return Res;
17708}
17709
17711 llvm::omp::DefaultKind M, SourceLocation MLoc,
17713 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17714 if (M == OMP_DEFAULT_unknown) {
17715 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17716 << getListOfPossibleValues(OMPC_default, /*First=*/0,
17717 /*Last=*/unsigned(OMP_DEFAULT_unknown))
17718 << getOpenMPClauseNameForDiag(OMPC_default);
17719 return nullptr;
17720 }
17721 if (VCKind == OMPC_DEFAULT_VC_unknown) {
17722 Diag(VCKindLoc, diag::err_omp_default_vc)
17723 << getOpenMPSimpleClauseTypeName(OMPC_default, unsigned(M));
17724 return nullptr;
17725 }
17726
17727 bool IsTargetDefault =
17728 getLangOpts().OpenMP >= 60 &&
17729 isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective());
17730
17731 // OpenMP 6.0, page 224, lines 3-4 default Clause, Semantics
17732 // If data-sharing-attribute is shared then the clause has no effect
17733 // on a target construct;
17734 if (IsTargetDefault && M == OMP_DEFAULT_shared)
17735 return nullptr;
17736
17737 auto SetDefaultClauseAttrs = [&](llvm::omp::DefaultKind M,
17740 OpenMPDefaultmapClauseKind DefMapKind;
17741 // default data-sharing-attribute
17742 switch (M) {
17743 case OMP_DEFAULT_none:
17744 if (IsTargetDefault)
17745 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_none;
17746 else
17747 DSAStack->setDefaultDSANone(MLoc);
17748 break;
17749 case OMP_DEFAULT_firstprivate:
17750 if (IsTargetDefault)
17751 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_firstprivate;
17752 else
17753 DSAStack->setDefaultDSAFirstPrivate(MLoc);
17754 break;
17755 case OMP_DEFAULT_private:
17756 if (IsTargetDefault)
17757 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_private;
17758 else
17759 DSAStack->setDefaultDSAPrivate(MLoc);
17760 break;
17761 case OMP_DEFAULT_shared:
17762 assert(!IsTargetDefault && "DSA shared invalid with target directive");
17763 DSAStack->setDefaultDSAShared(MLoc);
17764 break;
17765 default:
17766 llvm_unreachable("unexpected DSA in OpenMP default clause");
17767 }
17768 // default variable-category
17769 switch (VCKind) {
17770 case OMPC_DEFAULT_VC_aggregate:
17771 if (IsTargetDefault)
17772 DefMapKind = OMPC_DEFAULTMAP_aggregate;
17773 else
17774 DSAStack->setDefaultDSAVCAggregate(VCKindLoc);
17775 break;
17776 case OMPC_DEFAULT_VC_pointer:
17777 if (IsTargetDefault)
17778 DefMapKind = OMPC_DEFAULTMAP_pointer;
17779 else
17780 DSAStack->setDefaultDSAVCPointer(VCKindLoc);
17781 break;
17782 case OMPC_DEFAULT_VC_scalar:
17783 if (IsTargetDefault)
17784 DefMapKind = OMPC_DEFAULTMAP_scalar;
17785 else
17786 DSAStack->setDefaultDSAVCScalar(VCKindLoc);
17787 break;
17788 case OMPC_DEFAULT_VC_all:
17789 if (IsTargetDefault)
17790 DefMapKind = OMPC_DEFAULTMAP_all;
17791 else
17792 DSAStack->setDefaultDSAVCAll(VCKindLoc);
17793 break;
17794 default:
17795 llvm_unreachable("unexpected variable category in OpenMP default clause");
17796 }
17797 // OpenMP 6.0, page 224, lines 4-5 default Clause, Semantics
17798 // otherwise, its effect on a target construct is equivalent to
17799 // specifying the defaultmap clause with the same data-sharing-attribute
17800 // and variable-category.
17801 //
17802 // If earlier than OpenMP 6.0, or not a target directive, the default DSA
17803 // is/was set as before.
17804 if (IsTargetDefault) {
17805 if (DefMapKind == OMPC_DEFAULTMAP_all) {
17806 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_aggregate, MLoc);
17807 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_scalar, MLoc);
17808 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_pointer, MLoc);
17809 } else {
17810 DSAStack->setDefaultDMAAttr(DefMapMod, DefMapKind, MLoc);
17811 }
17812 }
17813 };
17814
17815 SetDefaultClauseAttrs(M, VCKind);
17816 return new (getASTContext())
17817 OMPDefaultClause(M, MLoc, VCKind, VCKindLoc, StartLoc, LParenLoc, EndLoc);
17818}
17819
17821 SourceLocation KindLoc,
17822 SourceLocation StartLoc,
17823 SourceLocation LParenLoc,
17824 SourceLocation EndLoc) {
17825 if (Kind == OMPC_THREADSET_unknown) {
17826 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17827 << getListOfPossibleValues(OMPC_threadset, /*First=*/0,
17828 /*Last=*/unsigned(OMPC_THREADSET_unknown))
17829 << getOpenMPClauseName(OMPC_threadset);
17830 return nullptr;
17831 }
17832
17833 return new (getASTContext())
17834 OMPThreadsetClause(Kind, KindLoc, StartLoc, LParenLoc, EndLoc);
17835}
17836
17837static OMPClause *
17838createTransparentClause(Sema &SemaRef, ASTContext &Ctx, Expr *ImpexTypeArg,
17839 Stmt *HelperValStmt, OpenMPDirectiveKind CaptureRegion,
17840 SourceLocation StartLoc, SourceLocation LParenLoc,
17841 SourceLocation EndLoc) {
17842 ExprResult ER = SemaRef.DefaultLvalueConversion(ImpexTypeArg);
17843 if (ER.isInvalid())
17844 return nullptr;
17845
17846 return new (Ctx) OMPTransparentClause(ER.get(), HelperValStmt, CaptureRegion,
17847 StartLoc, LParenLoc, EndLoc);
17848}
17849
17851 SourceLocation StartLoc,
17852 SourceLocation LParenLoc,
17853 SourceLocation EndLoc) {
17854 Stmt *HelperValStmt = nullptr;
17855 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17857 DKind, OMPC_transparent, getLangOpts().OpenMP);
17858 if (CaptureRegion != OMPD_unknown &&
17859 !SemaRef.CurContext->isDependentContext()) {
17860 Expr *ValExpr = SemaRef.MakeFullExpr(ImpexTypeArg).get();
17861 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17862 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17863 HelperValStmt = buildPreInits(getASTContext(), Captures);
17864 }
17865 if (!ImpexTypeArg) {
17866 return new (getASTContext())
17867 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
17868 StartLoc, LParenLoc, EndLoc);
17869 }
17870 QualType Ty = ImpexTypeArg->getType();
17871
17872 if (const auto *TT = Ty->getAs<TypedefType>()) {
17873 const TypedefNameDecl *TypedefDecl = TT->getDecl();
17874 llvm::StringRef TypedefName = TypedefDecl->getName();
17875 IdentifierInfo &II = SemaRef.PP.getIdentifierTable().get(TypedefName);
17876 ParsedType ImpexTy =
17877 SemaRef.getTypeName(II, StartLoc, SemaRef.getCurScope());
17878 if (!ImpexTy.getAsOpaquePtr() || ImpexTy.get().isNull()) {
17879 SemaRef.Diag(StartLoc, diag::err_omp_implied_type_not_found)
17880 << TypedefName;
17881 return nullptr;
17882 }
17883 return new (getASTContext())
17884 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
17885 StartLoc, LParenLoc, EndLoc);
17886 }
17887
17888 if (Ty->isEnumeralType())
17889 return createTransparentClause(SemaRef, getASTContext(), ImpexTypeArg,
17890 HelperValStmt, CaptureRegion, StartLoc,
17891 LParenLoc, EndLoc);
17892 if (Ty->isIntegerType()) {
17893 if (isNonNegativeIntegerValue(ImpexTypeArg, SemaRef, OMPC_transparent,
17894 /*StrictlyPositive=*/false)) {
17896 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(StartLoc,
17897 ImpexTypeArg);
17898 if (std::optional<llvm::APSInt> Result =
17899 Value.get()->getIntegerConstantExpr(SemaRef.Context)) {
17900 if (Result->isNegative() ||
17901 Result >
17902 static_cast<int64_t>(SemaOpenMP::OpenMPImpexType::OMP_Export))
17903 SemaRef.Diag(StartLoc, diag::err_omp_transparent_invalid_value);
17904 }
17905 return new (getASTContext())
17906 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
17907 StartLoc, LParenLoc, EndLoc);
17908 }
17909 }
17910 if (!isNonNegativeIntegerValue(ImpexTypeArg, SemaRef, OMPC_transparent,
17911 /*StrictlyPositive=*/true))
17912 return nullptr;
17913 return new (getASTContext()) OMPTransparentClause(
17914 ImpexTypeArg, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17915}
17916
17918 SourceLocation KindKwLoc,
17919 SourceLocation StartLoc,
17920 SourceLocation LParenLoc,
17921 SourceLocation EndLoc) {
17922 if (Kind == OMP_PROC_BIND_unknown) {
17923 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17924 << getListOfPossibleValues(OMPC_proc_bind,
17925 /*First=*/unsigned(OMP_PROC_BIND_master),
17926 /*Last=*/
17927 unsigned(getLangOpts().OpenMP > 50
17928 ? OMP_PROC_BIND_primary
17929 : OMP_PROC_BIND_spread) +
17930 1)
17931 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
17932 return nullptr;
17933 }
17934 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
17935 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17936 << getListOfPossibleValues(OMPC_proc_bind,
17937 /*First=*/unsigned(OMP_PROC_BIND_master),
17938 /*Last=*/
17939 unsigned(OMP_PROC_BIND_spread) + 1)
17940 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
17941 return new (getASTContext())
17942 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17943}
17944
17947 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17949 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17951 OMPC_atomic_default_mem_order, /*First=*/0,
17953 << getOpenMPClauseNameForDiag(OMPC_atomic_default_mem_order);
17954 return nullptr;
17955 }
17956 return new (getASTContext()) OMPAtomicDefaultMemOrderClause(
17957 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17958}
17959
17961 SourceLocation KindKwLoc,
17962 SourceLocation StartLoc,
17963 SourceLocation LParenLoc,
17964 SourceLocation EndLoc) {
17965 if (Kind == OMPC_AT_unknown) {
17966 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17967 << getListOfPossibleValues(OMPC_at, /*First=*/0,
17968 /*Last=*/OMPC_AT_unknown)
17969 << getOpenMPClauseNameForDiag(OMPC_at);
17970 return nullptr;
17971 }
17972 return new (getASTContext())
17973 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17974}
17975
17977 SourceLocation KindKwLoc,
17978 SourceLocation StartLoc,
17979 SourceLocation LParenLoc,
17980 SourceLocation EndLoc) {
17981 if (Kind == OMPC_SEVERITY_unknown) {
17982 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17983 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
17984 /*Last=*/OMPC_SEVERITY_unknown)
17985 << getOpenMPClauseNameForDiag(OMPC_severity);
17986 return nullptr;
17987 }
17988 return new (getASTContext())
17989 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17990}
17991
17993 SourceLocation StartLoc,
17994 SourceLocation LParenLoc,
17995 SourceLocation EndLoc) {
17996 assert(ME && "NULL expr in Message clause");
17997 QualType Type = ME->getType();
17998 if ((!Type->isPointerType() && !Type->isArrayType()) ||
18000 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
18001 << getOpenMPClauseNameForDiag(OMPC_message) << 0;
18002 return nullptr;
18003 }
18004
18005 Stmt *HelperValStmt = nullptr;
18006
18007 // Depending on whether this clause appears in an executable context or not,
18008 // we may or may not build a capture.
18009 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18010 OpenMPDirectiveKind CaptureRegion =
18011 DKind == OMPD_unknown ? OMPD_unknown
18013 DKind, OMPC_message, getLangOpts().OpenMP);
18014 if (CaptureRegion != OMPD_unknown &&
18015 !SemaRef.CurContext->isDependentContext()) {
18016 ME = SemaRef.MakeFullExpr(ME).get();
18017 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18018 ME = tryBuildCapture(SemaRef, ME, Captures).get();
18019 HelperValStmt = buildPreInits(getASTContext(), Captures);
18020 }
18021
18022 // Convert array type to pointer type if needed.
18023 ME = SemaRef.DefaultFunctionArrayLvalueConversion(ME).get();
18024
18025 return new (getASTContext()) OMPMessageClause(
18026 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18027}
18028
18031 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
18032 SourceLocation KindLoc, SourceLocation EndLoc) {
18033 if (Kind != OMPC_ORDER_concurrent ||
18034 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
18035 // Kind should be concurrent,
18036 // Modifiers introduced in OpenMP 5.1
18037 static_assert(OMPC_ORDER_unknown > 0,
18038 "OMPC_ORDER_unknown not greater than 0");
18039
18040 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
18041 << getListOfPossibleValues(OMPC_order,
18042 /*First=*/0,
18043 /*Last=*/OMPC_ORDER_unknown)
18044 << getOpenMPClauseNameForDiag(OMPC_order);
18045 return nullptr;
18046 }
18047 if (getLangOpts().OpenMP >= 51 && Modifier == OMPC_ORDER_MODIFIER_unknown &&
18048 MLoc.isValid()) {
18049 Diag(MLoc, diag::err_omp_unexpected_clause_value)
18050 << getListOfPossibleValues(OMPC_order,
18051 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
18052 /*Last=*/OMPC_ORDER_MODIFIER_last)
18053 << getOpenMPClauseNameForDiag(OMPC_order);
18054 } else if (getLangOpts().OpenMP >= 50) {
18055 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
18056 if (DSAStack->getCurScope()) {
18057 // mark the current scope with 'order' flag
18058 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
18059 DSAStack->getCurScope()->setFlags(existingFlags |
18061 }
18062 }
18063 return new (getASTContext()) OMPOrderClause(
18064 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
18065}
18066
18068 SourceLocation KindKwLoc,
18069 SourceLocation StartLoc,
18070 SourceLocation LParenLoc,
18071 SourceLocation EndLoc) {
18072 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
18073 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
18074 SmallVector<unsigned> Except = {
18075 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
18076 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
18077 if (getLangOpts().OpenMP < 51)
18078 Except.push_back(OMPC_DEPEND_inoutset);
18079 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
18080 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
18081 /*Last=*/OMPC_DEPEND_unknown, Except)
18082 << getOpenMPClauseNameForDiag(OMPC_update);
18083 return nullptr;
18084 }
18085 return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc,
18086 KindKwLoc, Kind, EndLoc);
18087}
18088
18090 SourceLocation StartLoc,
18091 SourceLocation LParenLoc,
18092 SourceLocation EndLoc) {
18093 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
18094
18095 for (Expr *&SizeExpr : SanitizedSizeExprs) {
18096 // Skip if already sanitized, e.g. during a partial template instantiation.
18097 if (!SizeExpr)
18098 continue;
18099
18100 bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes,
18101 /*StrictlyPositive=*/true);
18102
18103 // isNonNegativeIntegerValue returns true for non-integral types (but still
18104 // emits error diagnostic), so check for the expected type explicitly.
18105 QualType SizeTy = SizeExpr->getType();
18106 if (!SizeTy->isIntegerType())
18107 IsValid = false;
18108
18109 // Handling in templates is tricky. There are four possibilities to
18110 // consider:
18111 //
18112 // 1a. The expression is valid and we are in a instantiated template or not
18113 // in a template:
18114 // Pass valid expression to be further analysed later in Sema.
18115 // 1b. The expression is valid and we are in a template (including partial
18116 // instantiation):
18117 // isNonNegativeIntegerValue skipped any checks so there is no
18118 // guarantee it will be correct after instantiation.
18119 // ActOnOpenMPSizesClause will be called again at instantiation when
18120 // it is not in a dependent context anymore. This may cause warnings
18121 // to be emitted multiple times.
18122 // 2a. The expression is invalid and we are in an instantiated template or
18123 // not in a template:
18124 // Invalidate the expression with a clearly wrong value (nullptr) so
18125 // later in Sema we do not have to do the same validity analysis again
18126 // or crash from unexpected data. Error diagnostics have already been
18127 // emitted.
18128 // 2b. The expression is invalid and we are in a template (including partial
18129 // instantiation):
18130 // Pass the invalid expression as-is, template instantiation may
18131 // replace unexpected types/values with valid ones. The directives
18132 // with this clause must not try to use these expressions in dependent
18133 // contexts, but delay analysis until full instantiation.
18134 if (!SizeExpr->isInstantiationDependent() && !IsValid)
18135 SizeExpr = nullptr;
18136 }
18137
18138 return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
18139 SanitizedSizeExprs);
18140}
18141
18143 SourceLocation StartLoc,
18144 SourceLocation LParenLoc,
18145 SourceLocation EndLoc,
18146 std::optional<unsigned> FillIdx,
18147 SourceLocation FillLoc,
18148 unsigned FillCount) {
18149 SmallVector<Expr *> SanitizedCountExprs(CountExprs);
18150
18151 // OpenMP 6.0: each list item in counts(...) is either the omp_fill keyword
18152 // or an integral constant expression (non-negative). Runtime variables are
18153 // not permitted; this matches split codegen, which needs segment sizes at
18154 // compile time.
18155 for (unsigned I = 0; I < SanitizedCountExprs.size(); ++I) {
18156 Expr *&CountExpr = SanitizedCountExprs[I];
18157 if (FillIdx && I == *FillIdx)
18158 continue;
18159 if (!CountExpr)
18160 continue;
18161
18163 CountExpr, OMPC_counts, /*StrictlyPositive=*/false);
18164 if (Verified.isInvalid())
18165 CountExpr = nullptr;
18166 else
18167 CountExpr = Verified.get();
18168 }
18169
18170 if (FillCount != 1) {
18171 Diag(FillCount == 0 ? StartLoc : FillLoc,
18172 diag::err_omp_split_counts_not_one_omp_fill);
18173 }
18174
18175 return OMPCountsClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
18176 SanitizedCountExprs, FillIdx, FillLoc);
18177}
18178
18180 SourceLocation StartLoc,
18181 SourceLocation LParenLoc,
18182 SourceLocation EndLoc) {
18183 size_t NumLoops = PermExprs.size();
18184 SmallVector<Expr *> SanitizedPermExprs;
18185 llvm::append_range(SanitizedPermExprs, PermExprs);
18186
18187 for (Expr *&PermExpr : SanitizedPermExprs) {
18188 // Skip if template-dependent or already sanitized, e.g. during a partial
18189 // template instantiation.
18190 if (!PermExpr || PermExpr->isInstantiationDependent())
18191 continue;
18192
18193 llvm::APSInt PermVal;
18194 ExprResult PermEvalExpr = SemaRef.VerifyIntegerConstantExpression(
18195 PermExpr, &PermVal, AllowFoldKind::Allow);
18196 bool IsValid = PermEvalExpr.isUsable();
18197 if (IsValid)
18198 PermExpr = PermEvalExpr.get();
18199
18200 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
18201 SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
18202 PermEvalExpr.get()->getEndLoc());
18203 Diag(PermEvalExpr.get()->getExprLoc(),
18204 diag::err_omp_interchange_permutation_value_range)
18205 << NumLoops << ExprRange;
18206 IsValid = false;
18207 }
18208
18209 if (!PermExpr->isInstantiationDependent() && !IsValid)
18210 PermExpr = nullptr;
18211 }
18212
18213 return OMPPermutationClause::Create(getASTContext(), StartLoc, LParenLoc,
18214 EndLoc, SanitizedPermExprs);
18215}
18216
18218 SourceLocation EndLoc) {
18219 return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc);
18220}
18221
18223 SourceLocation StartLoc,
18224 SourceLocation LParenLoc,
18225 SourceLocation EndLoc) {
18226 if (FactorExpr) {
18227 // If an argument is specified, it must be a constant (or an unevaluated
18228 // template expression).
18230 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
18231 if (FactorResult.isInvalid())
18232 return nullptr;
18233 FactorExpr = FactorResult.get();
18234 }
18235
18236 return OMPPartialClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
18237 FactorExpr);
18238}
18239
18241 Expr *First, Expr *Count, SourceLocation StartLoc, SourceLocation LParenLoc,
18242 SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc) {
18243
18244 // OpenMP [6.0, Restrictions]
18245 // First and Count must be integer expressions with positive value
18246 ExprResult FirstVal =
18248 if (FirstVal.isInvalid())
18249 First = nullptr;
18250
18251 ExprResult CountVal =
18252 VerifyPositiveIntegerConstantInClause(Count, OMPC_looprange);
18253 if (CountVal.isInvalid())
18254 Count = nullptr;
18255
18256 // OpenMP [6.0, Restrictions]
18257 // first + count - 1 must not evaluate to a value greater than the
18258 // loop sequence length of the associated canonical loop sequence.
18259 // This check must be performed afterwards due to the delayed
18260 // parsing and computation of the associated loop sequence
18261 return OMPLoopRangeClause::Create(getASTContext(), StartLoc, LParenLoc,
18262 FirstLoc, CountLoc, EndLoc, First, Count);
18263}
18264
18266 SourceLocation LParenLoc,
18267 SourceLocation EndLoc) {
18268 ExprResult AlignVal;
18269 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
18270 if (AlignVal.isInvalid())
18271 return nullptr;
18272 return OMPAlignClause::Create(getASTContext(), AlignVal.get(), StartLoc,
18273 LParenLoc, EndLoc);
18274}
18275
18278 SourceLocation StartLoc, SourceLocation LParenLoc,
18279 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
18280 SourceLocation EndLoc) {
18281 OMPClause *Res = nullptr;
18282 switch (Kind) {
18283 case OMPC_schedule: {
18284 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
18285 assert(Argument.size() == NumberOfElements &&
18286 ArgumentLoc.size() == NumberOfElements);
18288 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
18289 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
18290 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
18291 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
18292 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
18293 break;
18294 }
18295 case OMPC_if:
18296 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
18297 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
18298 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
18299 DelimLoc, EndLoc);
18300 break;
18301 case OMPC_dist_schedule:
18303 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
18304 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
18305 break;
18306 case OMPC_default:
18307 enum { DefaultModifier, DefaultVarCategory };
18309 static_cast<llvm::omp::DefaultKind>(Argument[DefaultModifier]),
18310 ArgumentLoc[DefaultModifier],
18312 Argument[DefaultVarCategory]),
18313 ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc);
18314 break;
18315 case OMPC_defaultmap:
18316 enum { Modifier, DefaultmapKind };
18318 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
18319 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
18320 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
18321 EndLoc);
18322 break;
18323 case OMPC_order:
18324 enum { OrderModifier, OrderKind };
18326 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
18327 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
18328 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
18329 break;
18330 case OMPC_device:
18331 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
18333 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
18334 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
18335 break;
18336 case OMPC_grainsize:
18337 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
18338 "Modifier for grainsize clause and its location are expected.");
18340 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
18341 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
18342 break;
18343 case OMPC_num_tasks:
18344 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
18345 "Modifier for num_tasks clause and its location are expected.");
18347 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
18348 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
18349 break;
18350 case OMPC_dyn_groupprivate: {
18351 enum { Modifier1, Modifier2, NumberOfElements };
18352 assert(Argument.size() == NumberOfElements &&
18353 ArgumentLoc.size() == NumberOfElements &&
18354 "Modifiers for dyn_groupprivate clause and their locations are "
18355 "expected.");
18357 static_cast<OpenMPDynGroupprivateClauseModifier>(Argument[Modifier1]),
18359 Argument[Modifier2]),
18360 Expr, StartLoc, LParenLoc, ArgumentLoc[Modifier1],
18361 ArgumentLoc[Modifier2], EndLoc);
18362 break;
18363 }
18364 case OMPC_num_threads:
18365 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
18366 "Modifier for num_threads clause and its location are expected.");
18368 static_cast<OpenMPNumThreadsClauseModifier>(Argument.back()), Expr,
18369 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
18370 break;
18371 case OMPC_final:
18372 case OMPC_safelen:
18373 case OMPC_simdlen:
18374 case OMPC_sizes:
18375 case OMPC_allocator:
18376 case OMPC_collapse:
18377 case OMPC_proc_bind:
18378 case OMPC_private:
18379 case OMPC_firstprivate:
18380 case OMPC_lastprivate:
18381 case OMPC_shared:
18382 case OMPC_reduction:
18383 case OMPC_task_reduction:
18384 case OMPC_in_reduction:
18385 case OMPC_linear:
18386 case OMPC_aligned:
18387 case OMPC_copyin:
18388 case OMPC_copyprivate:
18389 case OMPC_ordered:
18390 case OMPC_nowait:
18391 case OMPC_untied:
18392 case OMPC_mergeable:
18393 case OMPC_threadprivate:
18394 case OMPC_groupprivate:
18395 case OMPC_allocate:
18396 case OMPC_flush:
18397 case OMPC_depobj:
18398 case OMPC_read:
18399 case OMPC_write:
18400 case OMPC_update:
18401 case OMPC_capture:
18402 case OMPC_compare:
18403 case OMPC_seq_cst:
18404 case OMPC_acq_rel:
18405 case OMPC_acquire:
18406 case OMPC_release:
18407 case OMPC_relaxed:
18408 case OMPC_depend:
18409 case OMPC_threads:
18410 case OMPC_simd:
18411 case OMPC_map:
18412 case OMPC_num_teams:
18413 case OMPC_thread_limit:
18414 case OMPC_priority:
18415 case OMPC_nogroup:
18416 case OMPC_hint:
18417 case OMPC_unknown:
18418 case OMPC_uniform:
18419 case OMPC_to:
18420 case OMPC_from:
18421 case OMPC_use_device_ptr:
18422 case OMPC_use_device_addr:
18423 case OMPC_is_device_ptr:
18424 case OMPC_has_device_addr:
18425 case OMPC_unified_address:
18426 case OMPC_unified_shared_memory:
18427 case OMPC_reverse_offload:
18428 case OMPC_dynamic_allocators:
18429 case OMPC_atomic_default_mem_order:
18430 case OMPC_self_maps:
18431 case OMPC_device_type:
18432 case OMPC_match:
18433 case OMPC_nontemporal:
18434 case OMPC_at:
18435 case OMPC_severity:
18436 case OMPC_message:
18437 case OMPC_destroy:
18438 case OMPC_novariants:
18439 case OMPC_nocontext:
18440 case OMPC_detach:
18441 case OMPC_inclusive:
18442 case OMPC_exclusive:
18443 case OMPC_uses_allocators:
18444 case OMPC_affinity:
18445 case OMPC_when:
18446 case OMPC_bind:
18447 default:
18448 llvm_unreachable("Clause is not allowed.");
18449 }
18450 return Res;
18451}
18452
18455 SourceLocation M1Loc, SourceLocation M2Loc) {
18456 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
18457 SmallVector<unsigned, 2> Excluded;
18459 Excluded.push_back(M2);
18460 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
18461 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
18462 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
18463 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
18464 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
18465 << getListOfPossibleValues(OMPC_schedule,
18466 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
18468 Excluded)
18469 << getOpenMPClauseNameForDiag(OMPC_schedule);
18470 return true;
18471 }
18472 return false;
18473}
18474
18477 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
18478 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
18479 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
18480 if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) ||
18481 checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc))
18482 return nullptr;
18483 // OpenMP, 2.7.1, Loop Construct, Restrictions
18484 // Either the monotonic modifier or the nonmonotonic modifier can be specified
18485 // but not both.
18486 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
18487 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
18488 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
18489 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
18490 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
18491 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
18492 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
18493 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
18494 return nullptr;
18495 }
18496 if (Kind == OMPC_SCHEDULE_unknown) {
18497 std::string Values;
18498 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
18499 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
18500 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
18502 Exclude);
18503 } else {
18504 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
18505 /*Last=*/OMPC_SCHEDULE_unknown);
18506 }
18507 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
18508 << Values << getOpenMPClauseNameForDiag(OMPC_schedule);
18509 return nullptr;
18510 }
18511 // OpenMP, 2.7.1, Loop Construct, Restrictions
18512 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
18513 // schedule(guided).
18514 // OpenMP 5.0 does not have this restriction.
18515 if (getLangOpts().OpenMP < 50 &&
18516 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
18517 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
18518 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
18519 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
18520 diag::err_omp_schedule_nonmonotonic_static);
18521 return nullptr;
18522 }
18523 Expr *ValExpr = ChunkSize;
18524 Stmt *HelperValStmt = nullptr;
18525 if (ChunkSize) {
18526 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
18527 !ChunkSize->isInstantiationDependent() &&
18528 !ChunkSize->containsUnexpandedParameterPack()) {
18529 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
18530 ExprResult Val =
18531 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
18532 if (Val.isInvalid())
18533 return nullptr;
18534
18535 ValExpr = Val.get();
18536
18537 // OpenMP [2.7.1, Restrictions]
18538 // chunk_size must be a loop invariant integer expression with a positive
18539 // value.
18540 if (std::optional<llvm::APSInt> Result =
18542 if (Result->isSigned() && !Result->isStrictlyPositive()) {
18543 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
18544 << "schedule" << 1 << ChunkSize->getSourceRange();
18545 return nullptr;
18546 }
18548 DSAStack->getCurrentDirective(), OMPC_schedule,
18549 getLangOpts().OpenMP) != OMPD_unknown &&
18550 !SemaRef.CurContext->isDependentContext()) {
18551 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18552 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18553 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18554 HelperValStmt = buildPreInits(getASTContext(), Captures);
18555 }
18556 }
18557 }
18558
18559 return new (getASTContext())
18560 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
18561 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
18562}
18563
18565 SourceLocation StartLoc,
18566 SourceLocation EndLoc) {
18567 OMPClause *Res = nullptr;
18568 switch (Kind) {
18569 case OMPC_ordered:
18570 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
18571 break;
18572 case OMPC_nowait:
18573 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc,
18574 /*LParenLoc=*/SourceLocation(),
18575 /*Condition=*/nullptr);
18576 break;
18577 case OMPC_untied:
18578 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
18579 break;
18580 case OMPC_mergeable:
18581 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
18582 break;
18583 case OMPC_read:
18584 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
18585 break;
18586 case OMPC_write:
18587 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
18588 break;
18589 case OMPC_update:
18590 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
18591 break;
18592 case OMPC_capture:
18593 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
18594 break;
18595 case OMPC_compare:
18596 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
18597 break;
18598 case OMPC_fail:
18599 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
18600 break;
18601 case OMPC_seq_cst:
18602 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
18603 break;
18604 case OMPC_acq_rel:
18605 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
18606 break;
18607 case OMPC_acquire:
18608 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
18609 break;
18610 case OMPC_release:
18611 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
18612 break;
18613 case OMPC_relaxed:
18614 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
18615 break;
18616 case OMPC_weak:
18617 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
18618 break;
18619 case OMPC_threads:
18620 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
18621 break;
18622 case OMPC_simd:
18623 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
18624 break;
18625 case OMPC_nogroup:
18626 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
18627 break;
18628 case OMPC_unified_address:
18629 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
18630 break;
18631 case OMPC_unified_shared_memory:
18632 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
18633 break;
18634 case OMPC_reverse_offload:
18635 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
18636 break;
18637 case OMPC_dynamic_allocators:
18638 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
18639 break;
18640 case OMPC_self_maps:
18641 Res = ActOnOpenMPSelfMapsClause(StartLoc, EndLoc);
18642 break;
18643 case OMPC_destroy:
18644 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
18645 /*LParenLoc=*/SourceLocation(),
18646 /*VarLoc=*/SourceLocation(), EndLoc);
18647 break;
18648 case OMPC_full:
18649 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
18650 break;
18651 case OMPC_partial:
18652 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
18653 break;
18654 case OMPC_ompx_bare:
18655 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
18656 break;
18657 case OMPC_if:
18658 case OMPC_final:
18659 case OMPC_num_threads:
18660 case OMPC_safelen:
18661 case OMPC_simdlen:
18662 case OMPC_sizes:
18663 case OMPC_allocator:
18664 case OMPC_collapse:
18665 case OMPC_schedule:
18666 case OMPC_private:
18667 case OMPC_firstprivate:
18668 case OMPC_lastprivate:
18669 case OMPC_shared:
18670 case OMPC_reduction:
18671 case OMPC_task_reduction:
18672 case OMPC_in_reduction:
18673 case OMPC_linear:
18674 case OMPC_aligned:
18675 case OMPC_copyin:
18676 case OMPC_copyprivate:
18677 case OMPC_default:
18678 case OMPC_proc_bind:
18679 case OMPC_threadprivate:
18680 case OMPC_groupprivate:
18681 case OMPC_allocate:
18682 case OMPC_flush:
18683 case OMPC_depobj:
18684 case OMPC_depend:
18685 case OMPC_device:
18686 case OMPC_map:
18687 case OMPC_num_teams:
18688 case OMPC_thread_limit:
18689 case OMPC_priority:
18690 case OMPC_grainsize:
18691 case OMPC_num_tasks:
18692 case OMPC_hint:
18693 case OMPC_dist_schedule:
18694 case OMPC_defaultmap:
18695 case OMPC_unknown:
18696 case OMPC_uniform:
18697 case OMPC_to:
18698 case OMPC_from:
18699 case OMPC_use_device_ptr:
18700 case OMPC_use_device_addr:
18701 case OMPC_is_device_ptr:
18702 case OMPC_has_device_addr:
18703 case OMPC_atomic_default_mem_order:
18704 case OMPC_device_type:
18705 case OMPC_match:
18706 case OMPC_nontemporal:
18707 case OMPC_order:
18708 case OMPC_at:
18709 case OMPC_severity:
18710 case OMPC_message:
18711 case OMPC_novariants:
18712 case OMPC_nocontext:
18713 case OMPC_detach:
18714 case OMPC_inclusive:
18715 case OMPC_exclusive:
18716 case OMPC_uses_allocators:
18717 case OMPC_affinity:
18718 case OMPC_when:
18719 case OMPC_ompx_dyn_cgroup_mem:
18720 case OMPC_dyn_groupprivate:
18721 default:
18722 llvm_unreachable("Clause is not allowed.");
18723 }
18724 return Res;
18725}
18726
18728 SourceLocation EndLoc,
18729 SourceLocation LParenLoc,
18730 Expr *Condition) {
18731 Expr *ValExpr = Condition;
18732 if (Condition && LParenLoc.isValid()) {
18733 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18734 !Condition->isInstantiationDependent() &&
18735 !Condition->containsUnexpandedParameterPack()) {
18736 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
18737 if (Val.isInvalid())
18738 return nullptr;
18739
18740 ValExpr = Val.get();
18741 }
18742 }
18743 DSAStack->setNowaitRegion();
18744 return new (getASTContext())
18745 OMPNowaitClause(ValExpr, StartLoc, LParenLoc, EndLoc);
18746}
18747
18749 SourceLocation EndLoc) {
18750 DSAStack->setUntiedRegion();
18751 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
18752}
18753
18755 SourceLocation EndLoc) {
18756 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
18757}
18758
18760 SourceLocation EndLoc) {
18761 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
18762}
18763
18765 SourceLocation EndLoc) {
18766 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
18767}
18768
18770 SourceLocation EndLoc) {
18771 return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc);
18772}
18773
18775 SourceLocation EndLoc) {
18776 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
18777}
18778
18780 SourceLocation EndLoc) {
18781 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
18782}
18783
18785 SourceLocation EndLoc) {
18786 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
18787}
18788
18790 SourceLocation KindLoc,
18791 SourceLocation StartLoc,
18792 SourceLocation LParenLoc,
18793 SourceLocation EndLoc) {
18794
18796 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
18797 return nullptr;
18798 }
18799 return new (getASTContext())
18800 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
18801}
18802
18804 SourceLocation EndLoc) {
18805 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
18806}
18807
18809 SourceLocation EndLoc) {
18810 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
18811}
18812
18814 SourceLocation EndLoc) {
18815 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
18816}
18817
18819 SourceLocation EndLoc) {
18820 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
18821}
18822
18824 SourceLocation EndLoc) {
18825 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
18826}
18827
18829 SourceLocation EndLoc) {
18830 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
18831}
18832
18834 SourceLocation EndLoc) {
18835 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
18836}
18837
18839 SourceLocation EndLoc) {
18840 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
18841}
18842
18844 SourceLocation EndLoc) {
18845 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
18846}
18847
18849 SourceLocation EndLoc) {
18850 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
18851}
18852
18853OMPClause *
18855 SourceLocation EndLoc) {
18856 return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
18857}
18858
18860 SourceLocation EndLoc) {
18861 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
18862}
18863
18864OMPClause *
18866 SourceLocation EndLoc) {
18867 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
18868}
18869
18871 SourceLocation EndLoc) {
18872 return new (getASTContext()) OMPSelfMapsClause(StartLoc, EndLoc);
18873}
18874
18877 SourceLocation StartLoc,
18878 SourceLocation EndLoc) {
18879
18880 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18881 // At least one action-clause must appear on a directive.
18882 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
18883 unsigned OMPVersion = getLangOpts().OpenMP;
18884 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
18885 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
18886 << Expected << getOpenMPDirectiveName(OMPD_interop, OMPVersion);
18887 return StmtError();
18888 }
18889
18890 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18891 // A depend clause can only appear on the directive if a targetsync
18892 // interop-type is present or the interop-var was initialized with
18893 // the targetsync interop-type.
18894
18895 // If there is any 'init' clause diagnose if there is no 'init' clause with
18896 // interop-type of 'targetsync'. Cases involving other directives cannot be
18897 // diagnosed.
18898 const OMPDependClause *DependClause = nullptr;
18899 bool HasInitClause = false;
18900 bool IsTargetSync = false;
18901 for (const OMPClause *C : Clauses) {
18902 if (IsTargetSync)
18903 break;
18904 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
18905 HasInitClause = true;
18906 if (InitClause->getIsTargetSync())
18907 IsTargetSync = true;
18908 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
18909 DependClause = DC;
18910 }
18911 }
18912 if (DependClause && HasInitClause && !IsTargetSync) {
18913 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
18914 return StmtError();
18915 }
18916
18917 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18918 // Each interop-var may be specified for at most one action-clause of each
18919 // interop construct.
18921 for (OMPClause *C : Clauses) {
18922 OpenMPClauseKind ClauseKind = C->getClauseKind();
18923 std::pair<ValueDecl *, bool> DeclResult;
18924 SourceLocation ELoc;
18925 SourceRange ERange;
18926
18927 if (ClauseKind == OMPC_init) {
18928 auto *E = cast<OMPInitClause>(C)->getInteropVar();
18929 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18930 } else if (ClauseKind == OMPC_use) {
18931 auto *E = cast<OMPUseClause>(C)->getInteropVar();
18932 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18933 } else if (ClauseKind == OMPC_destroy) {
18934 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
18935 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18936 }
18937
18938 if (DeclResult.first) {
18939 if (!InteropVars.insert(DeclResult.first).second) {
18940 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
18941 << DeclResult.first;
18942 return StmtError();
18943 }
18944 }
18945 }
18946
18947 return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc,
18948 Clauses);
18949}
18950
18951static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
18952 SourceLocation VarLoc,
18953 OpenMPClauseKind Kind) {
18954 SourceLocation ELoc;
18955 SourceRange ERange;
18956 Expr *RefExpr = InteropVarExpr;
18957 auto Res = getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
18958 /*AllowArraySection=*/false,
18959 /*AllowAssumedSizeArray=*/false,
18960 /*DiagType=*/"omp_interop_t");
18961
18962 if (Res.second) {
18963 // It will be analyzed later.
18964 return true;
18965 }
18966
18967 if (!Res.first)
18968 return false;
18969
18970 // Interop variable should be of type omp_interop_t.
18971 bool HasError = false;
18972 QualType InteropType;
18973 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
18974 VarLoc, Sema::LookupOrdinaryName);
18975 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
18976 NamedDecl *ND = Result.getFoundDecl();
18977 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
18978 InteropType = QualType(TD->getTypeForDecl(), 0);
18979 } else {
18980 HasError = true;
18981 }
18982 } else {
18983 HasError = true;
18984 }
18985
18986 if (HasError) {
18987 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
18988 << "omp_interop_t";
18989 return false;
18990 }
18991
18992 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
18993 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
18994 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
18995 return false;
18996 }
18997
18998 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18999 // The interop-var passed to init or destroy must be non-const.
19000 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
19001 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
19002 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
19003 << /*non-const*/ 1;
19004 return false;
19005 }
19006 return true;
19007}
19008
19010 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
19011 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
19012
19013 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init))
19014 return nullptr;
19015
19016 // Check prefer_type values. fr() arguments are either string literals or
19017 // constant integral expressions; null Fr is only valid in OMP 6.0.
19018 // attr() arguments must be ext-string-literals with the 'ompx_' prefix
19019 // (OpenMP 6.0 spec, section 16.1.3).
19020 for (const OMPInteropPref &P : InteropInfo.Prefs) {
19021 const Expr *E = P.Fr;
19022 if (!E) {
19023 assert(InteropInfo.HasPreferAttrs && "null Fr requires OMP 6.0 syntax");
19024 } else if (!E->isValueDependent() && !E->isTypeDependent() &&
19028 !isa<StringLiteral>(E)) {
19029 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
19030 return nullptr;
19031 }
19032 }
19033 for (const Expr *A : P.Attrs) {
19034 if (A->isValueDependent() || A->isTypeDependent() ||
19036 continue;
19037 const auto *SL = dyn_cast<StringLiteral>(A);
19038 if (!SL) {
19039 Diag(A->getExprLoc(), diag::err_omp_interop_attr_not_string);
19040 return nullptr;
19041 }
19042 if (!SL->getString().starts_with("ompx_")) {
19043 Diag(A->getExprLoc(), diag::err_omp_interop_attr_missing_ompx_prefix)
19044 << SL->getString();
19045 return nullptr;
19046 }
19047 if (SL->getString().contains(',')) {
19048 Diag(A->getExprLoc(), diag::err_omp_interop_attr_contains_comma)
19049 << SL->getString();
19050 return nullptr;
19051 }
19052 }
19053 }
19054
19055 return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo,
19056 StartLoc, LParenLoc, VarLoc, EndLoc);
19057}
19058
19060 SourceLocation StartLoc,
19061 SourceLocation LParenLoc,
19062 SourceLocation VarLoc,
19063 SourceLocation EndLoc) {
19064
19065 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use))
19066 return nullptr;
19067
19068 return new (getASTContext())
19069 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
19070}
19071
19073 SourceLocation StartLoc,
19074 SourceLocation LParenLoc,
19075 SourceLocation VarLoc,
19076 SourceLocation EndLoc) {
19077 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
19078 DSAStack->getCurrentDirective() == OMPD_depobj) {
19079 unsigned OMPVersion = getLangOpts().OpenMP;
19080 Diag(StartLoc, diag::err_omp_expected_clause_argument)
19081 << getOpenMPClauseNameForDiag(OMPC_destroy)
19082 << getOpenMPDirectiveName(OMPD_depobj, OMPVersion);
19083 return nullptr;
19084 }
19085 if (InteropVar &&
19086 !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy))
19087 return nullptr;
19088
19089 return new (getASTContext())
19090 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
19091}
19092
19094 SourceLocation StartLoc,
19095 SourceLocation LParenLoc,
19096 SourceLocation EndLoc) {
19097 Expr *ValExpr = Condition;
19098 Stmt *HelperValStmt = nullptr;
19099 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
19100 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
19101 !Condition->isInstantiationDependent() &&
19102 !Condition->containsUnexpandedParameterPack()) {
19103 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
19104 if (Val.isInvalid())
19105 return nullptr;
19106
19107 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
19108
19109 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
19110 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
19111 getLangOpts().OpenMP);
19112 if (CaptureRegion != OMPD_unknown &&
19113 !SemaRef.CurContext->isDependentContext()) {
19114 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
19115 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19116 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
19117 HelperValStmt = buildPreInits(getASTContext(), Captures);
19118 }
19119 }
19120
19121 return new (getASTContext()) OMPNovariantsClause(
19122 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
19123}
19124
19126 SourceLocation StartLoc,
19127 SourceLocation LParenLoc,
19128 SourceLocation EndLoc) {
19129 Expr *ValExpr = Condition;
19130 Stmt *HelperValStmt = nullptr;
19131 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
19132 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
19133 !Condition->isInstantiationDependent() &&
19134 !Condition->containsUnexpandedParameterPack()) {
19135 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
19136 if (Val.isInvalid())
19137 return nullptr;
19138
19139 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
19140
19141 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
19142 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext,
19143 getLangOpts().OpenMP);
19144 if (CaptureRegion != OMPD_unknown &&
19145 !SemaRef.CurContext->isDependentContext()) {
19146 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
19147 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19148 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
19149 HelperValStmt = buildPreInits(getASTContext(), Captures);
19150 }
19151 }
19152
19153 return new (getASTContext()) OMPNocontextClause(
19154 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
19155}
19156
19158 SourceLocation StartLoc,
19159 SourceLocation LParenLoc,
19160 SourceLocation EndLoc) {
19161 Expr *ValExpr = ThreadID;
19162 Stmt *HelperValStmt = nullptr;
19163
19164 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
19165 OpenMPDirectiveKind CaptureRegion =
19166 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP);
19167 if (CaptureRegion != OMPD_unknown &&
19168 !SemaRef.CurContext->isDependentContext()) {
19169 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
19170 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19171 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
19172 HelperValStmt = buildPreInits(getASTContext(), Captures);
19173 }
19174
19175 return new (getASTContext()) OMPFilterClause(
19176 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
19177}
19178
19180 ArrayRef<Expr *> VarList,
19181 const OMPVarListLocTy &Locs,
19183 SourceLocation StartLoc = Locs.StartLoc;
19184 SourceLocation LParenLoc = Locs.LParenLoc;
19185 SourceLocation EndLoc = Locs.EndLoc;
19186 OMPClause *Res = nullptr;
19187 int ExtraModifier = Data.ExtraModifier;
19188 int OriginalSharingModifier = Data.OriginalSharingModifier;
19189 Expr *ExtraModifierExpr = Data.ExtraModifierExpr;
19190 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
19191 SourceLocation ColonLoc = Data.ColonLoc;
19192 switch (Kind) {
19193 case OMPC_private:
19194 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
19195 break;
19196 case OMPC_firstprivate:
19197 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
19198 break;
19199 case OMPC_lastprivate:
19200 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
19201 "Unexpected lastprivate modifier.");
19203 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
19204 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
19205 break;
19206 case OMPC_shared:
19207 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
19208 break;
19209 case OMPC_reduction:
19210 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
19211 "Unexpected lastprivate modifier.");
19213 VarList,
19215 ExtraModifier, OriginalSharingModifier),
19216 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
19217 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
19218 break;
19219 case OMPC_task_reduction:
19221 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
19222 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
19223 break;
19224 case OMPC_in_reduction:
19226 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
19227 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
19228 break;
19229 case OMPC_linear:
19230 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
19231 "Unexpected linear modifier.");
19233 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
19234 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
19235 ColonLoc, Data.StepModifierLoc, EndLoc);
19236 break;
19237 case OMPC_aligned:
19238 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
19239 LParenLoc, ColonLoc, EndLoc);
19240 break;
19241 case OMPC_copyin:
19242 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
19243 break;
19244 case OMPC_copyprivate:
19245 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
19246 break;
19247 case OMPC_flush:
19248 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
19249 break;
19250 case OMPC_depend:
19251 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
19252 "Unexpected depend modifier.");
19254 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
19255 ColonLoc, Data.OmpAllMemoryLoc},
19256 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
19257 break;
19258 case OMPC_map:
19259 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
19260 "Unexpected map modifier.");
19262 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
19263 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
19264 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
19265 ExtraModifierLoc, ColonLoc, VarList, Locs);
19266 break;
19267 case OMPC_to:
19268 Res = ActOnOpenMPToClause(
19269 Data.MotionModifiers, Data.MotionModifiersLoc, Data.IteratorExpr,
19270 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, ColonLoc,
19271 VarList, Locs);
19272 break;
19273 case OMPC_from:
19275 Data.MotionModifiers, Data.MotionModifiersLoc, Data.IteratorExpr,
19276 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, ColonLoc,
19277 VarList, Locs);
19278 break;
19279 case OMPC_use_device_ptr:
19280 assert(0 <= Data.ExtraModifier &&
19281 Data.ExtraModifier <= OMPC_USE_DEVICE_PTR_FALLBACK_unknown &&
19282 "Unexpected use_device_ptr fallback modifier.");
19284 VarList, Locs,
19285 static_cast<OpenMPUseDevicePtrFallbackModifier>(Data.ExtraModifier),
19286 Data.ExtraModifierLoc);
19287 break;
19288 case OMPC_use_device_addr:
19289 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
19290 break;
19291 case OMPC_is_device_ptr:
19292 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
19293 break;
19294 case OMPC_has_device_addr:
19295 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
19296 break;
19297 case OMPC_allocate: {
19300 SourceLocation Modifier1Loc, Modifier2Loc;
19301 if (!Data.AllocClauseModifiers.empty()) {
19302 assert(Data.AllocClauseModifiers.size() <= 2 &&
19303 "More allocate modifiers than expected");
19304 Modifier1 = Data.AllocClauseModifiers[0];
19305 Modifier1Loc = Data.AllocClauseModifiersLoc[0];
19306 if (Data.AllocClauseModifiers.size() == 2) {
19307 Modifier2 = Data.AllocClauseModifiers[1];
19308 Modifier2Loc = Data.AllocClauseModifiersLoc[1];
19309 }
19310 }
19312 Data.DepModOrTailExpr, Data.AllocateAlignment, Modifier1, Modifier1Loc,
19313 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
19314 EndLoc);
19315 break;
19316 }
19317 case OMPC_nontemporal:
19318 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
19319 break;
19320 case OMPC_inclusive:
19321 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
19322 break;
19323 case OMPC_exclusive:
19324 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
19325 break;
19326 case OMPC_affinity:
19327 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
19328 Data.DepModOrTailExpr, VarList);
19329 break;
19330 case OMPC_doacross:
19332 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
19333 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
19334 break;
19335 case OMPC_num_teams:
19336 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_NUMTEAMS_unknown &&
19337 "Unexpected num_teams modifier.");
19339 VarList, static_cast<OpenMPNumTeamsClauseModifier>(ExtraModifier),
19340 ExtraModifierExpr, ExtraModifierLoc, StartLoc, LParenLoc, EndLoc);
19341 break;
19342 case OMPC_thread_limit:
19343 Res = ActOnOpenMPThreadLimitClause(VarList, StartLoc, LParenLoc, EndLoc);
19344 break;
19345 case OMPC_if:
19346 case OMPC_depobj:
19347 case OMPC_final:
19348 case OMPC_num_threads:
19349 case OMPC_safelen:
19350 case OMPC_simdlen:
19351 case OMPC_sizes:
19352 case OMPC_allocator:
19353 case OMPC_collapse:
19354 case OMPC_default:
19355 case OMPC_proc_bind:
19356 case OMPC_schedule:
19357 case OMPC_ordered:
19358 case OMPC_nowait:
19359 case OMPC_untied:
19360 case OMPC_mergeable:
19361 case OMPC_threadprivate:
19362 case OMPC_groupprivate:
19363 case OMPC_read:
19364 case OMPC_write:
19365 case OMPC_update:
19366 case OMPC_capture:
19367 case OMPC_compare:
19368 case OMPC_seq_cst:
19369 case OMPC_acq_rel:
19370 case OMPC_acquire:
19371 case OMPC_release:
19372 case OMPC_relaxed:
19373 case OMPC_device:
19374 case OMPC_threads:
19375 case OMPC_simd:
19376 case OMPC_priority:
19377 case OMPC_grainsize:
19378 case OMPC_nogroup:
19379 case OMPC_num_tasks:
19380 case OMPC_hint:
19381 case OMPC_dist_schedule:
19382 case OMPC_defaultmap:
19383 case OMPC_unknown:
19384 case OMPC_uniform:
19385 case OMPC_unified_address:
19386 case OMPC_unified_shared_memory:
19387 case OMPC_reverse_offload:
19388 case OMPC_dynamic_allocators:
19389 case OMPC_atomic_default_mem_order:
19390 case OMPC_self_maps:
19391 case OMPC_device_type:
19392 case OMPC_match:
19393 case OMPC_order:
19394 case OMPC_at:
19395 case OMPC_severity:
19396 case OMPC_message:
19397 case OMPC_destroy:
19398 case OMPC_novariants:
19399 case OMPC_nocontext:
19400 case OMPC_detach:
19401 case OMPC_uses_allocators:
19402 case OMPC_when:
19403 case OMPC_bind:
19404 default:
19405 llvm_unreachable("Clause is not allowed.");
19406 }
19407 return Res;
19408}
19409
19411 ExprObjectKind OK,
19412 SourceLocation Loc) {
19413 ExprResult Res = SemaRef.BuildDeclRefExpr(
19414 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
19415 if (!Res.isUsable())
19416 return ExprError();
19417 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
19418 Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
19419 if (!Res.isUsable())
19420 return ExprError();
19421 }
19422 if (VK != VK_LValue && Res.get()->isGLValue()) {
19423 Res = SemaRef.DefaultLvalueConversion(Res.get());
19424 if (!Res.isUsable())
19425 return ExprError();
19426 }
19427 return Res;
19428}
19429
19431 SourceLocation StartLoc,
19432 SourceLocation LParenLoc,
19433 SourceLocation EndLoc) {
19435 SmallVector<Expr *, 8> PrivateCopies;
19436 unsigned OMPVersion = getLangOpts().OpenMP;
19437 bool IsImplicitClause =
19438 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
19439 for (Expr *RefExpr : VarList) {
19440 assert(RefExpr && "NULL expr in OpenMP private clause.");
19441 SourceLocation ELoc;
19442 SourceRange ERange;
19443 Expr *SimpleRefExpr = RefExpr;
19444 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19445 if (Res.second) {
19446 // It will be analyzed later.
19447 Vars.push_back(RefExpr);
19448 PrivateCopies.push_back(nullptr);
19449 }
19450 ValueDecl *D = Res.first;
19451 if (!D)
19452 continue;
19453
19454 QualType Type = D->getType();
19455 auto *VD = dyn_cast<VarDecl>(D);
19456
19457 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19458 // A variable that appears in a private clause must not have an incomplete
19459 // type or a reference type.
19460 if (SemaRef.RequireCompleteType(ELoc, Type,
19461 diag::err_omp_private_incomplete_type))
19462 continue;
19463 Type = Type.getNonReferenceType();
19464
19465 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19466 // A variable that is privatized must not have a const-qualified type
19467 // unless it is of class type with a mutable member. This restriction does
19468 // not apply to the firstprivate clause.
19469 //
19470 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
19471 // A variable that appears in a private clause must not have a
19472 // const-qualified type unless it is of class type with a mutable member.
19473 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc))
19474 continue;
19475
19476 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19477 // in a Construct]
19478 // Variables with the predetermined data-sharing attributes may not be
19479 // listed in data-sharing attributes clauses, except for the cases
19480 // listed below. For these exceptions only, listing a predetermined
19481 // variable in a data-sharing attribute clause is allowed and overrides
19482 // the variable's predetermined data-sharing attributes.
19483 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19484 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
19485 Diag(ELoc, diag::err_omp_wrong_dsa)
19486 << getOpenMPClauseNameForDiag(DVar.CKind)
19487 << getOpenMPClauseNameForDiag(OMPC_private);
19489 continue;
19490 }
19491
19492 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19493 // Variably modified types are not supported for tasks.
19495 isOpenMPTaskingDirective(CurrDir)) {
19496 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19497 << getOpenMPClauseNameForDiag(OMPC_private) << Type
19498 << getOpenMPDirectiveName(CurrDir, OMPVersion);
19499 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19501 Diag(D->getLocation(),
19502 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19503 << D;
19504 continue;
19505 }
19506
19507 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
19508 // A list item cannot appear in both a map clause and a data-sharing
19509 // attribute clause on the same construct
19510 //
19511 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
19512 // A list item cannot appear in both a map clause and a data-sharing
19513 // attribute clause on the same construct unless the construct is a
19514 // combined construct.
19515 if ((getLangOpts().OpenMP <= 45 &&
19517 CurrDir == OMPD_target) {
19518 OpenMPClauseKind ConflictKind;
19519 if (DSAStack->checkMappableExprComponentListsForDecl(
19520 VD, /*CurrentRegionOnly=*/true,
19522 OpenMPClauseKind WhereFoundClauseKind) -> bool {
19523 ConflictKind = WhereFoundClauseKind;
19524 return true;
19525 })) {
19526 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
19527 << getOpenMPClauseNameForDiag(OMPC_private)
19528 << getOpenMPClauseNameForDiag(ConflictKind)
19529 << getOpenMPDirectiveName(CurrDir, OMPVersion);
19531 continue;
19532 }
19533 }
19534
19535 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
19536 // A variable of class type (or array thereof) that appears in a private
19537 // clause requires an accessible, unambiguous default constructor for the
19538 // class type.
19539 // Generate helper private variable and initialize it with the default
19540 // value. The address of the original variable is replaced by the address of
19541 // the new private variable in CodeGen. This new variable is not added to
19542 // IdResolver, so the code in the OpenMP region uses original variable for
19543 // proper diagnostics.
19544 Type = Type.getUnqualifiedType();
19545 VarDecl *VDPrivate =
19546 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
19547 D->hasAttrs() ? &D->getAttrs() : nullptr,
19548 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19549 SemaRef.ActOnUninitializedDecl(VDPrivate);
19550 if (VDPrivate->isInvalidDecl())
19551 continue;
19552 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
19553 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
19554
19555 DeclRefExpr *Ref = nullptr;
19556 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19557 auto *FD = dyn_cast<FieldDecl>(D);
19558 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
19559 if (VD)
19561 RefExpr->getExprLoc());
19562 else
19563 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19564 }
19565 if (!IsImplicitClause)
19566 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
19567 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19568 ? RefExpr->IgnoreParens()
19569 : Ref);
19570 PrivateCopies.push_back(VDPrivateRefExpr);
19571 }
19572
19573 if (Vars.empty())
19574 return nullptr;
19575
19576 return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19577 Vars, PrivateCopies);
19578}
19579
19581 SourceLocation StartLoc,
19582 SourceLocation LParenLoc,
19583 SourceLocation EndLoc) {
19585 SmallVector<Expr *, 8> PrivateCopies;
19587 SmallVector<Decl *, 4> ExprCaptures;
19588 bool IsImplicitClause =
19589 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
19590 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
19591 unsigned OMPVersion = getLangOpts().OpenMP;
19592
19593 for (Expr *RefExpr : VarList) {
19594 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
19595 SourceLocation ELoc;
19596 SourceRange ERange;
19597 Expr *SimpleRefExpr = RefExpr;
19598 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19599 if (Res.second) {
19600 // It will be analyzed later.
19601 Vars.push_back(RefExpr);
19602 PrivateCopies.push_back(nullptr);
19603 Inits.push_back(nullptr);
19604 }
19605 ValueDecl *D = Res.first;
19606 if (!D)
19607 continue;
19608
19609 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
19610 QualType Type = D->getType();
19611 auto *VD = dyn_cast<VarDecl>(D);
19612
19613 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19614 // A variable that appears in a private clause must not have an incomplete
19615 // type or a reference type.
19616 if (SemaRef.RequireCompleteType(ELoc, Type,
19617 diag::err_omp_firstprivate_incomplete_type))
19618 continue;
19619 Type = Type.getNonReferenceType();
19620
19621 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
19622 // A variable of class type (or array thereof) that appears in a private
19623 // clause requires an accessible, unambiguous copy constructor for the
19624 // class type.
19625 QualType ElemType =
19627
19628 // If an implicit firstprivate variable found it was checked already.
19629 DSAStackTy::DSAVarData TopDVar;
19630 if (!IsImplicitClause) {
19631 DSAStackTy::DSAVarData DVar =
19632 DSAStack->getTopDSA(D, /*FromParent=*/false);
19633 TopDVar = DVar;
19634 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19635 bool IsConstant = ElemType.isConstant(getASTContext());
19636 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
19637 // A list item that specifies a given variable may not appear in more
19638 // than one clause on the same directive, except that a variable may be
19639 // specified in both firstprivate and lastprivate clauses.
19640 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
19641 // A list item may appear in a firstprivate or lastprivate clause but not
19642 // both.
19643 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
19644 (isOpenMPDistributeDirective(CurrDir) ||
19645 DVar.CKind != OMPC_lastprivate) &&
19646 DVar.RefExpr) {
19647 Diag(ELoc, diag::err_omp_wrong_dsa)
19648 << getOpenMPClauseNameForDiag(DVar.CKind)
19649 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
19651 continue;
19652 }
19653
19654 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19655 // in a Construct]
19656 // Variables with the predetermined data-sharing attributes may not be
19657 // listed in data-sharing attributes clauses, except for the cases
19658 // listed below. For these exceptions only, listing a predetermined
19659 // variable in a data-sharing attribute clause is allowed and overrides
19660 // the variable's predetermined data-sharing attributes.
19661 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19662 // in a Construct, C/C++, p.2]
19663 // Variables with const-qualified type having no mutable member may be
19664 // listed in a firstprivate clause, even if they are static data members.
19665 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
19666 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
19667 Diag(ELoc, diag::err_omp_wrong_dsa)
19668 << getOpenMPClauseNameForDiag(DVar.CKind)
19669 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
19671 continue;
19672 }
19673
19674 // OpenMP [2.9.3.4, Restrictions, p.2]
19675 // A list item that is private within a parallel region must not appear
19676 // in a firstprivate clause on a worksharing construct if any of the
19677 // worksharing regions arising from the worksharing construct ever bind
19678 // to any of the parallel regions arising from the parallel construct.
19679 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
19680 // A list item that is private within a teams region must not appear in a
19681 // firstprivate clause on a distribute construct if any of the distribute
19682 // regions arising from the distribute construct ever bind to any of the
19683 // teams regions arising from the teams construct.
19684 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
19685 // A list item that appears in a reduction clause of a teams construct
19686 // must not appear in a firstprivate clause on a distribute construct if
19687 // any of the distribute regions arising from the distribute construct
19688 // ever bind to any of the teams regions arising from the teams construct.
19689 if ((isOpenMPWorksharingDirective(CurrDir) ||
19690 isOpenMPDistributeDirective(CurrDir)) &&
19691 !isOpenMPParallelDirective(CurrDir) &&
19692 !isOpenMPTeamsDirective(CurrDir)) {
19693 DVar = DSAStack->getImplicitDSA(D, true);
19694 if (DVar.CKind != OMPC_shared &&
19695 (isOpenMPParallelDirective(DVar.DKind) ||
19696 isOpenMPTeamsDirective(DVar.DKind) ||
19697 DVar.DKind == OMPD_unknown)) {
19698 Diag(ELoc, diag::err_omp_required_access)
19699 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
19700 << getOpenMPClauseNameForDiag(OMPC_shared);
19702 continue;
19703 }
19704 }
19705 // OpenMP [2.9.3.4, Restrictions, p.3]
19706 // A list item that appears in a reduction clause of a parallel construct
19707 // must not appear in a firstprivate clause on a worksharing or task
19708 // construct if any of the worksharing or task regions arising from the
19709 // worksharing or task construct ever bind to any of the parallel regions
19710 // arising from the parallel construct.
19711 // OpenMP [2.9.3.4, Restrictions, p.4]
19712 // A list item that appears in a reduction clause in worksharing
19713 // construct must not appear in a firstprivate clause in a task construct
19714 // encountered during execution of any of the worksharing regions arising
19715 // from the worksharing construct.
19716 if (isOpenMPTaskingDirective(CurrDir)) {
19717 DVar = DSAStack->hasInnermostDSA(
19718 D,
19719 [](OpenMPClauseKind C, bool AppliedToPointee) {
19720 return C == OMPC_reduction && !AppliedToPointee;
19721 },
19722 [](OpenMPDirectiveKind K) {
19723 return isOpenMPParallelDirective(K) ||
19726 },
19727 /*FromParent=*/true);
19728 if (DVar.CKind == OMPC_reduction &&
19729 (isOpenMPParallelDirective(DVar.DKind) ||
19730 isOpenMPWorksharingDirective(DVar.DKind) ||
19731 isOpenMPTeamsDirective(DVar.DKind))) {
19732 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
19733 << getOpenMPDirectiveName(DVar.DKind, OMPVersion);
19735 continue;
19736 }
19737 }
19738
19739 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
19740 // A list item cannot appear in both a map clause and a data-sharing
19741 // attribute clause on the same construct
19742 //
19743 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
19744 // A list item cannot appear in both a map clause and a data-sharing
19745 // attribute clause on the same construct unless the construct is a
19746 // combined construct.
19747 if ((getLangOpts().OpenMP <= 45 &&
19749 CurrDir == OMPD_target) {
19750 OpenMPClauseKind ConflictKind;
19751 if (DSAStack->checkMappableExprComponentListsForDecl(
19752 VD, /*CurrentRegionOnly=*/true,
19753 [&ConflictKind](
19755 OpenMPClauseKind WhereFoundClauseKind) {
19756 ConflictKind = WhereFoundClauseKind;
19757 return true;
19758 })) {
19759 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
19760 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
19761 << getOpenMPClauseNameForDiag(ConflictKind)
19762 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
19763 OMPVersion);
19765 continue;
19766 }
19767 }
19768 }
19769
19770 // Variably modified types are not supported for tasks.
19772 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
19773 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19774 << getOpenMPClauseNameForDiag(OMPC_firstprivate) << Type
19775 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
19776 OMPVersion);
19777 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19779 Diag(D->getLocation(),
19780 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19781 << D;
19782 continue;
19783 }
19784
19785 Type = Type.getUnqualifiedType();
19786 VarDecl *VDPrivate =
19787 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
19788 D->hasAttrs() ? &D->getAttrs() : nullptr,
19789 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19790 // Generate helper private variable and initialize it with the value of the
19791 // original variable. The address of the original variable is replaced by
19792 // the address of the new private variable in the CodeGen. This new variable
19793 // is not added to IdResolver, so the code in the OpenMP region uses
19794 // original variable for proper diagnostics and variable capturing.
19795 Expr *VDInitRefExpr = nullptr;
19796 // For arrays generate initializer for single element and replace it by the
19797 // original array element in CodeGen.
19798 if (Type->isArrayType()) {
19799 VarDecl *VDInit =
19800 buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName());
19801 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc);
19802 Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get();
19803 ElemType = ElemType.getUnqualifiedType();
19804 VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(),
19805 ElemType, ".firstprivate.temp");
19806 InitializedEntity Entity =
19809
19810 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
19811 ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init);
19812 if (Result.isInvalid())
19813 VDPrivate->setInvalidDecl();
19814 else
19815 VDPrivate->setInit(Result.getAs<Expr>());
19816 // Remove temp variable declaration.
19817 getASTContext().Deallocate(VDInitTemp);
19818 } else {
19819 VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type,
19820 ".firstprivate.temp");
19821 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(),
19822 RefExpr->getExprLoc());
19823 SemaRef.AddInitializerToDecl(
19824 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
19825 /*DirectInit=*/false);
19826 }
19827 if (VDPrivate->isInvalidDecl()) {
19828 if (IsImplicitClause) {
19829 Diag(RefExpr->getExprLoc(),
19830 diag::note_omp_task_predetermined_firstprivate_here);
19831 }
19832 continue;
19833 }
19834 SemaRef.CurContext->addDecl(VDPrivate);
19835 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
19836 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(),
19837 RefExpr->getExprLoc());
19838 DeclRefExpr *Ref = nullptr;
19839 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19840 if (TopDVar.CKind == OMPC_lastprivate) {
19841 Ref = TopDVar.PrivateCopy;
19842 } else {
19843 auto *FD = dyn_cast<FieldDecl>(D);
19844 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
19845 if (VD)
19846 Ref =
19848 RefExpr->getExprLoc());
19849 else
19850 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19851 if (VD || !isOpenMPCapturedDecl(D))
19852 ExprCaptures.push_back(Ref->getDecl());
19853 }
19854 }
19855 if (!IsImplicitClause)
19856 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
19857 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19858 ? RefExpr->IgnoreParens()
19859 : Ref);
19860 PrivateCopies.push_back(VDPrivateRefExpr);
19861 Inits.push_back(VDInitRefExpr);
19862 }
19863
19864 if (Vars.empty())
19865 return nullptr;
19866
19867 return OMPFirstprivateClause::Create(
19868 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
19869 buildPreInits(getASTContext(), ExprCaptures));
19870}
19871
19874 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
19875 SourceLocation LParenLoc, SourceLocation EndLoc) {
19876 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
19877 assert(ColonLoc.isValid() && "Colon location must be valid.");
19878 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
19879 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
19880 /*Last=*/OMPC_LASTPRIVATE_unknown)
19881 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
19882 return nullptr;
19883 }
19884
19886 SmallVector<Expr *, 8> SrcExprs;
19887 SmallVector<Expr *, 8> DstExprs;
19888 SmallVector<Expr *, 8> AssignmentOps;
19889 SmallVector<Decl *, 4> ExprCaptures;
19890 SmallVector<Expr *, 4> ExprPostUpdates;
19891 for (Expr *RefExpr : VarList) {
19892 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
19893 SourceLocation ELoc;
19894 SourceRange ERange;
19895 Expr *SimpleRefExpr = RefExpr;
19896 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19897 if (Res.second) {
19898 // It will be analyzed later.
19899 Vars.push_back(RefExpr);
19900 SrcExprs.push_back(nullptr);
19901 DstExprs.push_back(nullptr);
19902 AssignmentOps.push_back(nullptr);
19903 }
19904 ValueDecl *D = Res.first;
19905 if (!D)
19906 continue;
19907
19908 QualType Type = D->getType();
19909 auto *VD = dyn_cast<VarDecl>(D);
19910
19911 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
19912 // A variable that appears in a lastprivate clause must not have an
19913 // incomplete type or a reference type.
19914 if (SemaRef.RequireCompleteType(ELoc, Type,
19915 diag::err_omp_lastprivate_incomplete_type))
19916 continue;
19917 Type = Type.getNonReferenceType();
19918
19919 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19920 // A variable that is privatized must not have a const-qualified type
19921 // unless it is of class type with a mutable member. This restriction does
19922 // not apply to the firstprivate clause.
19923 //
19924 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
19925 // A variable that appears in a lastprivate clause must not have a
19926 // const-qualified type unless it is of class type with a mutable member.
19927 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc))
19928 continue;
19929
19930 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
19931 // A list item that appears in a lastprivate clause with the conditional
19932 // modifier must be a scalar variable.
19933 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
19934 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
19935 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19937 Diag(D->getLocation(),
19938 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19939 << D;
19940 continue;
19941 }
19942
19943 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19944 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19945 // in a Construct]
19946 // Variables with the predetermined data-sharing attributes may not be
19947 // listed in data-sharing attributes clauses, except for the cases
19948 // listed below.
19949 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
19950 // A list item may appear in a firstprivate or lastprivate clause but not
19951 // both.
19952 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19953 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
19954 (isOpenMPDistributeDirective(CurrDir) ||
19955 DVar.CKind != OMPC_firstprivate) &&
19956 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
19957 Diag(ELoc, diag::err_omp_wrong_dsa)
19958 << getOpenMPClauseNameForDiag(DVar.CKind)
19959 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
19961 continue;
19962 }
19963
19964 // OpenMP [2.14.3.5, Restrictions, p.2]
19965 // A list item that is private within a parallel region, or that appears in
19966 // the reduction clause of a parallel construct, must not appear in a
19967 // lastprivate clause on a worksharing construct if any of the corresponding
19968 // worksharing regions ever binds to any of the corresponding parallel
19969 // regions.
19970 DSAStackTy::DSAVarData TopDVar = DVar;
19971 if (isOpenMPWorksharingDirective(CurrDir) &&
19972 !isOpenMPParallelDirective(CurrDir) &&
19973 !isOpenMPTeamsDirective(CurrDir)) {
19974 DVar = DSAStack->getImplicitDSA(D, true);
19975 if (DVar.CKind != OMPC_shared) {
19976 Diag(ELoc, diag::err_omp_required_access)
19977 << getOpenMPClauseNameForDiag(OMPC_lastprivate)
19978 << getOpenMPClauseNameForDiag(OMPC_shared);
19980 continue;
19981 }
19982 }
19983
19984 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
19985 // A variable of class type (or array thereof) that appears in a
19986 // lastprivate clause requires an accessible, unambiguous default
19987 // constructor for the class type, unless the list item is also specified
19988 // in a firstprivate clause.
19989 // A variable of class type (or array thereof) that appears in a
19990 // lastprivate clause requires an accessible, unambiguous copy assignment
19991 // operator for the class type.
19993 VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(),
19994 Type.getUnqualifiedType(), ".lastprivate.src",
19995 D->hasAttrs() ? &D->getAttrs() : nullptr);
19996 DeclRefExpr *PseudoSrcExpr =
19997 buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc);
19998 VarDecl *DstVD =
19999 buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst",
20000 D->hasAttrs() ? &D->getAttrs() : nullptr);
20001 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
20002 // For arrays generate assignment operation for single element and replace
20003 // it by the original array element in CodeGen.
20004 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
20005 PseudoDstExpr, PseudoSrcExpr);
20006 if (AssignmentOp.isInvalid())
20007 continue;
20008 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
20009 /*DiscardedValue=*/false);
20010 if (AssignmentOp.isInvalid())
20011 continue;
20012
20013 DeclRefExpr *Ref = nullptr;
20014 if (!VD && !SemaRef.CurContext->isDependentContext()) {
20015 if (TopDVar.CKind == OMPC_firstprivate) {
20016 Ref = TopDVar.PrivateCopy;
20017 } else {
20018 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
20019 if (!isOpenMPCapturedDecl(D))
20020 ExprCaptures.push_back(Ref->getDecl());
20021 }
20022 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
20023 (!isOpenMPCapturedDecl(D) &&
20024 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
20025 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
20026 if (!RefRes.isUsable())
20027 continue;
20028 ExprResult PostUpdateRes =
20029 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
20030 SimpleRefExpr, RefRes.get());
20031 if (!PostUpdateRes.isUsable())
20032 continue;
20033 ExprPostUpdates.push_back(
20034 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
20035 }
20036 }
20037 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
20038 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
20039 ? RefExpr->IgnoreParens()
20040 : Ref);
20041 SrcExprs.push_back(PseudoSrcExpr);
20042 DstExprs.push_back(PseudoDstExpr);
20043 AssignmentOps.push_back(AssignmentOp.get());
20044 }
20045
20046 if (Vars.empty())
20047 return nullptr;
20048
20049 return OMPLastprivateClause::Create(
20050 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
20051 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
20052 buildPreInits(getASTContext(), ExprCaptures),
20053 buildPostUpdate(SemaRef, ExprPostUpdates));
20054}
20055
20057 SourceLocation StartLoc,
20058 SourceLocation LParenLoc,
20059 SourceLocation EndLoc) {
20061 for (Expr *RefExpr : VarList) {
20062 assert(RefExpr && "NULL expr in OpenMP shared clause.");
20063 SourceLocation ELoc;
20064 SourceRange ERange;
20065 Expr *SimpleRefExpr = RefExpr;
20066 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20067 if (Res.second) {
20068 // It will be analyzed later.
20069 Vars.push_back(RefExpr);
20070 }
20071 ValueDecl *D = Res.first;
20072 if (!D)
20073 continue;
20074
20075 auto *VD = dyn_cast<VarDecl>(D);
20076 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
20077 // in a Construct]
20078 // Variables with the predetermined data-sharing attributes may not be
20079 // listed in data-sharing attributes clauses, except for the cases
20080 // listed below. For these exceptions only, listing a predetermined
20081 // variable in a data-sharing attribute clause is allowed and overrides
20082 // the variable's predetermined data-sharing attributes.
20083 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
20084 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
20085 DVar.RefExpr) {
20086 Diag(ELoc, diag::err_omp_wrong_dsa)
20087 << getOpenMPClauseNameForDiag(DVar.CKind)
20088 << getOpenMPClauseNameForDiag(OMPC_shared);
20090 continue;
20091 }
20092
20093 DeclRefExpr *Ref = nullptr;
20094 if (!VD && isOpenMPCapturedDecl(D) &&
20095 !SemaRef.CurContext->isDependentContext())
20096 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
20097 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
20098 Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext())
20099 ? RefExpr->IgnoreParens()
20100 : Ref);
20101 }
20102
20103 if (Vars.empty())
20104 return nullptr;
20105
20106 return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
20107 Vars);
20108}
20109
20110namespace {
20111class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
20112 DSAStackTy *Stack;
20113
20114public:
20115 bool VisitDeclRefExpr(DeclRefExpr *E) {
20116 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
20117 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
20118 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
20119 return false;
20120 if (DVar.CKind != OMPC_unknown)
20121 return true;
20122 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
20123 VD,
20124 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
20125 return isOpenMPPrivate(C) && !AppliedToPointee;
20126 },
20127 [](OpenMPDirectiveKind) { return true; },
20128 /*FromParent=*/true);
20129 return DVarPrivate.CKind != OMPC_unknown;
20130 }
20131 return false;
20132 }
20133 bool VisitStmt(Stmt *S) {
20134 for (Stmt *Child : S->children()) {
20135 if (Child && Visit(Child))
20136 return true;
20137 }
20138 return false;
20139 }
20140 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
20141};
20142} // namespace
20143
20144namespace {
20145// Transform MemberExpression for specified FieldDecl of current class to
20146// DeclRefExpr to specified OMPCapturedExprDecl.
20147class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
20148 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
20149 ValueDecl *Field = nullptr;
20150 DeclRefExpr *CapturedExpr = nullptr;
20151
20152public:
20153 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
20154 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
20155
20156 ExprResult TransformMemberExpr(MemberExpr *E) {
20158 E->getMemberDecl() == Field) {
20159 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
20160 return CapturedExpr;
20161 }
20162 return BaseTransform::TransformMemberExpr(E);
20163 }
20164 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
20165};
20166} // namespace
20167
20168template <typename T, typename U>
20170 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
20171 for (U &Set : Lookups) {
20172 for (auto *D : Set) {
20173 if (T Res = Gen(cast<ValueDecl>(D)))
20174 return Res;
20175 }
20176 }
20177 return T();
20178}
20179
20181 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
20182
20183 for (auto *RD : D->redecls()) {
20184 // Don't bother with extra checks if we already know this one isn't visible.
20185 if (RD == D)
20186 continue;
20187
20188 auto ND = cast<NamedDecl>(RD);
20189 if (LookupResult::isVisible(SemaRef, ND))
20190 return ND;
20191 }
20192
20193 return nullptr;
20194}
20195
20196static void
20198 SourceLocation Loc, QualType Ty,
20200 // Find all of the associated namespaces and classes based on the
20201 // arguments we have.
20202 Sema::AssociatedNamespaceSet AssociatedNamespaces;
20203 Sema::AssociatedClassSet AssociatedClasses;
20204 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
20205 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
20206 AssociatedClasses);
20207
20208 // C++ [basic.lookup.argdep]p3:
20209 // Let X be the lookup set produced by unqualified lookup (3.4.1)
20210 // and let Y be the lookup set produced by argument dependent
20211 // lookup (defined as follows). If X contains [...] then Y is
20212 // empty. Otherwise Y is the set of declarations found in the
20213 // namespaces associated with the argument types as described
20214 // below. The set of declarations found by the lookup of the name
20215 // is the union of X and Y.
20216 //
20217 // Here, we compute Y and add its members to the overloaded
20218 // candidate set.
20219 for (auto *NS : AssociatedNamespaces) {
20220 // When considering an associated namespace, the lookup is the
20221 // same as the lookup performed when the associated namespace is
20222 // used as a qualifier (3.4.3.2) except that:
20223 //
20224 // -- Any using-directives in the associated namespace are
20225 // ignored.
20226 //
20227 // -- Any namespace-scope friend functions declared in
20228 // associated classes are visible within their respective
20229 // namespaces even if they are not visible during an ordinary
20230 // lookup (11.4).
20231 DeclContext::lookup_result R = NS->lookup(Id.getName());
20232 for (auto *D : R) {
20233 auto *Underlying = D;
20234 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
20235 Underlying = USD->getTargetDecl();
20236
20237 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
20238 !isa<OMPDeclareMapperDecl>(Underlying))
20239 continue;
20240
20241 if (!SemaRef.isVisible(D)) {
20242 D = findAcceptableDecl(SemaRef, D);
20243 if (!D)
20244 continue;
20245 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
20246 Underlying = USD->getTargetDecl();
20247 }
20248 Lookups.emplace_back();
20249 Lookups.back().addDecl(Underlying);
20250 }
20251 }
20252}
20253
20254static ExprResult
20256 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
20257 const DeclarationNameInfo &ReductionId, QualType Ty,
20258 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
20259 if (ReductionIdScopeSpec.isInvalid())
20260 return ExprError();
20261 SmallVector<UnresolvedSet<8>, 4> Lookups;
20262 if (S) {
20263 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
20264 Lookup.suppressDiagnostics();
20265 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec,
20266 /*ObjectType=*/QualType())) {
20267 NamedDecl *D = Lookup.getRepresentativeDecl();
20268 do {
20269 S = S->getParent();
20270 } while (S && !S->isDeclScope(D));
20271 if (S)
20272 S = S->getParent();
20273 Lookups.emplace_back();
20274 Lookups.back().append(Lookup.begin(), Lookup.end());
20275 Lookup.clear();
20276 }
20277 } else if (auto *ULE =
20278 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
20279 Lookups.push_back(UnresolvedSet<8>());
20280 Decl *PrevD = nullptr;
20281 for (NamedDecl *D : ULE->decls()) {
20282 if (D == PrevD)
20283 Lookups.push_back(UnresolvedSet<8>());
20284 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
20285 Lookups.back().addDecl(DRD);
20286 PrevD = D;
20287 }
20288 }
20289 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
20293 return !D->isInvalidDecl() &&
20294 (D->getType()->isDependentType() ||
20295 D->getType()->isInstantiationDependentType() ||
20296 D->getType()->containsUnexpandedParameterPack());
20297 })) {
20298 UnresolvedSet<8> ResSet;
20299 for (const UnresolvedSet<8> &Set : Lookups) {
20300 if (Set.empty())
20301 continue;
20302 ResSet.append(Set.begin(), Set.end());
20303 // The last item marks the end of all declarations at the specified scope.
20304 ResSet.addDecl(Set[Set.size() - 1]);
20305 }
20307 SemaRef.Context, /*NamingClass=*/nullptr,
20308 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
20309 /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false,
20310 /*KnownInstantiationDependent=*/false);
20311 }
20312 // Lookup inside the classes.
20313 // C++ [over.match.oper]p3:
20314 // For a unary operator @ with an operand of a type whose
20315 // cv-unqualified version is T1, and for a binary operator @ with
20316 // a left operand of a type whose cv-unqualified version is T1 and
20317 // a right operand of a type whose cv-unqualified version is T2,
20318 // three sets of candidate functions, designated member
20319 // candidates, non-member candidates and built-in candidates, are
20320 // constructed as follows:
20321 // -- If T1 is a complete class type or a class currently being
20322 // defined, the set of member candidates is the result of the
20323 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
20324 // the set of member candidates is empty.
20325 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
20326 Lookup.suppressDiagnostics();
20327 if (Ty->isRecordType()) {
20328 // Complete the type if it can be completed.
20329 // If the type is neither complete nor being defined, bail out now.
20330 bool IsComplete = SemaRef.isCompleteType(Loc, Ty);
20331 auto *RD = Ty->castAsRecordDecl();
20332 if (IsComplete || RD->isBeingDefined()) {
20333 Lookup.clear();
20334 SemaRef.LookupQualifiedName(Lookup, RD);
20335 if (Lookup.empty()) {
20336 Lookups.emplace_back();
20337 Lookups.back().append(Lookup.begin(), Lookup.end());
20338 }
20339 }
20340 }
20341 // Perform ADL.
20342 if (SemaRef.getLangOpts().CPlusPlus)
20343 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
20345 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
20346 if (!D->isInvalidDecl() &&
20347 SemaRef.Context.hasSameType(D->getType(), Ty))
20348 return D;
20349 return nullptr;
20350 }))
20351 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
20352 VK_LValue, Loc);
20353 if (SemaRef.getLangOpts().CPlusPlus) {
20355 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
20356 if (!D->isInvalidDecl() &&
20357 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
20359 SemaRef.getASTContext()))
20360 return D;
20361 return nullptr;
20362 })) {
20363 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
20364 /*DetectVirtual=*/false);
20365 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
20366 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
20367 VD->getType().getUnqualifiedType()))) {
20368 if (SemaRef.CheckBaseClassAccess(
20369 Loc, VD->getType(), Ty, Paths.front(),
20370 /*DiagID=*/0) != Sema::AR_inaccessible) {
20371 SemaRef.BuildBasePathArray(Paths, BasePath);
20372 return SemaRef.BuildDeclRefExpr(
20373 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc);
20374 }
20375 }
20376 }
20377 }
20378 }
20379 if (ReductionIdScopeSpec.isSet()) {
20380 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
20381 << Ty << Range;
20382 return ExprError();
20383 }
20384 return ExprEmpty();
20385}
20386
20387namespace {
20388/// Data for the reduction-based clauses.
20389struct ReductionData {
20390 /// List of original reduction items.
20391 SmallVector<Expr *, 8> Vars;
20392 /// List of private copies of the reduction items.
20393 SmallVector<Expr *, 8> Privates;
20394 /// LHS expressions for the reduction_op expressions.
20395 SmallVector<Expr *, 8> LHSs;
20396 /// RHS expressions for the reduction_op expressions.
20397 SmallVector<Expr *, 8> RHSs;
20398 /// Reduction operation expression.
20399 SmallVector<Expr *, 8> ReductionOps;
20400 /// inscan copy operation expressions.
20401 SmallVector<Expr *, 8> InscanCopyOps;
20402 /// inscan copy temp array expressions for prefix sums.
20403 SmallVector<Expr *, 8> InscanCopyArrayTemps;
20404 /// inscan copy temp array element expressions for prefix sums.
20405 SmallVector<Expr *, 8> InscanCopyArrayElems;
20406 /// Taskgroup descriptors for the corresponding reduction items in
20407 /// in_reduction clauses.
20408 SmallVector<Expr *, 8> TaskgroupDescriptors;
20409 /// List of captures for clause.
20410 SmallVector<Decl *, 4> ExprCaptures;
20411 /// List of postupdate expressions.
20412 SmallVector<Expr *, 4> ExprPostUpdates;
20413 /// Reduction modifier.
20414 unsigned RedModifier = 0;
20415 /// Original modifier.
20416 unsigned OrigSharingModifier = 0;
20417 /// Private Variable Reduction
20418 SmallVector<bool, 8> IsPrivateVarReduction;
20419 ReductionData() = delete;
20420 /// Reserves required memory for the reduction data.
20421 ReductionData(unsigned Size, unsigned Modifier = 0, unsigned OrgModifier = 0)
20422 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
20423 Vars.reserve(Size);
20424 Privates.reserve(Size);
20425 LHSs.reserve(Size);
20426 RHSs.reserve(Size);
20427 ReductionOps.reserve(Size);
20428 IsPrivateVarReduction.reserve(Size);
20429 if (RedModifier == OMPC_REDUCTION_inscan) {
20430 InscanCopyOps.reserve(Size);
20431 InscanCopyArrayTemps.reserve(Size);
20432 InscanCopyArrayElems.reserve(Size);
20433 }
20434 TaskgroupDescriptors.reserve(Size);
20435 ExprCaptures.reserve(Size);
20436 ExprPostUpdates.reserve(Size);
20437 }
20438 /// Stores reduction item and reduction operation only (required for dependent
20439 /// reduction item).
20440 void push(Expr *Item, Expr *ReductionOp) {
20441 Vars.emplace_back(Item);
20442 Privates.emplace_back(nullptr);
20443 LHSs.emplace_back(nullptr);
20444 RHSs.emplace_back(nullptr);
20445 ReductionOps.emplace_back(ReductionOp);
20446 IsPrivateVarReduction.emplace_back(false);
20447 TaskgroupDescriptors.emplace_back(nullptr);
20448 if (RedModifier == OMPC_REDUCTION_inscan) {
20449 InscanCopyOps.push_back(nullptr);
20450 InscanCopyArrayTemps.push_back(nullptr);
20451 InscanCopyArrayElems.push_back(nullptr);
20452 }
20453 }
20454 /// Stores reduction data.
20455 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
20456 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
20457 Expr *CopyArrayElem, bool IsPrivate) {
20458 Vars.emplace_back(Item);
20459 Privates.emplace_back(Private);
20460 LHSs.emplace_back(LHS);
20461 RHSs.emplace_back(RHS);
20462 ReductionOps.emplace_back(ReductionOp);
20463 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
20464 if (RedModifier == OMPC_REDUCTION_inscan) {
20465 InscanCopyOps.push_back(CopyOp);
20466 InscanCopyArrayTemps.push_back(CopyArrayTemp);
20467 InscanCopyArrayElems.push_back(CopyArrayElem);
20468 } else {
20469 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
20470 CopyArrayElem == nullptr &&
20471 "Copy operation must be used for inscan reductions only.");
20472 }
20473 IsPrivateVarReduction.emplace_back(IsPrivate);
20474 }
20475};
20476} // namespace
20477
20479 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
20480 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
20481 const Expr *Length = OASE->getLength();
20482 if (Length == nullptr) {
20483 // For array sections of the form [1:] or [:], we would need to analyze
20484 // the lower bound...
20485 if (OASE->getColonLocFirst().isValid())
20486 return false;
20487
20488 // This is an array subscript which has implicit length 1!
20489 SingleElement = true;
20490 ArraySizes.push_back(llvm::APSInt::get(1));
20491 } else {
20493 if (!Length->EvaluateAsInt(Result, Context))
20494 return false;
20495
20496 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
20497 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
20498 ArraySizes.push_back(ConstantLengthValue);
20499 }
20500
20501 // Get the base of this array section and walk up from there.
20502 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
20503
20504 // We require length = 1 for all array sections except the right-most to
20505 // guarantee that the memory region is contiguous and has no holes in it.
20506 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) {
20507 Length = TempOASE->getLength();
20508 if (Length == nullptr) {
20509 // For array sections of the form [1:] or [:], we would need to analyze
20510 // the lower bound...
20511 if (OASE->getColonLocFirst().isValid())
20512 return false;
20513
20514 // This is an array subscript which has implicit length 1!
20515 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
20516 ArraySizes.push_back(ConstantOne);
20517 } else {
20519 if (!Length->EvaluateAsInt(Result, Context))
20520 return false;
20521
20522 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
20523 if (ConstantLengthValue.getSExtValue() != 1)
20524 return false;
20525
20526 ArraySizes.push_back(ConstantLengthValue);
20527 }
20528 Base = TempOASE->getBase()->IgnoreParenImpCasts();
20529 }
20530
20531 // If we have a single element, we don't need to add the implicit lengths.
20532 if (!SingleElement) {
20533 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
20534 // Has implicit length 1!
20535 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
20536 ArraySizes.push_back(ConstantOne);
20537 Base = TempASE->getBase()->IgnoreParenImpCasts();
20538 }
20539 }
20540
20541 // This array section can be privatized as a single value or as a constant
20542 // sized array.
20543 return true;
20544}
20545
20546static BinaryOperatorKind
20548 if (BOK == BO_Add)
20549 return BO_AddAssign;
20550 if (BOK == BO_Mul)
20551 return BO_MulAssign;
20552 if (BOK == BO_And)
20553 return BO_AndAssign;
20554 if (BOK == BO_Or)
20555 return BO_OrAssign;
20556 if (BOK == BO_Xor)
20557 return BO_XorAssign;
20558 return BOK;
20559}
20560
20562 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
20563 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20564 SourceLocation ColonLoc, SourceLocation EndLoc,
20565 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20566 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
20567 DeclarationName DN = ReductionId.getName();
20569 BinaryOperatorKind BOK = BO_Comma;
20570
20571 ASTContext &Context = S.Context;
20572 // OpenMP [2.14.3.6, reduction clause]
20573 // C
20574 // reduction-identifier is either an identifier or one of the following
20575 // operators: +, -, *, &, |, ^, && and ||
20576 // C++
20577 // reduction-identifier is either an id-expression or one of the following
20578 // operators: +, -, *, &, |, ^, && and ||
20579 switch (OOK) {
20580 case OO_Plus:
20581 BOK = BO_Add;
20582 break;
20583 case OO_Minus:
20584 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
20585 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
20586 // reduction identifier.
20587 if (S.LangOpts.OpenMP > 52)
20588 BOK = BO_Comma;
20589 else
20590 BOK = BO_Add;
20591 break;
20592 case OO_Star:
20593 BOK = BO_Mul;
20594 break;
20595 case OO_Amp:
20596 BOK = BO_And;
20597 break;
20598 case OO_Pipe:
20599 BOK = BO_Or;
20600 break;
20601 case OO_Caret:
20602 BOK = BO_Xor;
20603 break;
20604 case OO_AmpAmp:
20605 BOK = BO_LAnd;
20606 break;
20607 case OO_PipePipe:
20608 BOK = BO_LOr;
20609 break;
20610 case OO_New:
20611 case OO_Delete:
20612 case OO_Array_New:
20613 case OO_Array_Delete:
20614 case OO_Slash:
20615 case OO_Percent:
20616 case OO_Tilde:
20617 case OO_Exclaim:
20618 case OO_Equal:
20619 case OO_Less:
20620 case OO_Greater:
20621 case OO_LessEqual:
20622 case OO_GreaterEqual:
20623 case OO_PlusEqual:
20624 case OO_MinusEqual:
20625 case OO_StarEqual:
20626 case OO_SlashEqual:
20627 case OO_PercentEqual:
20628 case OO_CaretEqual:
20629 case OO_AmpEqual:
20630 case OO_PipeEqual:
20631 case OO_LessLess:
20632 case OO_GreaterGreater:
20633 case OO_LessLessEqual:
20634 case OO_GreaterGreaterEqual:
20635 case OO_EqualEqual:
20636 case OO_ExclaimEqual:
20637 case OO_Spaceship:
20638 case OO_PlusPlus:
20639 case OO_MinusMinus:
20640 case OO_Comma:
20641 case OO_ArrowStar:
20642 case OO_Arrow:
20643 case OO_Call:
20644 case OO_Subscript:
20645 case OO_Conditional:
20646 case OO_Coawait:
20648 llvm_unreachable("Unexpected reduction identifier");
20649 case OO_None:
20650 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
20651 if (II->isStr("max"))
20652 BOK = BO_GT;
20653 else if (II->isStr("min"))
20654 BOK = BO_LT;
20655 }
20656 break;
20657 }
20658
20659 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
20660 // A reduction clause with the minus (-) operator was deprecated
20661 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
20662 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
20663
20664 SourceRange ReductionIdRange;
20665 if (ReductionIdScopeSpec.isValid())
20666 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
20667 else
20668 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
20669 ReductionIdRange.setEnd(ReductionId.getEndLoc());
20670
20671 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
20672 bool FirstIter = true;
20673 for (Expr *RefExpr : VarList) {
20674 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
20675 // OpenMP [2.1, C/C++]
20676 // A list item is a variable or array section, subject to the restrictions
20677 // specified in Section 2.4 on page 42 and in each of the sections
20678 // describing clauses and directives for which a list appears.
20679 // OpenMP [2.14.3.3, Restrictions, p.1]
20680 // A variable that is part of another variable (as an array or
20681 // structure element) cannot appear in a private clause.
20682 if (!FirstIter && IR != ER)
20683 ++IR;
20684 FirstIter = false;
20685 SourceLocation ELoc;
20686 SourceRange ERange;
20687 bool IsPrivate = false;
20688 Expr *SimpleRefExpr = RefExpr;
20689 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
20690 /*AllowArraySection=*/true);
20691 if (Res.second) {
20692 // Try to find 'declare reduction' corresponding construct before using
20693 // builtin/overloaded operators.
20694 QualType Type = Context.DependentTy;
20695 CXXCastPath BasePath;
20696 ExprResult DeclareReductionRef = buildDeclareReductionRef(
20697 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20698 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
20699 Expr *ReductionOp = nullptr;
20700 if (S.CurContext->isDependentContext() &&
20701 (DeclareReductionRef.isUnset() ||
20702 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
20703 ReductionOp = DeclareReductionRef.get();
20704 // It will be analyzed later.
20705 RD.push(RefExpr, ReductionOp);
20706 }
20707 ValueDecl *D = Res.first;
20708 if (!D)
20709 continue;
20710
20711 Expr *TaskgroupDescriptor = nullptr;
20712 QualType Type;
20713 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
20714 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
20715 if (ASE) {
20716 Type = ASE->getType().getNonReferenceType();
20717 } else if (OASE) {
20718 QualType BaseType =
20720 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20721 Type = ATy->getElementType();
20722 else
20723 Type = BaseType->getPointeeType();
20724 Type = Type.getNonReferenceType();
20725 } else {
20726 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
20727 }
20728 auto *VD = dyn_cast<VarDecl>(D);
20729
20730 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
20731 // A variable that appears in a private clause must not have an incomplete
20732 // type or a reference type.
20733 if (S.RequireCompleteType(ELoc, D->getType(),
20734 diag::err_omp_reduction_incomplete_type))
20735 continue;
20736 // OpenMP [2.14.3.6, reduction clause, Restrictions]
20737 // A list item that appears in a reduction clause must not be
20738 // const-qualified.
20739 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
20740 /*AcceptIfMutable=*/false, ASE || OASE))
20741 continue;
20742
20743 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
20744 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
20745 // If a list-item is a reference type then it must bind to the same object
20746 // for all threads of the team.
20747 if (!ASE && !OASE) {
20748 if (VD) {
20749 VarDecl *VDDef = VD->getDefinition();
20750 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
20751 DSARefChecker Check(Stack);
20752 if (Check.Visit(VDDef->getInit())) {
20753 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
20754 << getOpenMPClauseNameForDiag(ClauseKind) << ERange;
20755 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
20756 continue;
20757 }
20758 }
20759 }
20760
20761 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
20762 // in a Construct]
20763 // Variables with the predetermined data-sharing attributes may not be
20764 // listed in data-sharing attributes clauses, except for the cases
20765 // listed below. For these exceptions only, listing a predetermined
20766 // variable in a data-sharing attribute clause is allowed and overrides
20767 // the variable's predetermined data-sharing attributes.
20768 // OpenMP [2.14.3.6, Restrictions, p.3]
20769 // Any number of reduction clauses can be specified on the directive,
20770 // but a list item can appear only once in the reduction clauses for that
20771 // directive.
20772 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
20773 if (DVar.CKind == OMPC_reduction) {
20774 S.Diag(ELoc, diag::err_omp_once_referenced)
20775 << getOpenMPClauseNameForDiag(ClauseKind);
20776 if (DVar.RefExpr)
20777 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
20778 continue;
20779 }
20780 if (DVar.CKind != OMPC_unknown) {
20781 S.Diag(ELoc, diag::err_omp_wrong_dsa)
20782 << getOpenMPClauseNameForDiag(DVar.CKind)
20783 << getOpenMPClauseNameForDiag(OMPC_reduction);
20784 reportOriginalDsa(S, Stack, D, DVar);
20785 continue;
20786 }
20787
20788 // OpenMP [2.14.3.6, Restrictions, p.1]
20789 // A list item that appears in a reduction clause of a worksharing
20790 // construct must be shared in the parallel regions to which any of the
20791 // worksharing regions arising from the worksharing construct bind.
20792
20793 if (S.getLangOpts().OpenMP <= 52 &&
20795 !isOpenMPParallelDirective(CurrDir) &&
20796 !isOpenMPTeamsDirective(CurrDir)) {
20797 DVar = Stack->getImplicitDSA(D, true);
20798 if (DVar.CKind != OMPC_shared) {
20799 S.Diag(ELoc, diag::err_omp_required_access)
20800 << getOpenMPClauseNameForDiag(OMPC_reduction)
20801 << getOpenMPClauseNameForDiag(OMPC_shared);
20802 reportOriginalDsa(S, Stack, D, DVar);
20803 continue;
20804 }
20805 } else if (isOpenMPWorksharingDirective(CurrDir) &&
20806 !isOpenMPParallelDirective(CurrDir) &&
20807 !isOpenMPTeamsDirective(CurrDir)) {
20808 // OpenMP 6.0 [ 7.6.10 ]
20809 // Support Reduction over private variables with reduction clause.
20810 // A list item in a reduction clause can now be private in the enclosing
20811 // context. For orphaned constructs it is assumed to be shared unless
20812 // the original(private) modifier appears in the clause.
20813 DVar = Stack->getImplicitDSA(D, true);
20814 // Determine if the variable should be considered private
20815 IsPrivate = DVar.CKind != OMPC_shared;
20816 bool IsOrphaned = false;
20817 OpenMPDirectiveKind ParentDir = Stack->getParentDirective();
20818 IsOrphaned = ParentDir == OMPD_unknown;
20819 if ((IsOrphaned &&
20820 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
20821 IsPrivate = true;
20822 }
20823 } else {
20824 // Threadprivates cannot be shared between threads, so dignose if the base
20825 // is a threadprivate variable.
20826 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
20827 if (DVar.CKind == OMPC_threadprivate) {
20828 S.Diag(ELoc, diag::err_omp_wrong_dsa)
20829 << getOpenMPClauseNameForDiag(DVar.CKind)
20830 << getOpenMPClauseNameForDiag(OMPC_reduction);
20831 reportOriginalDsa(S, Stack, D, DVar);
20832 continue;
20833 }
20834 }
20835
20836 // Try to find 'declare reduction' corresponding construct before using
20837 // builtin/overloaded operators.
20838 CXXCastPath BasePath;
20839 ExprResult DeclareReductionRef = buildDeclareReductionRef(
20840 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20841 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
20842 if (DeclareReductionRef.isInvalid())
20843 continue;
20844 if (S.CurContext->isDependentContext() &&
20845 (DeclareReductionRef.isUnset() ||
20846 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
20847 RD.push(RefExpr, DeclareReductionRef.get());
20848 // Handle non-dependent inscan reduction variables in dependent contexts.
20849 if (RD.RedModifier == OMPC_REDUCTION_inscan)
20850 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, nullptr,
20851 RD.RedModifier, ASE || OASE);
20852 continue;
20853 }
20854 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
20855 // Not allowed reduction identifier is found.
20856 if (S.LangOpts.OpenMP > 52)
20857 S.Diag(ReductionId.getBeginLoc(),
20858 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
20859 << Type << ReductionIdRange;
20860 else
20861 S.Diag(ReductionId.getBeginLoc(),
20862 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
20863 << Type << ReductionIdRange;
20864 continue;
20865 }
20866
20867 // OpenMP [2.14.3.6, reduction clause, Restrictions]
20868 // The type of a list item that appears in a reduction clause must be valid
20869 // for the reduction-identifier. For a max or min reduction in C, the type
20870 // of the list item must be an allowed arithmetic data type: char, int,
20871 // float, double, or _Bool, possibly modified with long, short, signed, or
20872 // unsigned. For a max or min reduction in C++, the type of the list item
20873 // must be an allowed arithmetic data type: char, wchar_t, int, float,
20874 // double, or bool, possibly modified with long, short, signed, or unsigned.
20875 if (DeclareReductionRef.isUnset()) {
20876 if ((BOK == BO_GT || BOK == BO_LT) &&
20877 !(Type->isScalarType() ||
20878 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
20879 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
20880 << getOpenMPClauseNameForDiag(ClauseKind)
20881 << S.getLangOpts().CPlusPlus;
20882 if (!ASE && !OASE) {
20883 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20885 S.Diag(D->getLocation(),
20886 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20887 << D;
20888 }
20889 continue;
20890 }
20891 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
20892 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
20893 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
20894 << getOpenMPClauseNameForDiag(ClauseKind);
20895 if (!ASE && !OASE) {
20896 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20898 S.Diag(D->getLocation(),
20899 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20900 << D;
20901 }
20902 continue;
20903 }
20904 }
20905
20906 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
20907 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
20908 D->hasAttrs() ? &D->getAttrs() : nullptr);
20909 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
20910 D->hasAttrs() ? &D->getAttrs() : nullptr);
20911 QualType PrivateTy = Type;
20912
20913 // Try if we can determine constant lengths for all array sections and avoid
20914 // the VLA.
20915 bool ConstantLengthOASE = false;
20916 if (OASE) {
20917 bool SingleElement;
20919 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
20920 Context, OASE, SingleElement, ArraySizes);
20921
20922 // If we don't have a single element, we must emit a constant array type.
20923 if (ConstantLengthOASE && !SingleElement) {
20924 for (llvm::APSInt &Size : ArraySizes)
20925 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
20927 /*IndexTypeQuals=*/0);
20928 }
20929 }
20930
20931 if ((OASE && !ConstantLengthOASE) ||
20932 (!OASE && !ASE &&
20934 if (!Context.getTargetInfo().isVLASupported()) {
20935 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
20936 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20937 S.Diag(ELoc, diag::note_vla_unsupported);
20938 continue;
20939 } else {
20940 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20941 S.targetDiag(ELoc, diag::note_vla_unsupported);
20942 }
20943 }
20944 // For arrays/array sections only:
20945 // Create pseudo array type for private copy. The size for this array will
20946 // be generated during codegen.
20947 // For array subscripts or single variables Private Ty is the same as Type
20948 // (type of the variable or single array element).
20949 PrivateTy = Context.getVariableArrayType(
20950 Type,
20951 new (Context)
20952 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
20953 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0);
20954 } else if (!ASE && !OASE &&
20955 Context.getAsArrayType(D->getType().getNonReferenceType())) {
20956 PrivateTy = D->getType().getNonReferenceType();
20957 }
20958 // Private copy.
20959 VarDecl *PrivateVD =
20960 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
20961 D->hasAttrs() ? &D->getAttrs() : nullptr,
20962 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
20963 // Add initializer for private variable.
20964 Expr *Init = nullptr;
20965 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
20966 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
20967 if (DeclareReductionRef.isUsable()) {
20968 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
20969 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
20970 if (DRD->getInitializer()) {
20971 Init = DRDRef;
20972 RHSVD->setInit(DRDRef);
20974 }
20975 } else {
20976 switch (BOK) {
20977 case BO_Add:
20978 case BO_Xor:
20979 case BO_Or:
20980 case BO_LOr:
20981 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
20983 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
20984 break;
20985 case BO_Mul:
20986 // '*' reduction op - initializer is '1'.
20987 // For C++ class types (e.g. std::complex) the OpenMP built-in
20988 // reduction identifiers are an extension: the standard only defines
20989 // identities for arithmetic (and, in Clang, _Complex) types. Without
20990 // an explicit initializer the private copy would be value-initialized,
20991 // which yields the *additive* identity (e.g. std::complex(0,0)) and is
20992 // wrong for multiplication. Initialize from the integer literal '1'
20993 // instead and let the converting constructor build the multiplicative
20994 // identity (e.g. std::complex(1) == (1,0)).
20995 if (Type->isScalarType() || Type->isAnyComplexType()) {
20996 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
20997 } else if (S.getLangOpts().CPlusPlus && Type->isRecordType()) {
20998 // Only use '1' when the type is actually copy-initializable from it.
20999 // Otherwise fall back to value-initialization (the previous behavior)
21000 // rather than rejecting the reduction, so a class that used to
21001 // compile keeps compiling. Such a class keeps its (possibly
21002 // incorrect) value-initialized identity, matching the pre-existing
21003 // behavior; BO_Add likewise relies on value-initialization for class
21004 // types.
21005 Expr *One = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
21006 InitializedEntity Entity =
21009 InitializationSequence Seq(S, Entity, Kind, One);
21010 if (Seq)
21011 Init = One;
21012 }
21013 break;
21014 case BO_LAnd:
21015 if (Type->isScalarType() || Type->isAnyComplexType()) {
21016 // '&&' reduction ops - initializer is '1'.
21017 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
21018 }
21019 break;
21020 case BO_And: {
21021 // '&' reduction op - initializer is '~0'.
21022 QualType OrigType = Type;
21023 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
21024 Type = ComplexTy->getElementType();
21025 if (Type->isRealFloatingType()) {
21026 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
21027 Context.getFloatTypeSemantics(Type));
21028 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
21029 Type, ELoc);
21030 } else if (Type->isScalarType()) {
21031 uint64_t Size = Context.getTypeSize(Type);
21032 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
21033 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
21034 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
21035 }
21036 if (Init && OrigType->isAnyComplexType()) {
21037 // Init = 0xFFFF + 0xFFFFi;
21038 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
21039 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
21040 }
21041 Type = OrigType;
21042 break;
21043 }
21044 case BO_LT:
21045 case BO_GT: {
21046 // 'min' reduction op - initializer is 'Largest representable number in
21047 // the reduction list item type'.
21048 // 'max' reduction op - initializer is 'Least representable number in
21049 // the reduction list item type'.
21050 if (Type->isIntegerType() || Type->isPointerType()) {
21051 bool IsSigned = Type->hasSignedIntegerRepresentation();
21052 uint64_t Size = Context.getTypeSize(Type);
21053 QualType IntTy =
21054 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
21055 llvm::APInt InitValue =
21056 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
21057 : llvm::APInt::getMinValue(Size)
21058 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
21059 : llvm::APInt::getMaxValue(Size);
21060 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
21061 if (Type->isPointerType()) {
21062 // Cast to pointer type.
21064 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
21065 if (CastExpr.isInvalid())
21066 continue;
21067 Init = CastExpr.get();
21068 }
21069 } else if (Type->isRealFloatingType()) {
21070 llvm::APFloat InitValue = llvm::APFloat::getLargest(
21071 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
21072 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
21073 Type, ELoc);
21074 }
21075 break;
21076 }
21077 case BO_PtrMemD:
21078 case BO_PtrMemI:
21079 case BO_MulAssign:
21080 case BO_Div:
21081 case BO_Rem:
21082 case BO_Sub:
21083 case BO_Shl:
21084 case BO_Shr:
21085 case BO_LE:
21086 case BO_GE:
21087 case BO_EQ:
21088 case BO_NE:
21089 case BO_Cmp:
21090 case BO_AndAssign:
21091 case BO_XorAssign:
21092 case BO_OrAssign:
21093 case BO_Assign:
21094 case BO_AddAssign:
21095 case BO_SubAssign:
21096 case BO_DivAssign:
21097 case BO_RemAssign:
21098 case BO_ShlAssign:
21099 case BO_ShrAssign:
21100 case BO_Comma:
21101 llvm_unreachable("Unexpected reduction operation");
21102 }
21103 }
21104 if (Init && DeclareReductionRef.isUnset()) {
21105 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
21106 // Store initializer for single element in private copy. Will be used
21107 // during codegen.
21108 PrivateVD->setInit(RHSVD->getInit());
21109 PrivateVD->setInitStyle(RHSVD->getInitStyle());
21110 } else if (!Init) {
21111 S.ActOnUninitializedDecl(RHSVD);
21112 // Store initializer for single element in private copy. Will be used
21113 // during codegen.
21114 PrivateVD->setInit(RHSVD->getInit());
21115 PrivateVD->setInitStyle(RHSVD->getInitStyle());
21116 }
21117 if (RHSVD->isInvalidDecl())
21118 continue;
21119 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
21120 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
21121 << Type << ReductionIdRange;
21122 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
21124 S.Diag(D->getLocation(),
21125 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21126 << D;
21127 continue;
21128 }
21129 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
21130 ExprResult ReductionOp;
21131 if (DeclareReductionRef.isUsable()) {
21132 QualType RedTy = DeclareReductionRef.get()->getType();
21133 QualType PtrRedTy = Context.getPointerType(RedTy);
21134 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
21135 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
21136 if (!BasePath.empty()) {
21137 LHS = S.DefaultLvalueConversion(LHS.get());
21138 RHS = S.DefaultLvalueConversion(RHS.get());
21140 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
21141 LHS.get()->getValueKind(), FPOptionsOverride());
21143 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
21144 RHS.get()->getValueKind(), FPOptionsOverride());
21145 }
21147 QualType Params[] = {PtrRedTy, PtrRedTy};
21148 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
21149 auto *OVE = new (Context) OpaqueValueExpr(
21150 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
21151 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
21152 Expr *Args[] = {LHS.get(), RHS.get()};
21153 ReductionOp =
21154 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
21156 } else {
21158 if (Type->isRecordType() && CombBOK != BOK) {
21160 ReductionOp =
21161 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
21162 CombBOK, LHSDRE, RHSDRE);
21163 }
21164 if (!ReductionOp.isUsable()) {
21165 ReductionOp =
21166 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
21167 LHSDRE, RHSDRE);
21168 if (ReductionOp.isUsable()) {
21169 if (BOK != BO_LT && BOK != BO_GT) {
21170 ReductionOp =
21171 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
21172 BO_Assign, LHSDRE, ReductionOp.get());
21173 } else {
21174 auto *ConditionalOp = new (Context)
21175 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
21176 RHSDRE, Type, VK_LValue, OK_Ordinary);
21177 ReductionOp =
21178 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
21179 BO_Assign, LHSDRE, ConditionalOp);
21180 }
21181 }
21182 }
21183 if (ReductionOp.isUsable())
21184 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
21185 /*DiscardedValue=*/false);
21186 if (!ReductionOp.isUsable())
21187 continue;
21188 }
21189
21190 // Add copy operations for inscan reductions.
21191 // LHS = RHS;
21192 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
21193 if (ClauseKind == OMPC_reduction &&
21194 RD.RedModifier == OMPC_REDUCTION_inscan) {
21195 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
21196 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
21197 RHS.get());
21198 if (!CopyOpRes.isUsable())
21199 continue;
21200 CopyOpRes =
21201 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
21202 if (!CopyOpRes.isUsable())
21203 continue;
21204 // For simd directive and simd-based directives in simd mode no need to
21205 // construct temp array, need just a single temp element.
21206 if (Stack->getCurrentDirective() == OMPD_simd ||
21207 (S.getLangOpts().OpenMPSimd &&
21208 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
21209 VarDecl *TempArrayVD =
21210 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
21211 D->hasAttrs() ? &D->getAttrs() : nullptr);
21212 // Add a constructor to the temp decl.
21213 S.ActOnUninitializedDecl(TempArrayVD);
21214 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
21215 } else {
21216 // Build temp array for prefix sum.
21217 auto *Dim = new (S.Context)
21220 PrivateTy, Dim, ArraySizeModifier::Normal,
21221 /*IndexTypeQuals=*/0);
21222 VarDecl *TempArrayVD =
21223 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
21224 D->hasAttrs() ? &D->getAttrs() : nullptr);
21225 // Add a constructor to the temp decl.
21226 S.ActOnUninitializedDecl(TempArrayVD);
21227 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
21228 TempArrayElem =
21229 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
21230 auto *Idx = new (S.Context)
21232 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
21233 ELoc, Idx, ELoc);
21234 }
21235 }
21236
21237 // OpenMP [2.15.4.6, Restrictions, p.2]
21238 // A list item that appears in an in_reduction clause of a task construct
21239 // must appear in a task_reduction clause of a construct associated with a
21240 // taskgroup region that includes the participating task in its taskgroup
21241 // set. The construct associated with the innermost region that meets this
21242 // condition must specify the same reduction-identifier as the in_reduction
21243 // clause.
21244 if (ClauseKind == OMPC_in_reduction) {
21245 SourceRange ParentSR;
21246 BinaryOperatorKind ParentBOK;
21247 const Expr *ParentReductionOp = nullptr;
21248 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
21249 DSAStackTy::DSAVarData ParentBOKDSA =
21250 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
21251 ParentBOKTD);
21252 DSAStackTy::DSAVarData ParentReductionOpDSA =
21253 Stack->getTopMostTaskgroupReductionData(
21254 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
21255 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
21256 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
21257 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
21258 (DeclareReductionRef.isUsable() && IsParentBOK) ||
21259 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
21260 bool EmitError = true;
21261 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
21262 llvm::FoldingSetNodeID RedId, ParentRedId;
21263 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
21264 DeclareReductionRef.get()->Profile(RedId, Context,
21265 /*Canonical=*/true);
21266 EmitError = RedId != ParentRedId;
21267 }
21268 if (EmitError) {
21269 S.Diag(ReductionId.getBeginLoc(),
21270 diag::err_omp_reduction_identifier_mismatch)
21271 << ReductionIdRange << RefExpr->getSourceRange();
21272 S.Diag(ParentSR.getBegin(),
21273 diag::note_omp_previous_reduction_identifier)
21274 << ParentSR
21275 << (IsParentBOK ? ParentBOKDSA.RefExpr
21276 : ParentReductionOpDSA.RefExpr)
21277 ->getSourceRange();
21278 continue;
21279 }
21280 }
21281 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
21282 }
21283
21284 DeclRefExpr *Ref = nullptr;
21285 Expr *VarsExpr = RefExpr->IgnoreParens();
21286 if (!VD && !S.CurContext->isDependentContext()) {
21287 if (ASE || OASE) {
21288 TransformExprToCaptures RebuildToCapture(S, D);
21289 VarsExpr =
21290 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
21291 Ref = RebuildToCapture.getCapturedExpr();
21292 } else {
21293 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
21294 }
21295 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
21296 RD.ExprCaptures.emplace_back(Ref->getDecl());
21297 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
21298 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
21299 if (!RefRes.isUsable())
21300 continue;
21301 ExprResult PostUpdateRes =
21302 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
21303 RefRes.get());
21304 if (!PostUpdateRes.isUsable())
21305 continue;
21306 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
21307 Stack->getCurrentDirective() == OMPD_taskgroup) {
21308 S.Diag(RefExpr->getExprLoc(),
21309 diag::err_omp_reduction_non_addressable_expression)
21310 << RefExpr->getSourceRange();
21311 continue;
21312 }
21313 RD.ExprPostUpdates.emplace_back(
21314 S.IgnoredValueConversions(PostUpdateRes.get()).get());
21315 }
21316 }
21317 }
21318 // All reduction items are still marked as reduction (to do not increase
21319 // code base size).
21320 unsigned Modifier = RD.RedModifier;
21321 // Consider task_reductions as reductions with task modifier. Required for
21322 // correct analysis of in_reduction clauses.
21323 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
21324 Modifier = OMPC_REDUCTION_task;
21325 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
21326 ASE || OASE);
21327 if (Modifier == OMPC_REDUCTION_task &&
21328 (CurrDir == OMPD_taskgroup ||
21329 ((isOpenMPParallelDirective(CurrDir) ||
21330 isOpenMPWorksharingDirective(CurrDir)) &&
21331 !isOpenMPSimdDirective(CurrDir)))) {
21332 if (DeclareReductionRef.isUsable())
21333 Stack->addTaskgroupReductionData(D, ReductionIdRange,
21334 DeclareReductionRef.get());
21335 else
21336 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
21337 }
21338 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
21339 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
21340 TempArrayElem.get(), IsPrivate);
21341 }
21342 return RD.Vars.empty();
21343}
21344
21346 ArrayRef<Expr *> VarList,
21348 SourceLocation StartLoc, SourceLocation LParenLoc,
21349 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
21350 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
21351 ArrayRef<Expr *> UnresolvedReductions) {
21353 static_cast<OpenMPReductionClauseModifier>(Modifiers.ExtraModifier);
21354 OpenMPOriginalSharingModifier OriginalSharingModifier =
21355 static_cast<OpenMPOriginalSharingModifier>(
21356 Modifiers.OriginalSharingModifier);
21357 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
21358 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
21359 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
21360 /*Last=*/OMPC_REDUCTION_unknown)
21361 << getOpenMPClauseNameForDiag(OMPC_reduction);
21362 return nullptr;
21363 }
21364 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
21365 // A reduction clause with the inscan reduction-modifier may only appear on a
21366 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
21367 // construct, a parallel worksharing-loop construct or a parallel
21368 // worksharing-loop SIMD construct.
21369 if (Modifier == OMPC_REDUCTION_inscan &&
21370 (DSAStack->getCurrentDirective() != OMPD_for &&
21371 DSAStack->getCurrentDirective() != OMPD_for_simd &&
21372 DSAStack->getCurrentDirective() != OMPD_simd &&
21373 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
21374 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
21375 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
21376 return nullptr;
21377 }
21378 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
21379 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
21380 StartLoc, LParenLoc, ColonLoc, EndLoc,
21381 ReductionIdScopeSpec, ReductionId,
21382 UnresolvedReductions, RD))
21383 return nullptr;
21384
21385 return OMPReductionClause::Create(
21386 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
21387 Modifier, RD.Vars,
21388 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
21389 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
21390 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
21391 buildPreInits(getASTContext(), RD.ExprCaptures),
21392 buildPostUpdate(SemaRef, RD.ExprPostUpdates), RD.IsPrivateVarReduction,
21393 OriginalSharingModifier);
21394}
21395
21397 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
21398 SourceLocation ColonLoc, SourceLocation EndLoc,
21399 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
21400 ArrayRef<Expr *> UnresolvedReductions) {
21401 ReductionData RD(VarList.size());
21402 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction,
21403 VarList, StartLoc, LParenLoc, ColonLoc,
21404 EndLoc, ReductionIdScopeSpec, ReductionId,
21405 UnresolvedReductions, RD))
21406 return nullptr;
21407
21408 return OMPTaskReductionClause::Create(
21409 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
21410 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
21411 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
21412 buildPreInits(getASTContext(), RD.ExprCaptures),
21413 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
21414}
21415
21417 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
21418 SourceLocation ColonLoc, SourceLocation EndLoc,
21419 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
21420 ArrayRef<Expr *> UnresolvedReductions) {
21421 ReductionData RD(VarList.size());
21422 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList,
21423 StartLoc, LParenLoc, ColonLoc, EndLoc,
21424 ReductionIdScopeSpec, ReductionId,
21425 UnresolvedReductions, RD))
21426 return nullptr;
21427
21428 return OMPInReductionClause::Create(
21429 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
21430 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
21431 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
21432 buildPreInits(getASTContext(), RD.ExprCaptures),
21433 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
21434}
21435
21437 SourceLocation LinLoc) {
21438 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
21439 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
21440 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
21441 << getLangOpts().CPlusPlus;
21442 return true;
21443 }
21444 return false;
21445}
21446
21448 OpenMPLinearClauseKind LinKind,
21449 QualType Type, bool IsDeclareSimd) {
21450 const auto *VD = dyn_cast_or_null<VarDecl>(D);
21451 // A variable must not have an incomplete type or a reference type.
21452 if (SemaRef.RequireCompleteType(ELoc, Type,
21453 diag::err_omp_linear_incomplete_type))
21454 return true;
21455 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
21456 !Type->isReferenceType()) {
21457 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
21458 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
21459 return true;
21460 }
21461 Type = Type.getNonReferenceType();
21462
21463 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
21464 // A variable that is privatized must not have a const-qualified type
21465 // unless it is of class type with a mutable member. This restriction does
21466 // not apply to the firstprivate clause, nor to the linear clause on
21467 // declarative directives (like declare simd).
21468 if (!IsDeclareSimd &&
21469 rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc))
21470 return true;
21471
21472 // A list item must be of integral or pointer type.
21473 Type = Type.getUnqualifiedType().getCanonicalType();
21474 const auto *Ty = Type.getTypePtrOrNull();
21475 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
21476 !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) {
21477 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
21478 if (D) {
21479 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21481 Diag(D->getLocation(),
21482 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21483 << D;
21484 }
21485 return true;
21486 }
21487 return false;
21488}
21489
21491 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
21492 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
21493 SourceLocation LinLoc, SourceLocation ColonLoc,
21494 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
21498 SmallVector<Decl *, 4> ExprCaptures;
21499 SmallVector<Expr *, 4> ExprPostUpdates;
21500 // OpenMP 5.2 [Section 5.4.6, linear clause]
21501 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
21502 // 'ref'
21503 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
21504 getLangOpts().OpenMP >= 52)
21505 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
21506 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
21507 LinKind = OMPC_LINEAR_val;
21508 for (Expr *RefExpr : VarList) {
21509 assert(RefExpr && "NULL expr in OpenMP linear clause.");
21510 SourceLocation ELoc;
21511 SourceRange ERange;
21512 Expr *SimpleRefExpr = RefExpr;
21513 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21514 if (Res.second) {
21515 // It will be analyzed later.
21516 Vars.push_back(RefExpr);
21517 Privates.push_back(nullptr);
21518 Inits.push_back(nullptr);
21519 }
21520 ValueDecl *D = Res.first;
21521 if (!D)
21522 continue;
21523
21524 QualType Type = D->getType();
21525 auto *VD = dyn_cast<VarDecl>(D);
21526
21527 // OpenMP [2.14.3.7, linear clause]
21528 // A list-item cannot appear in more than one linear clause.
21529 // A list-item that appears in a linear clause cannot appear in any
21530 // other data-sharing attribute clause.
21531 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
21532 if (DVar.RefExpr) {
21533 Diag(ELoc, diag::err_omp_wrong_dsa)
21534 << getOpenMPClauseNameForDiag(DVar.CKind)
21535 << getOpenMPClauseNameForDiag(OMPC_linear);
21537 continue;
21538 }
21539
21540 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
21541 continue;
21542 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
21543
21544 // Build private copy of original var.
21545 VarDecl *Private =
21546 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
21547 D->hasAttrs() ? &D->getAttrs() : nullptr,
21548 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
21549 DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc);
21550 // Build var to save initial value.
21551 VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start");
21552 Expr *InitExpr;
21553 DeclRefExpr *Ref = nullptr;
21554 if (!VD && !SemaRef.CurContext->isDependentContext()) {
21555 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
21556 if (!isOpenMPCapturedDecl(D)) {
21557 ExprCaptures.push_back(Ref->getDecl());
21558 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
21559 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
21560 if (!RefRes.isUsable())
21561 continue;
21562 ExprResult PostUpdateRes =
21563 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
21564 SimpleRefExpr, RefRes.get());
21565 if (!PostUpdateRes.isUsable())
21566 continue;
21567 ExprPostUpdates.push_back(
21568 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
21569 }
21570 }
21571 }
21572 if (LinKind == OMPC_LINEAR_uval)
21573 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
21574 else
21575 InitExpr = VD ? SimpleRefExpr : Ref;
21576 SemaRef.AddInitializerToDecl(
21577 Init, SemaRef.DefaultLvalueConversion(InitExpr).get(),
21578 /*DirectInit=*/false);
21579 DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc);
21580
21581 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
21582 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
21583 ? RefExpr->IgnoreParens()
21584 : Ref);
21585 Privates.push_back(PrivateRef);
21586 Inits.push_back(InitRef);
21587 }
21588
21589 if (Vars.empty())
21590 return nullptr;
21591
21592 Expr *StepExpr = Step;
21593 Expr *CalcStepExpr = nullptr;
21594 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
21595 !Step->isInstantiationDependent() &&
21597 SourceLocation StepLoc = Step->getBeginLoc();
21599 if (Val.isInvalid())
21600 return nullptr;
21601 StepExpr = Val.get();
21602
21603 // Build var to save the step value.
21604 VarDecl *SaveVar =
21605 buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step");
21606 ExprResult SaveRef =
21607 buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc);
21608 ExprResult CalcStep = SemaRef.BuildBinOp(
21609 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr);
21610 CalcStep =
21611 SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue=*/false);
21612
21613 // Warn about zero linear step (it would be probably better specified as
21614 // making corresponding variables 'const').
21615 if (std::optional<llvm::APSInt> Result =
21617 if (!Result->isNegative() && !Result->isStrictlyPositive())
21618 Diag(StepLoc, diag::warn_omp_linear_step_zero)
21619 << Vars[0] << (Vars.size() > 1);
21620 } else if (CalcStep.isUsable()) {
21621 // Calculate the step beforehand instead of doing this on each iteration.
21622 // (This is not used if the number of iterations may be kfold-ed).
21623 CalcStepExpr = CalcStep.get();
21624 }
21625 }
21626
21627 return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind,
21628 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
21629 Vars, Privates, Inits, StepExpr, CalcStepExpr,
21630 buildPreInits(getASTContext(), ExprCaptures),
21631 buildPostUpdate(SemaRef, ExprPostUpdates));
21632}
21633
21634static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
21635 Expr *NumIterations, Sema &SemaRef,
21636 Scope *S, DSAStackTy *Stack) {
21637 // Walk the vars and build update/final expressions for the CodeGen.
21640 SmallVector<Expr *, 8> UsedExprs;
21641 Expr *Step = Clause.getStep();
21642 Expr *CalcStep = Clause.getCalcStep();
21643 // OpenMP [2.14.3.7, linear clause]
21644 // If linear-step is not specified it is assumed to be 1.
21645 if (!Step)
21646 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
21647 else if (CalcStep)
21648 Step = cast<BinaryOperator>(CalcStep)->getLHS();
21649 bool HasErrors = false;
21650 auto CurInit = Clause.inits().begin();
21651 auto CurPrivate = Clause.privates().begin();
21652 OpenMPLinearClauseKind LinKind = Clause.getModifier();
21653 for (Expr *RefExpr : Clause.varlist()) {
21654 SourceLocation ELoc;
21655 SourceRange ERange;
21656 Expr *SimpleRefExpr = RefExpr;
21657 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21658 ValueDecl *D = Res.first;
21659 if (Res.second || !D) {
21660 Updates.push_back(nullptr);
21661 Finals.push_back(nullptr);
21662 HasErrors = true;
21663 continue;
21664 }
21665 auto &&Info = Stack->isLoopControlVariable(D);
21666 // OpenMP [2.15.11, distribute simd Construct]
21667 // A list item may not appear in a linear clause, unless it is the loop
21668 // iteration variable.
21669 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
21670 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
21671 SemaRef.Diag(ELoc,
21672 diag::err_omp_linear_distribute_var_non_loop_iteration);
21673 Updates.push_back(nullptr);
21674 Finals.push_back(nullptr);
21675 HasErrors = true;
21676 continue;
21677 }
21678 Expr *InitExpr = *CurInit;
21679
21680 // Build privatized reference to the current linear var.
21681 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
21682 Expr *CapturedRef;
21683 if (LinKind == OMPC_LINEAR_uval)
21684 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
21685 else
21686 CapturedRef =
21687 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
21688 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
21689 /*RefersToCapture=*/true);
21690
21691 // Build update: Var = InitExpr + IV * Step
21693 if (!Info.first)
21695 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
21696 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
21697 else
21698 Update = *CurPrivate;
21699 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
21700 /*DiscardedValue=*/false);
21701
21702 // Build final: Var = PrivCopy;
21703 ExprResult Final;
21704 if (!Info.first)
21705 Final = SemaRef.BuildBinOp(
21706 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
21707 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
21708 else
21709 Final = *CurPrivate;
21710 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
21711 /*DiscardedValue=*/false);
21712
21713 if (!Update.isUsable() || !Final.isUsable()) {
21714 Updates.push_back(nullptr);
21715 Finals.push_back(nullptr);
21716 UsedExprs.push_back(nullptr);
21717 HasErrors = true;
21718 } else {
21719 Updates.push_back(Update.get());
21720 Finals.push_back(Final.get());
21721 if (!Info.first)
21722 UsedExprs.push_back(SimpleRefExpr);
21723 }
21724 ++CurInit;
21725 ++CurPrivate;
21726 }
21727 if (Expr *S = Clause.getStep())
21728 UsedExprs.push_back(S);
21729 // Fill the remaining part with the nullptr.
21730 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
21731 Clause.setUpdates(Updates);
21732 Clause.setFinals(Finals);
21733 Clause.setUsedExprs(UsedExprs);
21734 return HasErrors;
21735}
21736
21738 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
21739 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
21741 for (Expr *RefExpr : VarList) {
21742 assert(RefExpr && "NULL expr in OpenMP aligned clause.");
21743 SourceLocation ELoc;
21744 SourceRange ERange;
21745 Expr *SimpleRefExpr = RefExpr;
21746 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21747 if (Res.second) {
21748 // It will be analyzed later.
21749 Vars.push_back(RefExpr);
21750 }
21751 ValueDecl *D = Res.first;
21752 if (!D)
21753 continue;
21754
21755 QualType QType = D->getType();
21756 auto *VD = dyn_cast<VarDecl>(D);
21757
21758 // OpenMP [2.8.1, simd construct, Restrictions]
21759 // The type of list items appearing in the aligned clause must be
21760 // array, pointer, reference to array, or reference to pointer.
21762 const Type *Ty = QType.getTypePtrOrNull();
21763 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
21764 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
21765 << QType << getLangOpts().CPlusPlus << ERange;
21766 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21768 Diag(D->getLocation(),
21769 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21770 << D;
21771 continue;
21772 }
21773
21774 // OpenMP [2.8.1, simd construct, Restrictions]
21775 // A list-item cannot appear in more than one aligned clause.
21776 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
21777 Diag(ELoc, diag::err_omp_used_in_clause_twice)
21778 << 0 << getOpenMPClauseNameForDiag(OMPC_aligned) << ERange;
21779 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
21780 << getOpenMPClauseNameForDiag(OMPC_aligned);
21781 continue;
21782 }
21783
21784 DeclRefExpr *Ref = nullptr;
21785 if (!VD && isOpenMPCapturedDecl(D))
21786 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
21787 Vars.push_back(SemaRef
21788 .DefaultFunctionArrayConversion(
21789 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
21790 .get());
21791 }
21792
21793 // OpenMP [2.8.1, simd construct, Description]
21794 // The parameter of the aligned clause, alignment, must be a constant
21795 // positive integer expression.
21796 // If no optional parameter is specified, implementation-defined default
21797 // alignments for SIMD instructions on the target platforms are assumed.
21798 if (Alignment != nullptr) {
21799 ExprResult AlignResult =
21800 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
21801 if (AlignResult.isInvalid())
21802 return nullptr;
21803 Alignment = AlignResult.get();
21804 }
21805 if (Vars.empty())
21806 return nullptr;
21807
21808 return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc,
21809 ColonLoc, EndLoc, Vars, Alignment);
21810}
21811
21813 SourceLocation StartLoc,
21814 SourceLocation LParenLoc,
21815 SourceLocation EndLoc) {
21817 SmallVector<Expr *, 8> SrcExprs;
21818 SmallVector<Expr *, 8> DstExprs;
21819 SmallVector<Expr *, 8> AssignmentOps;
21820 for (Expr *RefExpr : VarList) {
21821 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
21822 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21823 // It will be analyzed later.
21824 Vars.push_back(RefExpr);
21825 SrcExprs.push_back(nullptr);
21826 DstExprs.push_back(nullptr);
21827 AssignmentOps.push_back(nullptr);
21828 continue;
21829 }
21830
21831 SourceLocation ELoc = RefExpr->getExprLoc();
21832 // OpenMP [2.1, C/C++]
21833 // A list item is a variable name.
21834 // OpenMP [2.14.4.1, Restrictions, p.1]
21835 // A list item that appears in a copyin clause must be threadprivate.
21836 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
21837 if (!DE || !isa<VarDecl>(DE->getDecl())) {
21838 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
21839 << 0 << RefExpr->getSourceRange();
21840 continue;
21841 }
21842
21843 Decl *D = DE->getDecl();
21844 auto *VD = cast<VarDecl>(D);
21845
21846 QualType Type = VD->getType();
21848 // It will be analyzed later.
21849 Vars.push_back(DE);
21850 SrcExprs.push_back(nullptr);
21851 DstExprs.push_back(nullptr);
21852 AssignmentOps.push_back(nullptr);
21853 continue;
21854 }
21855
21856 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
21857 // A list item that appears in a copyin clause must be threadprivate.
21858 if (!DSAStack->isThreadPrivate(VD)) {
21859 unsigned OMPVersion = getLangOpts().OpenMP;
21860 Diag(ELoc, diag::err_omp_required_access)
21861 << getOpenMPClauseNameForDiag(OMPC_copyin)
21862 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion);
21863 continue;
21864 }
21865
21866 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
21867 // A variable of class type (or array thereof) that appears in a
21868 // copyin clause requires an accessible, unambiguous copy assignment
21869 // operator for the class type.
21870 QualType ElemType =
21872 VarDecl *SrcVD =
21873 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
21874 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
21875 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
21876 SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
21877 VarDecl *DstVD =
21878 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst",
21879 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
21880 DeclRefExpr *PseudoDstExpr =
21881 buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc());
21882 // For arrays generate assignment operation for single element and replace
21883 // it by the original array element in CodeGen.
21884 ExprResult AssignmentOp =
21885 SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
21886 PseudoDstExpr, PseudoSrcExpr);
21887 if (AssignmentOp.isInvalid())
21888 continue;
21889 AssignmentOp =
21890 SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
21891 /*DiscardedValue=*/false);
21892 if (AssignmentOp.isInvalid())
21893 continue;
21894
21895 DSAStack->addDSA(VD, DE, OMPC_copyin);
21896 Vars.push_back(DE);
21897 SrcExprs.push_back(PseudoSrcExpr);
21898 DstExprs.push_back(PseudoDstExpr);
21899 AssignmentOps.push_back(AssignmentOp.get());
21900 }
21901
21902 if (Vars.empty())
21903 return nullptr;
21904
21905 return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21906 Vars, SrcExprs, DstExprs, AssignmentOps);
21907}
21908
21910 SourceLocation StartLoc,
21911 SourceLocation LParenLoc,
21912 SourceLocation EndLoc) {
21914 SmallVector<Expr *, 8> SrcExprs;
21915 SmallVector<Expr *, 8> DstExprs;
21916 SmallVector<Expr *, 8> AssignmentOps;
21917 for (Expr *RefExpr : VarList) {
21918 assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");
21919 SourceLocation ELoc;
21920 SourceRange ERange;
21921 Expr *SimpleRefExpr = RefExpr;
21922 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21923 if (Res.second) {
21924 // It will be analyzed later.
21925 Vars.push_back(RefExpr);
21926 SrcExprs.push_back(nullptr);
21927 DstExprs.push_back(nullptr);
21928 AssignmentOps.push_back(nullptr);
21929 }
21930 ValueDecl *D = Res.first;
21931 if (!D)
21932 continue;
21933
21934 QualType Type = D->getType();
21935 auto *VD = dyn_cast<VarDecl>(D);
21936
21937 // OpenMP [2.14.4.2, Restrictions, p.2]
21938 // A list item that appears in a copyprivate clause may not appear in a
21939 // private or firstprivate clause on the single construct.
21940 if (!VD || !DSAStack->isThreadPrivate(VD)) {
21941 DSAStackTy::DSAVarData DVar =
21942 DSAStack->getTopDSA(D, /*FromParent=*/false);
21943 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
21944 DVar.RefExpr) {
21945 Diag(ELoc, diag::err_omp_wrong_dsa)
21946 << getOpenMPClauseNameForDiag(DVar.CKind)
21947 << getOpenMPClauseNameForDiag(OMPC_copyprivate);
21949 continue;
21950 }
21951
21952 // OpenMP [2.11.4.2, Restrictions, p.1]
21953 // All list items that appear in a copyprivate clause must be either
21954 // threadprivate or private in the enclosing context.
21955 if (DVar.CKind == OMPC_unknown) {
21956 DVar = DSAStack->getImplicitDSA(D, false);
21957 if (DVar.CKind == OMPC_shared) {
21958 Diag(ELoc, diag::err_omp_required_access)
21959 << getOpenMPClauseNameForDiag(OMPC_copyprivate)
21960 << "threadprivate or private in the enclosing context";
21962 continue;
21963 }
21964 }
21965 }
21966
21967 // Variably modified types are not supported.
21969 unsigned OMPVersion = getLangOpts().OpenMP;
21970 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
21971 << getOpenMPClauseNameForDiag(OMPC_copyprivate) << Type
21972 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
21973 OMPVersion);
21974 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21976 Diag(D->getLocation(),
21977 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21978 << D;
21979 continue;
21980 }
21981
21982 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
21983 // A variable of class type (or array thereof) that appears in a
21984 // copyin clause requires an accessible, unambiguous copy assignment
21985 // operator for the class type.
21987 .getBaseElementType(Type.getNonReferenceType())
21989 VarDecl *SrcVD =
21990 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
21991 D->hasAttrs() ? &D->getAttrs() : nullptr);
21992 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc);
21993 VarDecl *DstVD =
21994 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
21995 D->hasAttrs() ? &D->getAttrs() : nullptr);
21996 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
21997 ExprResult AssignmentOp = SemaRef.BuildBinOp(
21998 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
21999 if (AssignmentOp.isInvalid())
22000 continue;
22001 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
22002 /*DiscardedValue=*/false);
22003 if (AssignmentOp.isInvalid())
22004 continue;
22005
22006 // No need to mark vars as copyprivate, they are already threadprivate or
22007 // implicitly private.
22008 assert(VD || isOpenMPCapturedDecl(D));
22009 Vars.push_back(
22010 VD ? RefExpr->IgnoreParens()
22011 : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false));
22012 SrcExprs.push_back(PseudoSrcExpr);
22013 DstExprs.push_back(PseudoDstExpr);
22014 AssignmentOps.push_back(AssignmentOp.get());
22015 }
22016
22017 if (Vars.empty())
22018 return nullptr;
22019
22020 return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc,
22021 EndLoc, Vars, SrcExprs, DstExprs,
22022 AssignmentOps);
22023}
22024
22026 SourceLocation StartLoc,
22027 SourceLocation LParenLoc,
22028 SourceLocation EndLoc) {
22029 if (VarList.empty())
22030 return nullptr;
22031
22032 return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
22033 VarList);
22034}
22035
22036/// Tries to find omp_depend_t. type.
22037static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
22038 bool Diagnose = true) {
22039 QualType OMPDependT = Stack->getOMPDependT();
22040 if (!OMPDependT.isNull())
22041 return true;
22042 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
22043 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
22044 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
22045 if (Diagnose)
22046 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
22047 return false;
22048 }
22049 Stack->setOMPDependT(PT.get());
22050 return true;
22051}
22052
22054 SourceLocation StartLoc,
22055 SourceLocation LParenLoc,
22056 SourceLocation EndLoc) {
22057 if (!Depobj)
22058 return nullptr;
22059
22060 bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack);
22061
22062 // OpenMP 5.0, 2.17.10.1 depobj Construct
22063 // depobj is an lvalue expression of type omp_depend_t.
22064 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
22065 !Depobj->isInstantiationDependent() &&
22067 (OMPDependTFound && !getASTContext().typesAreCompatible(
22068 DSAStack->getOMPDependT(), Depobj->getType(),
22069 /*CompareUnqualified=*/true))) {
22070 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
22071 << 0 << Depobj->getType() << Depobj->getSourceRange();
22072 }
22073
22074 if (!Depobj->isLValue()) {
22075 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
22076 << 1 << Depobj->getSourceRange();
22077 }
22078
22079 return OMPDepobjClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
22080 Depobj);
22081}
22082
22083namespace {
22084// Utility struct that gathers the related info for doacross clause.
22085struct DoacrossDataInfoTy {
22086 // The list of expressions.
22088 // The OperatorOffset for doacross loop.
22089 DSAStackTy::OperatorOffsetTy OpsOffs;
22090 // The depended loop count.
22091 llvm::APSInt TotalDepCount;
22092};
22093} // namespace
22094static DoacrossDataInfoTy
22096 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
22097 SourceLocation EndLoc) {
22098
22100 DSAStackTy::OperatorOffsetTy OpsOffs;
22101 llvm::APSInt DepCounter(/*BitWidth=*/32);
22102 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
22103
22104 if (const Expr *OrderedCountExpr =
22105 Stack->getParentOrderedRegionParam().first) {
22106 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
22107 TotalDepCount.setIsUnsigned(/*Val=*/true);
22108 }
22109
22110 for (Expr *RefExpr : VarList) {
22111 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
22112 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
22113 // It will be analyzed later.
22114 Vars.push_back(RefExpr);
22115 continue;
22116 }
22117
22118 SourceLocation ELoc = RefExpr->getExprLoc();
22119 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
22120 if (!IsSource) {
22121 if (Stack->getParentOrderedRegionParam().first &&
22122 DepCounter >= TotalDepCount) {
22123 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
22124 continue;
22125 }
22126 ++DepCounter;
22127 // OpenMP [2.13.9, Summary]
22128 // depend(dependence-type : vec), where dependence-type is:
22129 // 'sink' and where vec is the iteration vector, which has the form:
22130 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
22131 // where n is the value specified by the ordered clause in the loop
22132 // directive, xi denotes the loop iteration variable of the i-th nested
22133 // loop associated with the loop directive, and di is a constant
22134 // non-negative integer.
22135 if (SemaRef.CurContext->isDependentContext()) {
22136 // It will be analyzed later.
22137 Vars.push_back(RefExpr);
22138 continue;
22139 }
22140 SimpleExpr = SimpleExpr->IgnoreImplicit();
22142 SourceLocation OOLoc;
22143 Expr *LHS = SimpleExpr;
22144 Expr *RHS = nullptr;
22145 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
22146 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
22147 OOLoc = BO->getOperatorLoc();
22148 LHS = BO->getLHS()->IgnoreParenImpCasts();
22149 RHS = BO->getRHS()->IgnoreParenImpCasts();
22150 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
22151 OOK = OCE->getOperator();
22152 OOLoc = OCE->getOperatorLoc();
22153 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
22154 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
22155 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
22156 OOK = MCE->getMethodDecl()
22157 ->getNameInfo()
22158 .getName()
22159 .getCXXOverloadedOperator();
22160 OOLoc = MCE->getCallee()->getExprLoc();
22161 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
22162 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
22163 }
22164 SourceLocation ELoc;
22165 SourceRange ERange;
22166 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
22167 if (Res.second) {
22168 // It will be analyzed later.
22169 Vars.push_back(RefExpr);
22170 }
22171 ValueDecl *D = Res.first;
22172 if (!D)
22173 continue;
22174
22175 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
22176 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
22177 continue;
22178 }
22179 if (RHS) {
22180 ExprResult RHSRes =
22182 RHS, OMPC_depend, /*StrictlyPositive=*/false);
22183 if (RHSRes.isInvalid())
22184 continue;
22185 }
22186 if (!SemaRef.CurContext->isDependentContext() &&
22187 Stack->getParentOrderedRegionParam().first &&
22188 DepCounter != Stack->isParentLoopControlVariable(D).first) {
22189 const ValueDecl *VD =
22190 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
22191 if (VD)
22192 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
22193 << 1 << VD;
22194 else
22195 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
22196 << 0;
22197 continue;
22198 }
22199 OpsOffs.emplace_back(RHS, OOK);
22200 }
22201 Vars.push_back(RefExpr->IgnoreParenImpCasts());
22202 }
22203 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
22204 TotalDepCount > VarList.size() &&
22205 Stack->getParentOrderedRegionParam().first &&
22206 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
22207 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
22208 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
22209 }
22210 return {Vars, OpsOffs, TotalDepCount};
22211}
22212
22214 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
22215 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
22216 SourceLocation EndLoc) {
22217 OpenMPDependClauseKind DepKind = Data.DepKind;
22218 SourceLocation DepLoc = Data.DepLoc;
22219 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
22220 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
22221 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
22222 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_depend);
22223 return nullptr;
22224 }
22225 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
22226 DepKind == OMPC_DEPEND_mutexinoutset) {
22227 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
22228 return nullptr;
22229 }
22230 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
22231 DSAStack->getCurrentDirective() == OMPD_depobj) &&
22232 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
22233 DepKind == OMPC_DEPEND_sink ||
22234 ((getLangOpts().OpenMP < 50 ||
22235 DSAStack->getCurrentDirective() == OMPD_depobj) &&
22236 DepKind == OMPC_DEPEND_depobj))) {
22237 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
22238 OMPC_DEPEND_outallmemory,
22239 OMPC_DEPEND_inoutallmemory};
22240 if (getLangOpts().OpenMP < 50 ||
22241 DSAStack->getCurrentDirective() == OMPD_depobj)
22242 Except.push_back(OMPC_DEPEND_depobj);
22243 if (getLangOpts().OpenMP < 51)
22244 Except.push_back(OMPC_DEPEND_inoutset);
22245 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
22246 ? "depend modifier(iterator) or "
22247 : "";
22248 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
22249 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
22250 /*Last=*/OMPC_DEPEND_unknown,
22251 Except)
22252 << getOpenMPClauseNameForDiag(OMPC_depend);
22253 return nullptr;
22254 }
22255 if (DepModifier &&
22256 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
22257 Diag(DepModifier->getExprLoc(),
22258 diag::err_omp_depend_sink_source_with_modifier);
22259 return nullptr;
22260 }
22261 if (DepModifier &&
22262 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
22263 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
22264
22266 DSAStackTy::OperatorOffsetTy OpsOffs;
22267 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
22268
22269 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
22270 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
22271 SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
22272 Vars = VarOffset.Vars;
22273 OpsOffs = VarOffset.OpsOffs;
22274 TotalDepCount = VarOffset.TotalDepCount;
22275 } else {
22276 for (Expr *RefExpr : VarList) {
22277 assert(RefExpr && "NULL expr in OpenMP depend clause.");
22278 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
22279 // It will be analyzed later.
22280 Vars.push_back(RefExpr);
22281 continue;
22282 }
22283
22284 SourceLocation ELoc = RefExpr->getExprLoc();
22285 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
22286 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
22287 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
22288 if (OMPDependTFound)
22289 OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack,
22290 DepKind == OMPC_DEPEND_depobj);
22291 if (DepKind == OMPC_DEPEND_depobj) {
22292 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
22293 // List items used in depend clauses with the depobj dependence type
22294 // must be expressions of the omp_depend_t type.
22295 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
22296 !RefExpr->isInstantiationDependent() &&
22297 !RefExpr->containsUnexpandedParameterPack() &&
22298 (OMPDependTFound &&
22299 !getASTContext().hasSameUnqualifiedType(
22300 DSAStack->getOMPDependT(), RefExpr->getType()))) {
22301 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
22302 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
22303 continue;
22304 }
22305 if (!RefExpr->isLValue()) {
22306 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
22307 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
22308 continue;
22309 }
22310 } else {
22311 // OpenMP 5.0 [2.17.11, Restrictions]
22312 // List items used in depend clauses cannot be zero-length array
22313 // sections.
22314 QualType ExprTy = RefExpr->getType().getNonReferenceType();
22315 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
22316 if (OASE) {
22317 QualType BaseType =
22319 if (BaseType.isNull())
22320 return nullptr;
22321 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
22322 ExprTy = ATy->getElementType();
22323 else
22324 ExprTy = BaseType->getPointeeType();
22325 if (BaseType.isNull() || ExprTy.isNull())
22326 return nullptr;
22327 ExprTy = ExprTy.getNonReferenceType();
22328 const Expr *Length = OASE->getLength();
22330 if (Length && !Length->isValueDependent() &&
22331 Length->EvaluateAsInt(Result, getASTContext()) &&
22332 Result.Val.getInt().isZero()) {
22333 Diag(ELoc,
22334 diag::err_omp_depend_zero_length_array_section_not_allowed)
22335 << SimpleExpr->getSourceRange();
22336 continue;
22337 }
22338 }
22339
22340 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
22341 // List items used in depend clauses with the in, out, inout,
22342 // inoutset, or mutexinoutset dependence types cannot be
22343 // expressions of the omp_depend_t type.
22344 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
22345 !RefExpr->isInstantiationDependent() &&
22346 !RefExpr->containsUnexpandedParameterPack() &&
22347 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
22348 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
22349 ExprTy.getTypePtr()))) {
22350 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
22351 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22352 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22353 << RefExpr->getSourceRange();
22354 continue;
22355 }
22356
22357 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
22358 if (ASE && !ASE->getBase()->isTypeDependent() &&
22359 !ASE->getBase()
22360 ->getType()
22361 .getNonReferenceType()
22362 ->isPointerType() &&
22363 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
22364 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
22365 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22366 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22367 << RefExpr->getSourceRange();
22368 continue;
22369 }
22370
22371 ExprResult Res;
22372 {
22374 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
22375 RefExpr->IgnoreParenImpCasts());
22376 }
22377 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
22379 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
22380 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22381 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
22382 << RefExpr->getSourceRange();
22383 continue;
22384 }
22385 }
22386 }
22387 Vars.push_back(RefExpr->IgnoreParenImpCasts());
22388 }
22389 }
22390
22391 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
22392 DepKind != OMPC_DEPEND_outallmemory &&
22393 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
22394 return nullptr;
22395
22396 auto *C = OMPDependClause::Create(
22397 getASTContext(), StartLoc, LParenLoc, EndLoc,
22398 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
22399 TotalDepCount.getZExtValue());
22400 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
22401 DSAStack->isParentOrderedRegion())
22402 DSAStack->addDoacrossDependClause(C, OpsOffs);
22403 return C;
22404}
22405
22408 SourceLocation LParenLoc, SourceLocation ModifierLoc,
22409 SourceLocation EndLoc) {
22410 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
22411 "Unexpected device modifier in OpenMP < 50.");
22412
22413 bool ErrorFound = false;
22414 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
22415 std::string Values =
22416 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
22417 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22418 << Values << getOpenMPClauseNameForDiag(OMPC_device);
22419 ErrorFound = true;
22420 }
22421
22422 Expr *ValExpr = Device;
22423 Stmt *HelperValStmt = nullptr;
22424
22425 // OpenMP 5.2 [1.3, Execution Model]: a conforming device number is either
22426 // a non-negative integer that is less than or equal to omp_get_num_devices()
22427 // or equal to omp_initial_device or omp_invalid_device. The predefined
22428 // identifiers were introduced in OpenMP 5.2; earlier versions require a
22429 // non-negative integer.
22430 if (getLangOpts().OpenMP >= 52) {
22431 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
22432 !ValExpr->isInstantiationDependent()) {
22433 SourceLocation Loc = ValExpr->getExprLoc();
22435 if (Value.isInvalid()) {
22436 ErrorFound = true;
22437 } else {
22438 ValExpr = Value.get();
22439 if (std::optional<llvm::APSInt> Result =
22441 if (Result->isSigned() && Result->slt(-2)) {
22442 Diag(Loc, diag::err_omp_device_expression_invalid)
22443 << ValExpr->getSourceRange();
22444 ErrorFound = true;
22445 }
22446 }
22447 }
22448 }
22449 } else {
22450 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device,
22451 /*StrictlyPositive=*/false) ||
22452 ErrorFound;
22453 }
22454 if (ErrorFound)
22455 return nullptr;
22456
22457 // OpenMP 5.0 [2.12.5, Restrictions]
22458 // In case of ancestor device-modifier, a requires directive with
22459 // the reverse_offload clause must be specified.
22460 if (Modifier == OMPC_DEVICE_ancestor) {
22461 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
22462 SemaRef.targetDiag(
22463 StartLoc,
22464 diag::err_omp_device_ancestor_without_requires_reverse_offload);
22465 ErrorFound = true;
22466 }
22467 }
22468
22469 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22470 OpenMPDirectiveKind CaptureRegion =
22471 getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP);
22472 if (CaptureRegion != OMPD_unknown &&
22473 !SemaRef.CurContext->isDependentContext()) {
22474 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22475 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22476 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22477 HelperValStmt = buildPreInits(getASTContext(), Captures);
22478 }
22479
22480 return new (getASTContext())
22481 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
22482 LParenLoc, ModifierLoc, EndLoc);
22483}
22484
22486 DSAStackTy *Stack, QualType QTy,
22487 bool FullCheck = true) {
22488 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
22489 return false;
22490 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
22491 !QTy.isTriviallyCopyableType(SemaRef.Context))
22492 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
22493 return true;
22494}
22495
22496/// Return true if it can be proven that the provided array expression
22497/// (array section or array subscript) does NOT specify the whole size of the
22498/// array whose base type is \a BaseQTy.
22500 const Expr *E,
22501 QualType BaseQTy) {
22502 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
22503
22504 // If this is an array subscript, it refers to the whole size if the size of
22505 // the dimension is constant and equals 1. Also, an array section assumes the
22506 // format of an array subscript if no colon is used.
22507 if (isa<ArraySubscriptExpr>(E) ||
22508 (OASE && OASE->getColonLocFirst().isInvalid())) {
22509 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
22510 return ATy->getSExtSize() != 1;
22511 // Size can't be evaluated statically.
22512 return false;
22513 }
22514
22515 assert(OASE && "Expecting array section if not an array subscript.");
22516 const Expr *LowerBound = OASE->getLowerBound();
22517 const Expr *Length = OASE->getLength();
22518
22519 // If there is a lower bound that does not evaluates to zero, we are not
22520 // covering the whole dimension.
22521 if (LowerBound) {
22523 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
22524 return false; // Can't get the integer value as a constant.
22525
22526 llvm::APSInt ConstLowerBound = Result.Val.getInt();
22527 if (ConstLowerBound.getSExtValue())
22528 return true;
22529 }
22530
22531 // If we don't have a length we covering the whole dimension.
22532 if (!Length)
22533 return false;
22534
22535 // If the base is a pointer, we don't have a way to get the size of the
22536 // pointee.
22537 if (BaseQTy->isPointerType())
22538 return false;
22539
22540 // We can only check if the length is the same as the size of the dimension
22541 // if we have a constant array.
22542 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
22543 if (!CATy)
22544 return false;
22545
22547 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
22548 return false; // Can't get the integer value as a constant.
22549
22550 llvm::APSInt ConstLength = Result.Val.getInt();
22551 return CATy->getSExtSize() != ConstLength.getSExtValue();
22552}
22553
22554// Return true if it can be proven that the provided array expression (array
22555// section or array subscript) does NOT specify a single element of the array
22556// whose base type is \a BaseQTy.
22558 const Expr *E,
22559 QualType BaseQTy) {
22560 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
22561
22562 // An array subscript always refer to a single element. Also, an array section
22563 // assumes the format of an array subscript if no colon is used.
22564 if (isa<ArraySubscriptExpr>(E) ||
22565 (OASE && OASE->getColonLocFirst().isInvalid()))
22566 return false;
22567
22568 assert(OASE && "Expecting array section if not an array subscript.");
22569 const Expr *Length = OASE->getLength();
22570
22571 // If we don't have a length we have to check if the array has unitary size
22572 // for this dimension. Also, we should always expect a length if the base type
22573 // is pointer.
22574 if (!Length) {
22575 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
22576 return ATy->getSExtSize() != 1;
22577 // We cannot assume anything.
22578 return false;
22579 }
22580
22581 // Check if the length evaluates to 1.
22583 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
22584 return false; // Can't get the integer value as a constant.
22585
22586 llvm::APSInt ConstLength = Result.Val.getInt();
22587 return ConstLength.getSExtValue() != 1;
22588}
22589
22590// The base of elements of list in a map clause have to be either:
22591// - a reference to variable or field.
22592// - a member expression.
22593// - an array expression.
22594//
22595// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
22596// reference to 'r'.
22597//
22598// If we have:
22599//
22600// struct SS {
22601// Bla S;
22602// foo() {
22603// #pragma omp target map (S.Arr[:12]);
22604// }
22605// }
22606//
22607// We want to retrieve the member expression 'this->S';
22608
22609// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
22610// If a list item is an array section, it must specify contiguous storage.
22611//
22612// For this restriction it is sufficient that we make sure only references
22613// to variables or fields and array expressions, and that no array sections
22614// exist except in the rightmost expression (unless they cover the whole
22615// dimension of the array). E.g. these would be invalid:
22616//
22617// r.ArrS[3:5].Arr[6:7]
22618//
22619// r.ArrS[3:5].x
22620//
22621// but these would be valid:
22622// r.ArrS[3].Arr[6:7]
22623//
22624// r.ArrS[3].x
22625namespace {
22626class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
22627 Sema &SemaRef;
22628 OpenMPClauseKind CKind = OMPC_unknown;
22629 OpenMPDirectiveKind DKind = OMPD_unknown;
22631 bool IsNonContiguous = false;
22632 bool NoDiagnose = false;
22633 const Expr *RelevantExpr = nullptr;
22634 bool AllowUnitySizeArraySection = true;
22635 bool AllowWholeSizeArraySection = true;
22636 bool AllowAnotherPtr = true;
22637 SourceLocation ELoc;
22638 SourceRange ERange;
22639
22640 void emitErrorMsg() {
22641 // If nothing else worked, this is not a valid map clause expression.
22642 if (SemaRef.getLangOpts().OpenMP < 50) {
22643 SemaRef.Diag(ELoc,
22644 diag::err_omp_expected_named_var_member_or_array_expression)
22645 << ERange;
22646 } else {
22647 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22648 << getOpenMPClauseNameForDiag(CKind) << ERange;
22649 }
22650 }
22651
22652public:
22653 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
22654 if (!isa<VarDecl>(DRE->getDecl())) {
22655 emitErrorMsg();
22656 return false;
22657 }
22658 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22659 RelevantExpr = DRE;
22660 // Record the component.
22661 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
22662 return true;
22663 }
22664
22665 bool VisitMemberExpr(MemberExpr *ME) {
22666 Expr *E = ME;
22667 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
22668
22669 if (isa<CXXThisExpr>(BaseE)) {
22670 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22671 // We found a base expression: this->Val.
22672 RelevantExpr = ME;
22673 } else {
22674 E = BaseE;
22675 }
22676
22677 if (!isa<FieldDecl>(ME->getMemberDecl())) {
22678 if (!NoDiagnose) {
22679 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
22680 << ME->getSourceRange();
22681 return false;
22682 }
22683 if (RelevantExpr)
22684 return false;
22685 return Visit(E);
22686 }
22687
22688 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
22689
22690 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
22691 // A bit-field cannot appear in a map clause.
22692 //
22693 if (FD->isBitField()) {
22694 if (!NoDiagnose) {
22695 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
22696 << ME->getSourceRange() << getOpenMPClauseNameForDiag(CKind);
22697 return false;
22698 }
22699 if (RelevantExpr)
22700 return false;
22701 return Visit(E);
22702 }
22703
22704 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22705 // If the type of a list item is a reference to a type T then the type
22706 // will be considered to be T for all purposes of this clause.
22707 QualType CurType = BaseE->getType().getNonReferenceType();
22708
22709 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
22710 // A list item cannot be a variable that is a member of a structure with
22711 // a union type.
22712 //
22713 if (CurType->isUnionType()) {
22714 if (!NoDiagnose) {
22715 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
22716 << ME->getSourceRange();
22717 return false;
22718 }
22719 return RelevantExpr || Visit(E);
22720 }
22721
22722 // If we got a member expression, we should not expect any array section
22723 // before that:
22724 //
22725 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
22726 // If a list item is an element of a structure, only the rightmost symbol
22727 // of the variable reference can be an array section.
22728 //
22729 AllowUnitySizeArraySection = false;
22730 AllowWholeSizeArraySection = false;
22731
22732 // Record the component.
22733 Components.emplace_back(ME, FD, IsNonContiguous);
22734 return RelevantExpr || Visit(E);
22735 }
22736
22737 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
22738 Expr *E = AE->getBase()->IgnoreParenImpCasts();
22739
22740 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
22741 if (!NoDiagnose) {
22742 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22743 << 0 << AE->getSourceRange();
22744 return false;
22745 }
22746 return RelevantExpr || Visit(E);
22747 }
22748
22749 // If we got an array subscript that express the whole dimension we
22750 // can have any array expressions before. If it only expressing part of
22751 // the dimension, we can only have unitary-size array expressions.
22753 AllowWholeSizeArraySection = false;
22754
22755 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
22756 Expr::EvalResult Result;
22757 if (!AE->getIdx()->isValueDependent() &&
22758 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
22759 !Result.Val.getInt().isZero()) {
22760 SemaRef.Diag(AE->getIdx()->getExprLoc(),
22761 diag::err_omp_invalid_map_this_expr);
22762 SemaRef.Diag(AE->getIdx()->getExprLoc(),
22763 diag::note_omp_invalid_subscript_on_this_ptr_map);
22764 }
22765 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22766 RelevantExpr = TE;
22767 }
22768
22769 // Record the component - we don't have any declaration associated.
22770 Components.emplace_back(AE, nullptr, IsNonContiguous);
22771
22772 return RelevantExpr || Visit(E);
22773 }
22774
22775 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
22776 // After OMP 5.0 Array section in reduction clause will be implicitly
22777 // mapped
22778 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
22779 "Array sections cannot be implicitly mapped.");
22780 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
22781 QualType CurType =
22783
22784 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22785 // If the type of a list item is a reference to a type T then the type
22786 // will be considered to be T for all purposes of this clause.
22787 if (CurType->isReferenceType())
22788 CurType = CurType->getPointeeType();
22789
22790 bool IsPointer = CurType->isAnyPointerType();
22791
22792 if (!IsPointer && !CurType->isArrayType()) {
22793 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22794 << 0 << OASE->getSourceRange();
22795 return false;
22796 }
22797
22798 bool NotWhole =
22799 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
22800 bool NotUnity =
22801 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
22802
22803 if (AllowWholeSizeArraySection) {
22804 // Any array section is currently allowed. Allowing a whole size array
22805 // section implies allowing a unity array section as well.
22806 //
22807 // If this array section refers to the whole dimension we can still
22808 // accept other array sections before this one, except if the base is a
22809 // pointer. Otherwise, only unitary sections are accepted.
22810 if (NotWhole || IsPointer)
22811 AllowWholeSizeArraySection = false;
22812 } else if (DKind == OMPD_target_update &&
22813 SemaRef.getLangOpts().OpenMP >= 50) {
22814 if (IsPointer && !AllowAnotherPtr)
22815 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
22816 << /*array of unknown bound */ 1;
22817 else
22818 IsNonContiguous = true;
22819 } else if (AllowUnitySizeArraySection && NotUnity) {
22820 // A unity or whole array section is not allowed and that is not
22821 // compatible with the properties of the current array section.
22822 if (NoDiagnose)
22823 return false;
22824 SemaRef.Diag(ELoc,
22825 diag::err_array_section_does_not_specify_contiguous_storage)
22826 << OASE->getSourceRange();
22827 return false;
22828 }
22829
22830 if (IsPointer)
22831 AllowAnotherPtr = false;
22832
22833 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
22834 Expr::EvalResult ResultR;
22835 Expr::EvalResult ResultL;
22836 if (!OASE->getLength()->isValueDependent() &&
22837 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
22838 !ResultR.Val.getInt().isOne()) {
22839 SemaRef.Diag(OASE->getLength()->getExprLoc(),
22840 diag::err_omp_invalid_map_this_expr);
22841 SemaRef.Diag(OASE->getLength()->getExprLoc(),
22842 diag::note_omp_invalid_length_on_this_ptr_mapping);
22843 }
22844 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
22845 OASE->getLowerBound()->EvaluateAsInt(ResultL,
22846 SemaRef.getASTContext()) &&
22847 !ResultL.Val.getInt().isZero()) {
22848 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
22849 diag::err_omp_invalid_map_this_expr);
22850 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
22851 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
22852 }
22853 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22854 RelevantExpr = TE;
22855 }
22856
22857 // Record the component - we don't have any declaration associated.
22858 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
22859 return RelevantExpr || Visit(E);
22860 }
22861 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
22862 Expr *Base = E->getBase();
22863
22864 // Record the component - we don't have any declaration associated.
22865 Components.emplace_back(E, nullptr, IsNonContiguous);
22866
22867 return Visit(Base->IgnoreParenImpCasts());
22868 }
22869
22870 bool VisitUnaryOperator(UnaryOperator *UO) {
22871 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
22872 UO->getOpcode() != UO_Deref) {
22873 emitErrorMsg();
22874 return false;
22875 }
22876 if (!RelevantExpr) {
22877 // Record the component if haven't found base decl.
22878 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
22879 }
22880 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
22881 }
22882 bool VisitBinaryOperator(BinaryOperator *BO) {
22883 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
22884 emitErrorMsg();
22885 return false;
22886 }
22887
22888 // Pointer arithmetic is the only thing we expect to happen here so after we
22889 // make sure the binary operator is a pointer type, the only thing we need
22890 // to do is to visit the subtree that has the same type as root (so that we
22891 // know the other subtree is just an offset)
22892 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
22893 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
22894 Components.emplace_back(BO, nullptr, false);
22895 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
22896 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
22897 "Either LHS or RHS have base decl inside");
22898 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
22899 return RelevantExpr || Visit(LE);
22900 return RelevantExpr || Visit(RE);
22901 }
22902 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
22903 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22904 RelevantExpr = CTE;
22905 Components.emplace_back(CTE, nullptr, IsNonContiguous);
22906 return true;
22907 }
22908 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
22909 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22910 Components.emplace_back(COCE, nullptr, IsNonContiguous);
22911 return true;
22912 }
22913 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
22914 Expr *Source = E->getSourceExpr();
22915 if (!Source) {
22916 emitErrorMsg();
22917 return false;
22918 }
22919 return Visit(Source);
22920 }
22921 bool VisitStmt(Stmt *) {
22922 emitErrorMsg();
22923 return false;
22924 }
22925 const Expr *getFoundBase() const { return RelevantExpr; }
22926 explicit MapBaseChecker(
22927 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
22929 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
22930 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
22931 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
22932};
22933} // namespace
22934
22935/// Return the expression of the base of the mappable expression or null if it
22936/// cannot be determined and do all the necessary checks to see if the
22937/// expression is valid as a standalone mappable expression. In the process,
22938/// record all the components of the expression.
22940 Sema &SemaRef, Expr *E,
22942 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
22943 SourceLocation ELoc = E->getExprLoc();
22944 SourceRange ERange = E->getSourceRange();
22945 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
22946 ERange);
22947 if (Checker.Visit(E->IgnoreParens())) {
22948 // Check if the highest dimension array section has length specified
22949 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
22950 (CKind == OMPC_to || CKind == OMPC_from)) {
22951 auto CI = CurComponents.rbegin();
22952 auto CE = CurComponents.rend();
22953 for (; CI != CE; ++CI) {
22954 const auto *OASE =
22955 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
22956 if (!OASE)
22957 continue;
22958 if (OASE && OASE->getLength())
22959 break;
22960 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
22961 << ERange;
22962 }
22963 }
22964 return Checker.getFoundBase();
22965 }
22966 return nullptr;
22967}
22968
22969// Return true if expression E associated with value VD has conflicts with other
22970// map information.
22972 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
22973 bool CurrentRegionOnly,
22975 OpenMPClauseKind CKind) {
22976 assert(VD && E);
22977 SourceLocation ELoc = E->getExprLoc();
22978 SourceRange ERange = E->getSourceRange();
22979
22980 // In order to easily check the conflicts we need to match each component of
22981 // the expression under test with the components of the expressions that are
22982 // already in the stack.
22983
22984 assert(!CurComponents.empty() && "Map clause expression with no components!");
22985 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
22986 "Map clause expression with unexpected base!");
22987
22988 // Variables to help detecting enclosing problems in data environment nests.
22989 bool IsEnclosedByDataEnvironmentExpr = false;
22990 const Expr *EnclosingExpr = nullptr;
22991
22992 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
22993 VD, CurrentRegionOnly,
22994 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
22995 ERange, CKind, &EnclosingExpr,
22997 StackComponents,
22998 OpenMPClauseKind Kind) {
22999 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
23000 return false;
23001 assert(!StackComponents.empty() &&
23002 "Map clause expression with no components!");
23003 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
23004 "Map clause expression with unexpected base!");
23005 (void)VD;
23006
23007 // The whole expression in the stack.
23008 const Expr *RE = StackComponents.front().getAssociatedExpression();
23009
23010 // Expressions must start from the same base. Here we detect at which
23011 // point both expressions diverge from each other and see if we can
23012 // detect if the memory referred to both expressions is contiguous and
23013 // do not overlap.
23014 auto CI = CurComponents.rbegin();
23015 auto CE = CurComponents.rend();
23016 auto SI = StackComponents.rbegin();
23017 auto SE = StackComponents.rend();
23018 for (; CI != CE && SI != SE; ++CI, ++SI) {
23019
23020 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
23021 // At most one list item can be an array item derived from a given
23022 // variable in map clauses of the same construct.
23023 if (CurrentRegionOnly &&
23024 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
23025 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
23026 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
23027 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
23028 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
23029 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
23030 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
23031 diag::err_omp_multiple_array_items_in_map_clause)
23032 << CI->getAssociatedExpression()->getSourceRange();
23033 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
23034 diag::note_used_here)
23035 << SI->getAssociatedExpression()->getSourceRange();
23036 return true;
23037 }
23038
23039 // Do both expressions have the same kind?
23040 if (CI->getAssociatedExpression()->getStmtClass() !=
23041 SI->getAssociatedExpression()->getStmtClass())
23042 break;
23043
23044 // Are we dealing with different variables/fields?
23045 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
23046 break;
23047 }
23048 // Check if the extra components of the expressions in the enclosing
23049 // data environment are redundant for the current base declaration.
23050 // If they are, the maps completely overlap, which is legal.
23051 for (; SI != SE; ++SI) {
23052 QualType Type;
23053 if (const auto *ASE =
23054 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
23055 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
23056 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
23057 SI->getAssociatedExpression())) {
23058 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
23060 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
23061 SI->getAssociatedExpression())) {
23062 Type = OASE->getBase()->getType()->getPointeeType();
23063 }
23064 if (Type.isNull() || Type->isAnyPointerType() ||
23066 SemaRef, SI->getAssociatedExpression(), Type))
23067 break;
23068 }
23069
23070 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
23071 // List items of map clauses in the same construct must not share
23072 // original storage.
23073 //
23074 // If the expressions are exactly the same or one is a subset of the
23075 // other, it means they are sharing storage.
23076 if (CI == CE && SI == SE) {
23077 if (CurrentRegionOnly) {
23078 if (CKind == OMPC_map) {
23079 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
23080 } else {
23081 assert(CKind == OMPC_to || CKind == OMPC_from);
23082 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
23083 << ERange;
23084 }
23085 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
23086 << RE->getSourceRange();
23087 return true;
23088 }
23089 // If we find the same expression in the enclosing data environment,
23090 // that is legal.
23091 IsEnclosedByDataEnvironmentExpr = true;
23092 return false;
23093 }
23094
23095 QualType DerivedType =
23096 std::prev(CI)->getAssociatedDeclaration()->getType();
23097 SourceLocation DerivedLoc =
23098 std::prev(CI)->getAssociatedExpression()->getExprLoc();
23099
23100 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
23101 // If the type of a list item is a reference to a type T then the type
23102 // will be considered to be T for all purposes of this clause.
23103 DerivedType = DerivedType.getNonReferenceType();
23104
23105 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
23106 // A variable for which the type is pointer and an array section
23107 // derived from that variable must not appear as list items of map
23108 // clauses of the same construct.
23109 //
23110 // Also, cover one of the cases in:
23111 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
23112 // If any part of the original storage of a list item has corresponding
23113 // storage in the device data environment, all of the original storage
23114 // must have corresponding storage in the device data environment.
23115 //
23116 if (DerivedType->isAnyPointerType()) {
23117 if (CI == CE || SI == SE) {
23118 SemaRef.Diag(
23119 DerivedLoc,
23120 diag::err_omp_pointer_mapped_along_with_derived_section)
23121 << DerivedLoc;
23122 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
23123 << RE->getSourceRange();
23124 return true;
23125 }
23126 if (CI->getAssociatedExpression()->getStmtClass() !=
23127 SI->getAssociatedExpression()->getStmtClass() ||
23128 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
23129 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
23130 assert(CI != CE && SI != SE);
23131 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
23132 << DerivedLoc;
23133 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
23134 << RE->getSourceRange();
23135 return true;
23136 }
23137 }
23138
23139 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
23140 // List items of map clauses in the same construct must not share
23141 // original storage.
23142 //
23143 // An expression is a subset of the other.
23144 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
23145 if (CKind == OMPC_map) {
23146 if (CI != CE || SI != SE) {
23147 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
23148 // a pointer.
23149 auto Begin =
23150 CI != CE ? CurComponents.begin() : StackComponents.begin();
23151 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
23152 auto It = Begin;
23153 while (It != End && !It->getAssociatedDeclaration())
23154 std::advance(It, 1);
23155 assert(It != End &&
23156 "Expected at least one component with the declaration.");
23157 if (It != Begin && It->getAssociatedDeclaration()
23158 ->getType()
23159 .getCanonicalType()
23160 ->isAnyPointerType()) {
23161 IsEnclosedByDataEnvironmentExpr = false;
23162 EnclosingExpr = nullptr;
23163 return false;
23164 }
23165 }
23166 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
23167 } else {
23168 assert(CKind == OMPC_to || CKind == OMPC_from);
23169 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
23170 << ERange;
23171 }
23172 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
23173 << RE->getSourceRange();
23174 return true;
23175 }
23176
23177 // The current expression uses the same base as other expression in the
23178 // data environment but does not contain it completely.
23179 if (!CurrentRegionOnly && SI != SE)
23180 EnclosingExpr = RE;
23181
23182 // The current expression is a subset of the expression in the data
23183 // environment.
23184 IsEnclosedByDataEnvironmentExpr |=
23185 (!CurrentRegionOnly && CI != CE && SI == SE);
23186
23187 return false;
23188 });
23189
23190 if (CurrentRegionOnly)
23191 return FoundError;
23192
23193 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
23194 // If any part of the original storage of a list item has corresponding
23195 // storage in the device data environment, all of the original storage must
23196 // have corresponding storage in the device data environment.
23197 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
23198 // If a list item is an element of a structure, and a different element of
23199 // the structure has a corresponding list item in the device data environment
23200 // prior to a task encountering the construct associated with the map clause,
23201 // then the list item must also have a corresponding list item in the device
23202 // data environment prior to the task encountering the construct.
23203 //
23204 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
23205 SemaRef.Diag(ELoc,
23206 diag::err_omp_original_storage_is_shared_and_does_not_contain)
23207 << ERange;
23208 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
23209 << EnclosingExpr->getSourceRange();
23210 return true;
23211 }
23212
23213 return FoundError;
23214}
23215
23216// Look up the user-defined mapper given the mapper name and mapped type, and
23217// build a reference to it.
23219 CXXScopeSpec &MapperIdScopeSpec,
23220 const DeclarationNameInfo &MapperId,
23221 QualType Type,
23222 Expr *UnresolvedMapper) {
23223 if (MapperIdScopeSpec.isInvalid())
23224 return ExprError();
23225 // Get the actual type for the array type.
23226 if (Type->isArrayType()) {
23227 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
23229 }
23230 // Find all user-defined mappers with the given MapperId.
23231 SmallVector<UnresolvedSet<8>, 4> Lookups;
23232 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
23233 Lookup.suppressDiagnostics();
23234 if (S) {
23235 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
23236 /*ObjectType=*/QualType())) {
23237 NamedDecl *D = Lookup.getRepresentativeDecl();
23238 while (S && !S->isDeclScope(D))
23239 S = S->getParent();
23240 if (S)
23241 S = S->getParent();
23242 Lookups.emplace_back();
23243 Lookups.back().append(Lookup.begin(), Lookup.end());
23244 Lookup.clear();
23245 }
23246 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
23247 // Extract the user-defined mappers with the given MapperId.
23248 Lookups.push_back(UnresolvedSet<8>());
23249 for (NamedDecl *D : ULE->decls()) {
23250 auto *DMD = cast<OMPDeclareMapperDecl>(D);
23251 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
23252 Lookups.back().addDecl(DMD);
23253 }
23254 }
23255 // Defer the lookup for dependent types. The results will be passed through
23256 // UnresolvedMapper on instantiation.
23257 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
23261 return !D->isInvalidDecl() &&
23262 (D->getType()->isDependentType() ||
23263 D->getType()->isInstantiationDependentType() ||
23264 D->getType()->containsUnexpandedParameterPack());
23265 })) {
23266 UnresolvedSet<8> URS;
23267 for (const UnresolvedSet<8> &Set : Lookups) {
23268 if (Set.empty())
23269 continue;
23270 URS.append(Set.begin(), Set.end());
23271 }
23273 SemaRef.Context, /*NamingClass=*/nullptr,
23274 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
23275 /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false,
23276 /*KnownInstantiationDependent=*/false);
23277 }
23278 SourceLocation Loc = MapperId.getLoc();
23279 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
23280 // The type must be of struct, union or class type in C and C++
23282 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
23283 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
23284 return ExprError();
23285 }
23286 // Perform argument dependent lookup.
23287 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
23288 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
23289 // Return the first user-defined mapper with the desired type.
23291 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
23292 if (!D->isInvalidDecl() &&
23293 SemaRef.Context.hasSameType(D->getType(), Type))
23294 return D;
23295 return nullptr;
23296 }))
23297 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
23298 // Find the first user-defined mapper with a type derived from the desired
23299 // type.
23301 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
23302 if (!D->isInvalidDecl() &&
23303 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
23304 !Type.isMoreQualifiedThan(D->getType(),
23305 SemaRef.getASTContext()))
23306 return D;
23307 return nullptr;
23308 })) {
23309 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
23310 /*DetectVirtual=*/false);
23311 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
23312 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
23313 VD->getType().getUnqualifiedType()))) {
23314 if (SemaRef.CheckBaseClassAccess(
23315 Loc, VD->getType(), Type, Paths.front(),
23316 /*DiagID=*/0) != Sema::AR_inaccessible) {
23317 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
23318 }
23319 }
23320 }
23321 }
23322 // Report error if a mapper is specified, but cannot be found.
23323 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
23324 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
23325 << Type << MapperId.getName();
23326 return ExprError();
23327 }
23328 return ExprEmpty();
23329}
23330
23331namespace {
23332// Utility struct that gathers all the related lists associated with a mappable
23333// expression.
23334struct MappableVarListInfo {
23335 // The list of expressions.
23336 ArrayRef<Expr *> VarList;
23337 // The list of processed expressions.
23338 SmallVector<Expr *, 16> ProcessedVarList;
23339 // The mappble components for each expression.
23341 // The base declaration of the variable.
23342 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
23343 // The reference to the user-defined mapper associated with every expression.
23344 SmallVector<Expr *, 16> UDMapperList;
23345
23346 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
23347 // We have a list of components and base declarations for each entry in the
23348 // variable list.
23349 VarComponents.reserve(VarList.size());
23350 VarBaseDeclarations.reserve(VarList.size());
23351 }
23352};
23353} // namespace
23354
23356 DSAStackTy *Stack,
23358
23359 const RecordDecl *RD = BaseType->getAsRecordDecl();
23360 SourceRange Range = RD->getSourceRange();
23361 DeclarationNameInfo ImplicitName;
23362 // Dummy variable _s for Mapper.
23363 VarDecl *VD = buildVarDecl(S, Range.getEnd(), BaseType, "_s");
23364 DeclRefExpr *MapperVarRef =
23365 buildDeclRefExpr(S, VD, BaseType, SourceLocation());
23366
23367 // Create implicit map clause for mapper.
23369 for (auto *FD : RD->fields()) {
23370 Expr *BE = S.BuildMemberExpr(
23371 MapperVarRef, /*IsArrow=*/false, Range.getBegin(),
23372 NestedNameSpecifierLoc(), Range.getBegin(), FD,
23374 /*HadMultipleCandidates=*/false,
23376 FD->getType(), VK_LValue, OK_Ordinary);
23377 SExprs.push_back(BE);
23378 }
23379 CXXScopeSpec MapperIdScopeSpec;
23380 DeclarationNameInfo MapperId;
23381 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
23382
23383 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
23384 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec,
23385 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
23386 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), SExprs,
23387 OMPVarListLocTy());
23388 Maps.push_back(MapClause);
23389 return MapperVarRef;
23390}
23391
23393 DSAStackTy *Stack) {
23394
23395 // Build impilicit map for mapper
23397 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
23398
23399 const RecordDecl *RD = BaseType->getAsRecordDecl();
23400 // AST context is RD's ParentASTContext().
23401 ASTContext &Ctx = RD->getParentASTContext();
23402 // DeclContext is RD's DeclContext.
23403 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
23404
23405 // Create implicit default mapper for "RD".
23406 DeclarationName MapperId;
23407 auto &DeclNames = Ctx.DeclarationNames;
23408 MapperId = DeclNames.getIdentifier(&Ctx.Idents.get("default"));
23409 auto *DMD = OMPDeclareMapperDecl::Create(Ctx, DCT, SourceLocation(), MapperId,
23410 BaseType, MapperId, Maps, nullptr);
23411 Scope *Scope = S.getScopeForContext(DCT);
23412 if (Scope)
23413 S.PushOnScopeChains(DMD, Scope, /*AddToContext=*/false);
23414 DCT->addDecl(DMD);
23415 DMD->setAccess(clang::AS_none);
23416 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
23417 VD->setDeclContext(DMD);
23418 VD->setLexicalDeclContext(DMD);
23419 DMD->addDecl(VD);
23420 DMD->setMapperVarRef(MapperVarRef);
23421 FieldDecl *FD = *RD->field_begin();
23422 // create mapper refence.
23424 DMD, false, SourceLocation(), BaseType, VK_LValue);
23425}
23426
23427// Look up the user-defined mapper given the mapper name and mapper type,
23428// return true if found one.
23429static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
23430 CXXScopeSpec &MapperIdScopeSpec,
23431 const DeclarationNameInfo &MapperId,
23432 QualType Type) {
23433 // Find all user-defined mappers with the given MapperId.
23434 SmallVector<UnresolvedSet<8>, 4> Lookups;
23435 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
23436 Lookup.suppressDiagnostics();
23437 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
23438 /*ObjectType=*/QualType())) {
23439 NamedDecl *D = Lookup.getRepresentativeDecl();
23440 while (S && !S->isDeclScope(D))
23441 S = S->getParent();
23442 if (S)
23443 S = S->getParent();
23444 Lookups.emplace_back();
23445 Lookups.back().append(Lookup.begin(), Lookup.end());
23446 Lookup.clear();
23447 }
23448 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
23452 return !D->isInvalidDecl() &&
23453 (D->getType()->isDependentType() ||
23454 D->getType()->isInstantiationDependentType() ||
23455 D->getType()->containsUnexpandedParameterPack());
23456 }))
23457 return false;
23458 // Perform argument dependent lookup.
23459 SourceLocation Loc = MapperId.getLoc();
23460 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
23461 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
23463 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
23464 if (!D->isInvalidDecl() &&
23465 SemaRef.Context.hasSameType(D->getType(), Type))
23466 return D;
23467 return nullptr;
23468 }))
23469 return true;
23470 // Find the first user-defined mapper with a type derived from the desired
23471 // type.
23473 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
23474 if (!D->isInvalidDecl() &&
23475 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
23476 !Type.isMoreQualifiedThan(D->getType(), SemaRef.getASTContext()))
23477 return D;
23478 return nullptr;
23479 });
23480 if (!VD)
23481 return false;
23482 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
23483 /*DetectVirtual=*/false);
23484 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
23485 bool IsAmbiguous = !Paths.isAmbiguous(
23487 if (IsAmbiguous)
23488 return false;
23489 if (SemaRef.CheckBaseClassAccess(Loc, VD->getType(), Type, Paths.front(),
23490 /*DiagID=*/0) != Sema::AR_inaccessible)
23491 return true;
23492 }
23493 return false;
23494}
23495
23496static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
23497 QualType CanonType, const Expr *E) {
23498
23499 // DFS over data members in structures/classes.
23501 {CanonType, nullptr});
23502 llvm::DenseMap<const Type *, bool> Visited;
23503 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
23504 while (!Types.empty()) {
23505 auto [BaseType, CurFD] = Types.pop_back_val();
23506 while (ParentChain.back().second == 0)
23507 ParentChain.pop_back();
23508 --ParentChain.back().second;
23509 if (BaseType.isNull())
23510 continue;
23511 // Only structs/classes are allowed to have mappers.
23512 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
23513 if (!RD)
23514 continue;
23515 auto It = Visited.find(BaseType.getTypePtr());
23516 if (It == Visited.end()) {
23517 // Try to find the associated user-defined mapper.
23518 CXXScopeSpec MapperIdScopeSpec;
23519 DeclarationNameInfo DefaultMapperId;
23521 &S.Context.Idents.get("default")));
23522 DefaultMapperId.setLoc(E->getExprLoc());
23523 bool HasUDMapper =
23524 hasUserDefinedMapper(S, Stack->getCurScope(), MapperIdScopeSpec,
23525 DefaultMapperId, BaseType);
23526 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
23527 }
23528 // Found default mapper.
23529 if (It->second)
23530 return true;
23531 // Check for the "default" mapper for data members.
23532 bool FirstIter = true;
23533 for (FieldDecl *FD : RD->fields()) {
23534 if (!FD)
23535 continue;
23536 QualType FieldTy = FD->getType();
23537 if (FieldTy.isNull() ||
23538 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
23539 continue;
23540 if (FirstIter) {
23541 FirstIter = false;
23542 ParentChain.emplace_back(CurFD, 1);
23543 } else {
23544 ++ParentChain.back().second;
23545 }
23546 Types.emplace_back(FieldTy, FD);
23547 }
23548 }
23549 return false;
23550}
23551
23552// Check the validity of the provided variable list for the provided clause kind
23553// \a CKind. In the check process the valid expressions, mappable expression
23554// components, variables, and user-defined mappers are extracted and used to
23555// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
23556// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
23557// and \a MapperId are expected to be valid if the clause kind is 'map'.
23559 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
23560 MappableVarListInfo &MVLI, SourceLocation StartLoc,
23561 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
23562 ArrayRef<Expr *> UnresolvedMappers,
23564 ArrayRef<OpenMPMapModifierKind> Modifiers = {},
23565 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
23566 // We only expect mappable expressions in 'to', 'from', 'map', and
23567 // 'use_device_addr' clauses.
23568 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from ||
23569 CKind == OMPC_use_device_addr) &&
23570 "Unexpected clause kind with mappable expressions!");
23571 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
23572
23573 // If the identifier of user-defined mapper is not specified, it is "default".
23574 // We do not change the actual name in this clause to distinguish whether a
23575 // mapper is specified explicitly, i.e., it is not explicitly specified when
23576 // MapperId.getName() is empty.
23577 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
23578 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
23579 MapperId.setName(DeclNames.getIdentifier(
23580 &SemaRef.getASTContext().Idents.get("default")));
23581 MapperId.setLoc(StartLoc);
23582 }
23583
23584 // Iterators to find the current unresolved mapper expression.
23585 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
23586 bool UpdateUMIt = false;
23587 Expr *UnresolvedMapper = nullptr;
23588
23589 bool HasHoldModifier =
23590 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
23591
23592 // Keep track of the mappable components and base declarations in this clause.
23593 // Each entry in the list is going to have a list of components associated. We
23594 // record each set of the components so that we can build the clause later on.
23595 // In the end we should have the same amount of declarations and component
23596 // lists.
23597
23598 for (Expr *RE : MVLI.VarList) {
23599 assert(RE && "Null expr in omp to/from/map clause");
23600 SourceLocation ELoc = RE->getExprLoc();
23601
23602 // Find the current unresolved mapper expression.
23603 if (UpdateUMIt && UMIt != UMEnd) {
23604 UMIt++;
23605 assert(
23606 UMIt != UMEnd &&
23607 "Expect the size of UnresolvedMappers to match with that of VarList");
23608 }
23609 UpdateUMIt = true;
23610 if (UMIt != UMEnd)
23611 UnresolvedMapper = *UMIt;
23612
23613 const Expr *VE = RE->IgnoreParenLValueCasts();
23614
23615 if (VE->isValueDependent() || VE->isTypeDependent() ||
23616 VE->isInstantiationDependent() ||
23617 VE->containsUnexpandedParameterPack()) {
23618 // Try to find the associated user-defined mapper.
23620 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23621 VE->getType().getCanonicalType(), UnresolvedMapper);
23622 if (ER.isInvalid())
23623 continue;
23624 MVLI.UDMapperList.push_back(ER.get());
23625 // We can only analyze this information once the missing information is
23626 // resolved.
23627 MVLI.ProcessedVarList.push_back(RE);
23628 continue;
23629 }
23630
23632
23633 if (!RE->isLValue()) {
23634 if (SemaRef.getLangOpts().OpenMP < 50) {
23635 SemaRef.Diag(
23636 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
23637 << RE->getSourceRange();
23638 } else {
23639 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
23640 << getOpenMPClauseNameForDiag(CKind) << RE->getSourceRange();
23641 }
23642 continue;
23643 }
23644
23646 ValueDecl *CurDeclaration = nullptr;
23647
23648 // Obtain the array or member expression bases if required. Also, fill the
23649 // components array with all the components identified in the process.
23650 const Expr *BE =
23651 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
23652 DSAS->getCurrentDirective(), NoDiagnose);
23653 if (!BE)
23654 continue;
23655
23656 assert(!CurComponents.empty() &&
23657 "Invalid mappable expression information.");
23658
23659 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
23660 // Add store "this" pointer to class in DSAStackTy for future checking
23661 DSAS->addMappedClassesQualTypes(TE->getType());
23662 // Try to find the associated user-defined mapper.
23664 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23665 VE->getType().getCanonicalType(), UnresolvedMapper);
23666 if (ER.isInvalid())
23667 continue;
23668 MVLI.UDMapperList.push_back(ER.get());
23669 // Skip restriction checking for variable or field declarations
23670 MVLI.ProcessedVarList.push_back(RE);
23671 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23672 MVLI.VarComponents.back().append(CurComponents.begin(),
23673 CurComponents.end());
23674 MVLI.VarBaseDeclarations.push_back(nullptr);
23675 continue;
23676 }
23677
23678 // For the following checks, we rely on the base declaration which is
23679 // expected to be associated with the last component. The declaration is
23680 // expected to be a variable or a field (if 'this' is being mapped).
23681 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
23682 assert(CurDeclaration && "Null decl on map clause.");
23683 assert(
23684 CurDeclaration->isCanonicalDecl() &&
23685 "Expecting components to have associated only canonical declarations.");
23686
23687 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
23688 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
23689
23690 assert((VD || FD) && "Only variables or fields are expected here!");
23691 (void)FD;
23692
23693 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
23694 // threadprivate variables cannot appear in a map clause.
23695 // OpenMP 4.5 [2.10.5, target update Construct]
23696 // threadprivate variables cannot appear in a from clause.
23697 if (VD && DSAS->isThreadPrivate(VD)) {
23698 if (NoDiagnose)
23699 continue;
23700 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
23701 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
23703 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
23704 continue;
23705 }
23706
23707 // OpenMP 6.0 [7.9.6, map Clause, Restrictions, p. 386]
23708 // A device-local variable must not appear as a list item in a map clause.
23709 if (VD && CKind == OMPC_map) {
23710 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
23711 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
23712 if (*Res == OMPDeclareTargetDeclAttr::MT_Local) {
23713 if (NoDiagnose)
23714 continue;
23715 SemaRef.Diag(ELoc, diag::err_omp_device_local_in_clause)
23716 << VD << getOpenMPClauseNameForDiag(CKind);
23717 continue;
23718 }
23719 }
23720 }
23721
23722 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
23723 // A list item cannot appear in both a map clause and a data-sharing
23724 // attribute clause on the same construct.
23725
23726 // Check conflicts with other map clause expressions. We check the conflicts
23727 // with the current construct separately from the enclosing data
23728 // environment, because the restrictions are different. We only have to
23729 // check conflicts across regions for the map clauses.
23730 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
23731 /*CurrentRegionOnly=*/true, CurComponents, CKind))
23732 break;
23733 if (CKind == OMPC_map &&
23734 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
23735 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
23736 /*CurrentRegionOnly=*/false, CurComponents, CKind))
23737 break;
23738
23739 // OpenMP 4.5 [2.10.5, target update Construct]
23740 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
23741 // If the type of a list item is a reference to a type T then the type will
23742 // be considered to be T for all purposes of this clause.
23743 auto I = llvm::find_if(
23744 CurComponents,
23745 [](const OMPClauseMappableExprCommon::MappableComponent &MC) {
23746 return MC.getAssociatedDeclaration();
23747 });
23748 assert(I != CurComponents.end() && "Null decl on map clause.");
23749 (void)I;
23750 QualType Type;
23751 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
23752 auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens());
23753 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
23754 if (ASE) {
23755 Type = ASE->getType().getNonReferenceType();
23756 } else if (OASE) {
23757 QualType BaseType =
23759 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
23760 Type = ATy->getElementType();
23761 else
23762 Type = BaseType->getPointeeType();
23763 Type = Type.getNonReferenceType();
23764 } else if (OAShE) {
23765 Type = OAShE->getBase()->getType()->getPointeeType();
23766 } else {
23767 Type = VE->getType();
23768 }
23769
23770 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
23771 // A list item in a to or from clause must have a mappable type.
23772 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
23773 // A list item must have a mappable type.
23774 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
23775 DSAS, Type, /*FullCheck=*/true))
23776 continue;
23777
23778 if (CKind == OMPC_map) {
23779 // target enter data
23780 // OpenMP [2.10.2, Restrictions, p. 99]
23781 // A map-type must be specified in all map clauses and must be either
23782 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
23783 // no map type is present.
23784 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
23785 if (DKind == OMPD_target_enter_data &&
23786 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
23787 SemaRef.getLangOpts().OpenMP >= 52)) {
23788 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23789 << (IsMapTypeImplicit ? 1 : 0)
23790 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
23791 << getOpenMPDirectiveName(DKind, OMPVersion);
23792 continue;
23793 }
23794
23795 // target exit_data
23796 // OpenMP [2.10.3, Restrictions, p. 102]
23797 // A map-type must be specified in all map clauses and must be either
23798 // from, release, or delete. Starting with OpenMP 5.2 the default map
23799 // type is `from` if no map type is present.
23800 if (DKind == OMPD_target_exit_data &&
23801 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
23802 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
23803 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23804 << (IsMapTypeImplicit ? 1 : 0)
23805 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
23806 << getOpenMPDirectiveName(DKind, OMPVersion);
23807 continue;
23808 }
23809
23810 // The 'ompx_hold' modifier is specifically intended to be used on a
23811 // 'target' or 'target data' directive to prevent data from being unmapped
23812 // during the associated statement. It is not permitted on a 'target
23813 // enter data' or 'target exit data' directive, which have no associated
23814 // statement.
23815 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
23816 HasHoldModifier) {
23817 SemaRef.Diag(StartLoc,
23818 diag::err_omp_invalid_map_type_modifier_for_directive)
23820 OMPC_MAP_MODIFIER_ompx_hold)
23821 << getOpenMPDirectiveName(DKind, OMPVersion);
23822 continue;
23823 }
23824
23825 // target, target data
23826 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
23827 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
23828 // A map-type in a map clause must be to, from, tofrom or alloc
23829 if ((DKind == OMPD_target_data ||
23831 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
23832 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
23833 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23834 << (IsMapTypeImplicit ? 1 : 0)
23835 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
23836 << getOpenMPDirectiveName(DKind, OMPVersion);
23837 continue;
23838 }
23839
23840 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
23841 // A list item cannot appear in both a map clause and a data-sharing
23842 // attribute clause on the same construct
23843 //
23844 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
23845 // A list item cannot appear in both a map clause and a data-sharing
23846 // attribute clause on the same construct unless the construct is a
23847 // combined construct.
23848 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
23850 DKind == OMPD_target)) {
23851 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
23852 if (isOpenMPPrivate(DVar.CKind)) {
23853 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23854 << getOpenMPClauseNameForDiag(DVar.CKind)
23855 << getOpenMPClauseNameForDiag(OMPC_map)
23856 << getOpenMPDirectiveName(DSAS->getCurrentDirective(),
23857 OMPVersion);
23858 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
23859 continue;
23860 }
23861 }
23862 }
23863
23864 // Try to find the associated user-defined mapper.
23866 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23867 Type.getCanonicalType(), UnresolvedMapper);
23868 if (ER.isInvalid())
23869 continue;
23870
23871 // If no user-defined mapper is found, we need to create an implicit one for
23872 // arrays/array-sections on structs that have members that have
23873 // user-defined mappers. This is needed to ensure that the mapper for the
23874 // member is invoked when mapping each element of the array/array-section.
23875 if (!ER.get()) {
23876 QualType BaseType;
23877
23879 BaseType = VE->getType().getCanonicalType();
23880 if (BaseType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
23881 const auto *OASE = cast<ArraySectionExpr>(VE->IgnoreParenImpCasts());
23882 QualType BType =
23884 QualType ElemType;
23885 if (const auto *ATy = BType->getAsArrayTypeUnsafe())
23886 ElemType = ATy->getElementType();
23887 else
23888 ElemType = BType->getPointeeType();
23889 BaseType = ElemType.getCanonicalType();
23890 }
23891 } else if (VE->getType()->isArrayType()) {
23892 const ArrayType *AT = VE->getType()->getAsArrayTypeUnsafe();
23893 const QualType ElemType = AT->getElementType();
23894 BaseType = ElemType.getCanonicalType();
23895 }
23896
23897 if (!BaseType.isNull() && BaseType->getAsRecordDecl() &&
23898 isImplicitMapperNeeded(SemaRef, DSAS, BaseType, VE)) {
23899 ER = buildImplicitMapper(SemaRef, BaseType, DSAS);
23900 }
23901 }
23902 MVLI.UDMapperList.push_back(ER.get());
23903
23904 // Save the current expression.
23905 MVLI.ProcessedVarList.push_back(RE);
23906
23907 // Store the components in the stack so that they can be used to check
23908 // against other clauses later on.
23909 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
23910 /*WhereFoundClauseKind=*/OMPC_map);
23911
23912 // Save the components and declaration to create the clause. For purposes of
23913 // the clause creation, any component list that has base 'this' uses
23914 // null as base declaration.
23915 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23916 MVLI.VarComponents.back().append(CurComponents.begin(),
23917 CurComponents.end());
23918 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
23919 : CurDeclaration);
23920 }
23921}
23922
23924 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
23925 ArrayRef<SourceLocation> MapTypeModifiersLoc,
23926 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23927 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
23928 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23929 const OMPVarListLocTy &Locs, bool NoDiagnose,
23930 ArrayRef<Expr *> UnresolvedMappers) {
23931 OpenMPMapModifierKind Modifiers[] = {
23937
23938 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
23939 BuiltinType::OMPIterator))
23940 Diag(IteratorModifier->getExprLoc(),
23941 diag::err_omp_map_modifier_not_iterator);
23942
23943 // Process map-type-modifiers, flag errors for duplicate modifiers.
23944 unsigned Count = 0;
23945 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
23946 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
23947 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
23948 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
23949 continue;
23950 }
23951 assert(Count < NumberOfOMPMapClauseModifiers &&
23952 "Modifiers exceed the allowed number of map type modifiers");
23953 Modifiers[Count] = MapTypeModifiers[I];
23954 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
23955 ++Count;
23956 }
23957
23958 MappableVarListInfo MVLI(VarList);
23959 // Per OpenMP 6.0 p299 lines 3-4, a list item with the const specifier and
23960 // no mutable members is ignored for 'from' clauses. A const-qualified
23961 // variable cannot be modified on the device, so copying back to the host
23962 // is unnecessary and potentially unsafe. Strip the FROM component:
23963 // map(tofrom:) -> map(to:), map(from:) -> map(alloc:).
23964 for (auto *E : VarList) {
23965 if ((MapType == OMPC_MAP_from || MapType == OMPC_MAP_tofrom) &&
23967 MapType = (MapType == OMPC_MAP_tofrom) ? OMPC_MAP_to : OMPC_MAP_alloc;
23968 }
23970 MapperIdScopeSpec, MapperId, UnresolvedMappers,
23971 MapType, Modifiers, IsMapTypeImplicit,
23972 NoDiagnose);
23973
23974 // We need to produce a map clause even if we don't have variables so that
23975 // other diagnostics related with non-existing map clauses are accurate.
23976 return OMPMapClause::Create(
23977 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23978 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
23979 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
23980 MapperId, MapType, IsMapTypeImplicit, MapLoc);
23981}
23982
23985 assert(ParsedType.isUsable());
23986
23987 QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get());
23988 if (ReductionType.isNull())
23989 return QualType();
23990
23991 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
23992 // A type name in a declare reduction directive cannot be a function type, an
23993 // array type, a reference type, or a type qualified with const, volatile or
23994 // restrict.
23995 if (ReductionType.hasQualifiers()) {
23996 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
23997 return QualType();
23998 }
23999
24000 if (ReductionType->isFunctionType()) {
24001 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
24002 return QualType();
24003 }
24004 if (ReductionType->isReferenceType()) {
24005 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
24006 return QualType();
24007 }
24008 if (ReductionType->isArrayType()) {
24009 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
24010 return QualType();
24011 }
24012 return ReductionType;
24013}
24014
24017 Scope *S, DeclContext *DC, DeclarationName Name,
24018 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
24019 AccessSpecifier AS, Decl *PrevDeclInScope) {
24021 Decls.reserve(ReductionTypes.size());
24022
24023 LookupResult Lookup(SemaRef, Name, SourceLocation(),
24025 SemaRef.forRedeclarationInCurContext());
24026 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
24027 // A reduction-identifier may not be re-declared in the current scope for the
24028 // same type or for a type that is compatible according to the base language
24029 // rules.
24030 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
24031 OMPDeclareReductionDecl *PrevDRD = nullptr;
24032 bool InCompoundScope = true;
24033 if (S != nullptr) {
24034 // Find previous declaration with the same name not referenced in other
24035 // declarations.
24036 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
24037 InCompoundScope =
24038 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
24039 SemaRef.LookupName(Lookup, S);
24040 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
24041 /*AllowInlineNamespace=*/false);
24042 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
24043 LookupResult::Filter Filter = Lookup.makeFilter();
24044 while (Filter.hasNext()) {
24045 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
24046 if (InCompoundScope) {
24047 UsedAsPrevious.try_emplace(PrevDecl, false);
24048 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
24049 UsedAsPrevious[D] = true;
24050 }
24051 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
24052 PrevDecl->getLocation();
24053 }
24054 Filter.done();
24055 if (InCompoundScope) {
24056 for (const auto &PrevData : UsedAsPrevious) {
24057 if (!PrevData.second) {
24058 PrevDRD = PrevData.first;
24059 break;
24060 }
24061 }
24062 }
24063 } else if (PrevDeclInScope != nullptr) {
24064 auto *PrevDRDInScope = PrevDRD =
24065 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
24066 do {
24067 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
24068 PrevDRDInScope->getLocation();
24069 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
24070 } while (PrevDRDInScope != nullptr);
24071 }
24072 for (const auto &TyData : ReductionTypes) {
24073 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
24074 bool Invalid = false;
24075 if (I != PreviousRedeclTypes.end()) {
24076 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
24077 << TyData.first;
24078 Diag(I->second, diag::note_previous_definition);
24079 Invalid = true;
24080 }
24081 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
24083 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
24084 DC->addDecl(DRD);
24085 DRD->setAccess(AS);
24086 Decls.push_back(DRD);
24087 if (Invalid)
24088 DRD->setInvalidDecl();
24089 else
24090 PrevDRD = DRD;
24091 }
24092
24093 return DeclGroupPtrTy::make(
24094 DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size()));
24095}
24096
24098 auto *DRD = cast<OMPDeclareReductionDecl>(D);
24099
24100 // Enter new function scope.
24101 SemaRef.PushFunctionScope();
24102 SemaRef.setFunctionHasBranchProtectedScope();
24103 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
24104
24105 if (S != nullptr)
24106 SemaRef.PushDeclContext(S, DRD);
24107 else
24108 SemaRef.CurContext = DRD;
24109
24110 SemaRef.PushExpressionEvaluationContext(
24112
24113 QualType ReductionType = DRD->getType();
24114 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
24115 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
24116 // uses semantics of argument handles by value, but it should be passed by
24117 // reference. C lang does not support references, so pass all parameters as
24118 // pointers.
24119 // Create 'T omp_in;' variable.
24120 VarDecl *OmpInParm =
24121 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in");
24122 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
24123 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
24124 // uses semantics of argument handles by value, but it should be passed by
24125 // reference. C lang does not support references, so pass all parameters as
24126 // pointers.
24127 // Create 'T omp_out;' variable.
24128 VarDecl *OmpOutParm =
24129 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out");
24130 if (S != nullptr) {
24131 SemaRef.PushOnScopeChains(OmpInParm, S);
24132 SemaRef.PushOnScopeChains(OmpOutParm, S);
24133 } else {
24134 DRD->addDecl(OmpInParm);
24135 DRD->addDecl(OmpOutParm);
24136 }
24137 Expr *InE =
24138 ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation());
24139 Expr *OutE =
24140 ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation());
24141 DRD->setCombinerData(InE, OutE);
24142}
24143
24145 Expr *Combiner) {
24146 auto *DRD = cast<OMPDeclareReductionDecl>(D);
24147 SemaRef.DiscardCleanupsInEvaluationContext();
24148 SemaRef.PopExpressionEvaluationContext();
24149
24150 SemaRef.PopDeclContext();
24151 SemaRef.PopFunctionScopeInfo();
24152
24153 if (Combiner != nullptr)
24154 DRD->setCombiner(Combiner);
24155 else
24156 DRD->setInvalidDecl();
24157}
24158
24160 Decl *D) {
24161 auto *DRD = cast<OMPDeclareReductionDecl>(D);
24162
24163 // Enter new function scope.
24164 SemaRef.PushFunctionScope();
24165 SemaRef.setFunctionHasBranchProtectedScope();
24166
24167 if (S != nullptr)
24168 SemaRef.PushDeclContext(S, DRD);
24169 else
24170 SemaRef.CurContext = DRD;
24171
24172 SemaRef.PushExpressionEvaluationContext(
24174
24175 QualType ReductionType = DRD->getType();
24176 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
24177 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
24178 // uses semantics of argument handles by value, but it should be passed by
24179 // reference. C lang does not support references, so pass all parameters as
24180 // pointers.
24181 // Create 'T omp_priv;' variable.
24182 VarDecl *OmpPrivParm =
24183 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv");
24184 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
24185 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
24186 // uses semantics of argument handles by value, but it should be passed by
24187 // reference. C lang does not support references, so pass all parameters as
24188 // pointers.
24189 // Create 'T omp_orig;' variable.
24190 VarDecl *OmpOrigParm =
24191 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig");
24192 if (S != nullptr) {
24193 SemaRef.PushOnScopeChains(OmpPrivParm, S);
24194 SemaRef.PushOnScopeChains(OmpOrigParm, S);
24195 } else {
24196 DRD->addDecl(OmpPrivParm);
24197 DRD->addDecl(OmpOrigParm);
24198 }
24199 Expr *OrigE =
24200 ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation());
24201 Expr *PrivE =
24202 ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation());
24203 DRD->setInitializerData(OrigE, PrivE);
24204 return OmpPrivParm;
24205}
24206
24208 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
24209 auto *DRD = cast<OMPDeclareReductionDecl>(D);
24210 SemaRef.DiscardCleanupsInEvaluationContext();
24211 SemaRef.PopExpressionEvaluationContext();
24212
24213 SemaRef.PopDeclContext();
24214 SemaRef.PopFunctionScopeInfo();
24215
24216 if (Initializer != nullptr) {
24217 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
24218 } else if (OmpPrivParm->hasInit()) {
24219 DRD->setInitializer(OmpPrivParm->getInit(),
24220 OmpPrivParm->isDirectInit()
24223 } else {
24224 DRD->setInvalidDecl();
24225 }
24226}
24227
24229 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
24230 for (Decl *D : DeclReductions.get()) {
24231 if (IsValid) {
24232 if (S)
24233 SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
24234 /*AddToContext=*/false);
24235 } else {
24236 D->setInvalidDecl();
24237 }
24238 }
24239 return DeclReductions;
24240}
24241
24243 Declarator &D) {
24244 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
24245 QualType T = TInfo->getType();
24246 if (D.isInvalidType())
24247 return true;
24248
24249 if (getLangOpts().CPlusPlus) {
24250 // Check that there are no default arguments (C++ only).
24251 SemaRef.CheckExtraCXXDefaultArguments(D);
24252 }
24253
24254 return SemaRef.CreateParsedType(T, TInfo);
24255}
24256
24259 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
24260
24261 QualType MapperType = SemaRef.GetTypeFromParser(ParsedType.get());
24262 assert(!MapperType.isNull() && "Expect valid mapper type");
24263
24264 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
24265 // The type must be of struct, union or class type in C and C++
24266 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
24267 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
24268 return QualType();
24269 }
24270 return MapperType;
24271}
24272
24274 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
24276 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
24277 LookupResult Lookup(SemaRef, Name, SourceLocation(),
24279 SemaRef.forRedeclarationInCurContext());
24280 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
24281 // A mapper-identifier may not be redeclared in the current scope for the
24282 // same type or for a type that is compatible according to the base language
24283 // rules.
24284 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
24285 OMPDeclareMapperDecl *PrevDMD = nullptr;
24286 bool InCompoundScope = true;
24287 if (S != nullptr) {
24288 // Find previous declaration with the same name not referenced in other
24289 // declarations.
24290 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
24291 InCompoundScope =
24292 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
24293 SemaRef.LookupName(Lookup, S);
24294 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
24295 /*AllowInlineNamespace=*/false);
24296 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
24297 LookupResult::Filter Filter = Lookup.makeFilter();
24298 while (Filter.hasNext()) {
24299 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
24300 if (InCompoundScope) {
24301 UsedAsPrevious.try_emplace(PrevDecl, false);
24302 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
24303 UsedAsPrevious[D] = true;
24304 }
24305 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
24306 PrevDecl->getLocation();
24307 }
24308 Filter.done();
24309 if (InCompoundScope) {
24310 for (const auto &PrevData : UsedAsPrevious) {
24311 if (!PrevData.second) {
24312 PrevDMD = PrevData.first;
24313 break;
24314 }
24315 }
24316 }
24317 } else if (PrevDeclInScope) {
24318 auto *PrevDMDInScope = PrevDMD =
24319 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
24320 do {
24321 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
24322 PrevDMDInScope->getLocation();
24323 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
24324 } while (PrevDMDInScope != nullptr);
24325 }
24326 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
24327 bool Invalid = false;
24328 if (I != PreviousRedeclTypes.end()) {
24329 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
24330 << MapperType << Name;
24331 Diag(I->second, diag::note_previous_definition);
24332 Invalid = true;
24333 }
24334 // Build expressions for implicit maps of data members with 'default'
24335 // mappers.
24336 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
24337 if (getLangOpts().OpenMP >= 50)
24339 ClausesWithImplicit);
24340 auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name,
24341 MapperType, VN, ClausesWithImplicit,
24342 PrevDMD);
24343 if (S)
24344 SemaRef.PushOnScopeChains(DMD, S);
24345 else
24346 DC->addDecl(DMD);
24347 DMD->setAccess(AS);
24348 if (Invalid)
24349 DMD->setInvalidDecl();
24350
24351 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
24352 VD->setDeclContext(DMD);
24353 VD->setLexicalDeclContext(DMD);
24354 DMD->addDecl(VD);
24355 DMD->setMapperVarRef(MapperVarRef);
24356
24358}
24359
24361 Scope *S, QualType MapperType, SourceLocation StartLoc,
24362 DeclarationName VN) {
24363 TypeSourceInfo *TInfo =
24364 getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc);
24365 auto *VD = VarDecl::Create(
24366 getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc,
24367 StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None);
24368 if (S)
24369 SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false);
24370 Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc);
24371 DSAStack->addDeclareMapperVarRef(E);
24372 return E;
24373}
24374
24376 bool IsGlobalVar =
24378 if (DSAStack->getDeclareMapperVarRef()) {
24379 if (IsGlobalVar)
24380 SemaRef.Consumer.HandleTopLevelDecl(DeclGroupRef(VD));
24381 DSAStack->addIteratorVarDecl(VD);
24382 } else {
24383 // Currently, only declare mapper handles global-scope iterator vars.
24384 assert(!IsGlobalVar && "Only declare mapper handles TU-scope iterators.");
24385 }
24386}
24387
24389 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
24390 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
24391 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
24392 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
24393 return true;
24395 return true;
24396 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
24397 return true;
24398 return false;
24399 }
24400 return true;
24401}
24402
24404 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
24405 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
24406}
24407
24410 Expr *ModifierExpr, SourceLocation ModifierLoc, SourceLocation StartLoc,
24411 SourceLocation LParenLoc, SourceLocation EndLoc) {
24412 if (VarList.empty())
24413 return nullptr;
24414
24415 for (Expr *ValExpr : VarList) {
24416 // OpenMP [teams Construct, Restrictions]
24417 // The num_teams expression must evaluate to a positive integer value.
24418 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams,
24419 /*StrictlyPositive=*/true))
24420 return nullptr;
24421 }
24422
24423 // OpenMP [teams Construct, Restrictions]
24424 // The lower-bound expression in num_teams must evaluate to a positive integer
24425 // value.
24426 if (ModifierExpr) {
24427 assert(Modifier == OMPC_NUMTEAMS_lower_bound && "Unexpected modifier.");
24428
24429 if (getLangOpts().OpenMP < 51) {
24430 Diag(ModifierLoc, diag::err_omp_modifier_requires_version)
24431 << getOpenMPSimpleClauseTypeName(llvm::omp::OMPC_num_teams, Modifier)
24432 << getOpenMPClauseName(llvm::omp::OMPC_num_teams) << "5.1";
24433 return nullptr;
24434 }
24435
24436 if (!isNonNegativeIntegerValue(ModifierExpr, SemaRef, OMPC_num_teams,
24437 /*StrictlyPositive=*/true))
24438 return nullptr;
24439
24440 // OpenMP 5.2: Validate lower-bound is less than or equal to upper-bound.
24441 Expr *LowerBound = ModifierExpr;
24442 Expr *UpperBound = VarList[0];
24443
24444 // Check if both are compile-time constants for validation.
24445 if (!LowerBound->isValueDependent() && !UpperBound->isValueDependent() &&
24446 LowerBound->isIntegerConstantExpr(getASTContext()) &&
24447 UpperBound->isIntegerConstantExpr(getASTContext())) {
24448
24449 // Get the actual constant values.
24450 llvm::APSInt LowerVal =
24451 LowerBound->EvaluateKnownConstInt(getASTContext());
24452 llvm::APSInt UpperVal =
24453 UpperBound->EvaluateKnownConstInt(getASTContext());
24454
24455 if (LowerVal > UpperVal) {
24456 Diag(LowerBound->getExprLoc(),
24457 diag::err_omp_num_teams_lower_bound_larger)
24458 << LowerBound->getSourceRange() << UpperBound->getSourceRange();
24459 return nullptr;
24460 }
24461 }
24462 }
24463
24464 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24466 DKind, OMPC_num_teams, getLangOpts().OpenMP);
24467 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
24468 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
24469 LParenLoc, EndLoc, VarList, Modifier,
24470 ModifierExpr, ModifierLoc,
24471 /*PreInit=*/nullptr);
24472
24473 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24475 for (Expr *ValExpr : VarList) {
24476 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
24477 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
24478 Vars.push_back(ValExpr);
24479 }
24480
24481 if (ModifierExpr) {
24482 ModifierExpr = SemaRef.MakeFullExpr(ModifierExpr).get();
24483 ModifierExpr = tryBuildCapture(SemaRef, ModifierExpr, Captures).get();
24484 }
24485
24486 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
24487 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
24488 LParenLoc, EndLoc, Vars, Modifier,
24489 ModifierExpr, ModifierLoc, PreInit);
24490}
24491
24493 SourceLocation StartLoc,
24494 SourceLocation LParenLoc,
24495 SourceLocation EndLoc) {
24496 if (VarList.empty())
24497 return nullptr;
24498
24499 for (Expr *ValExpr : VarList) {
24500 // OpenMP [teams Constrcut, Restrictions]
24501 // The thread_limit expression must evaluate to a positive integer value.
24502 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit,
24503 /*StrictlyPositive=*/true))
24504 return nullptr;
24505 }
24506
24507 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24509 DKind, OMPC_thread_limit, getLangOpts().OpenMP);
24510 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
24511 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion,
24512 StartLoc, LParenLoc, EndLoc, VarList,
24513 /*PreInit=*/nullptr);
24514
24515 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24517 for (Expr *ValExpr : VarList) {
24518 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
24519 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
24520 Vars.push_back(ValExpr);
24521 }
24522
24523 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
24524 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion, StartLoc,
24525 LParenLoc, EndLoc, Vars, PreInit);
24526}
24527
24529 SourceLocation StartLoc,
24530 SourceLocation LParenLoc,
24531 SourceLocation EndLoc) {
24532 Expr *ValExpr = Priority;
24533 Stmt *HelperValStmt = nullptr;
24534 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
24535
24536 // OpenMP [2.9.1, task Constrcut]
24537 // The priority-value is a non-negative numerical scalar expression.
24539 ValExpr, SemaRef, OMPC_priority,
24540 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
24541 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
24542 return nullptr;
24543
24544 return new (getASTContext()) OMPPriorityClause(
24545 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
24546}
24547
24549 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
24550 SourceLocation StartLoc, SourceLocation LParenLoc,
24551 SourceLocation ModifierLoc, SourceLocation EndLoc) {
24552 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
24553 "Unexpected grainsize modifier in OpenMP < 51.");
24554
24555 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
24556 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
24558 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
24559 << Values << getOpenMPClauseNameForDiag(OMPC_grainsize);
24560 return nullptr;
24561 }
24562
24563 Expr *ValExpr = Grainsize;
24564 Stmt *HelperValStmt = nullptr;
24565 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
24566
24567 // OpenMP [2.9.2, taskloop Constrcut]
24568 // The parameter of the grainsize clause must be a positive integer
24569 // expression.
24570 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize,
24571 /*StrictlyPositive=*/true,
24572 /*BuildCapture=*/true,
24573 DSAStack->getCurrentDirective(),
24574 &CaptureRegion, &HelperValStmt))
24575 return nullptr;
24576
24577 return new (getASTContext())
24578 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
24579 StartLoc, LParenLoc, ModifierLoc, EndLoc);
24580}
24581
24583 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
24584 SourceLocation StartLoc, SourceLocation LParenLoc,
24585 SourceLocation ModifierLoc, SourceLocation EndLoc) {
24586 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
24587 "Unexpected num_tasks modifier in OpenMP < 51.");
24588
24589 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
24590 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
24592 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
24593 << Values << getOpenMPClauseNameForDiag(OMPC_num_tasks);
24594 return nullptr;
24595 }
24596
24597 Expr *ValExpr = NumTasks;
24598 Stmt *HelperValStmt = nullptr;
24599 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
24600
24601 // OpenMP [2.9.2, taskloop Constrcut]
24602 // The parameter of the num_tasks clause must be a positive integer
24603 // expression.
24605 ValExpr, SemaRef, OMPC_num_tasks,
24606 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
24607 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
24608 return nullptr;
24609
24610 return new (getASTContext())
24611 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
24612 StartLoc, LParenLoc, ModifierLoc, EndLoc);
24613}
24614
24616 SourceLocation StartLoc,
24617 SourceLocation LParenLoc,
24618 SourceLocation EndLoc) {
24619 // OpenMP [2.13.2, critical construct, Description]
24620 // ... where hint-expression is an integer constant expression that evaluates
24621 // to a valid lock hint.
24622 ExprResult HintExpr =
24623 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
24624 if (HintExpr.isInvalid())
24625 return nullptr;
24626 return new (getASTContext())
24627 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
24628}
24629
24630/// Tries to find omp_event_handle_t type.
24632 DSAStackTy *Stack) {
24633 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
24634 if (!OMPEventHandleT.isNull())
24635 return true;
24636 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
24637 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
24638 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
24639 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
24640 return false;
24641 }
24642 Stack->setOMPEventHandleT(PT.get());
24643 return true;
24644}
24645
24647 SourceLocation StartLoc,
24648 SourceLocation LParenLoc,
24649 SourceLocation EndLoc) {
24650 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
24651 !Evt->isInstantiationDependent() &&
24654 return nullptr;
24655 // OpenMP 5.0, 2.10.1 task Construct.
24656 // event-handle is a variable of the omp_event_handle_t type.
24657 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
24658 if (!Ref) {
24659 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
24660 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
24661 return nullptr;
24662 }
24663 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
24664 if (!VD) {
24665 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
24666 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
24667 return nullptr;
24668 }
24669 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
24670 VD->getType()) ||
24671 VD->getType().isConstant(getASTContext())) {
24672 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
24673 << "omp_event_handle_t" << 1 << VD->getType()
24674 << Evt->getSourceRange();
24675 return nullptr;
24676 }
24677 // OpenMP 5.0, 2.10.1 task Construct
24678 // [detach clause]... The event-handle will be considered as if it was
24679 // specified on a firstprivate clause.
24680 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
24681 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
24682 DVar.RefExpr) {
24683 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
24684 << getOpenMPClauseNameForDiag(DVar.CKind)
24685 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
24687 return nullptr;
24688 }
24689 }
24690
24691 return new (getASTContext())
24692 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
24693}
24694
24696 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
24697 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
24698 SourceLocation EndLoc) {
24699 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
24700 std::string Values;
24701 Values += "'";
24702 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
24703 Values += "'";
24704 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24705 << Values << getOpenMPClauseNameForDiag(OMPC_dist_schedule);
24706 return nullptr;
24707 }
24708 Expr *ValExpr = ChunkSize;
24709 Stmt *HelperValStmt = nullptr;
24710 if (ChunkSize) {
24711 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
24712 !ChunkSize->isInstantiationDependent() &&
24713 !ChunkSize->containsUnexpandedParameterPack()) {
24714 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
24715 ExprResult Val =
24716 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
24717 if (Val.isInvalid())
24718 return nullptr;
24719
24720 ValExpr = Val.get();
24721
24722 // OpenMP [2.7.1, Restrictions]
24723 // chunk_size must be a loop invariant integer expression with a positive
24724 // value.
24725 if (std::optional<llvm::APSInt> Result =
24727 if (Result->isSigned() && !Result->isStrictlyPositive()) {
24728 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
24729 << "dist_schedule" << /*strictly positive*/ 1
24730 << ChunkSize->getSourceRange();
24731 return nullptr;
24732 }
24734 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
24735 getLangOpts().OpenMP) != OMPD_unknown &&
24736 !SemaRef.CurContext->isDependentContext()) {
24737 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
24738 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24739 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
24740 HelperValStmt = buildPreInits(getASTContext(), Captures);
24741 }
24742 }
24743 }
24744
24745 return new (getASTContext())
24746 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
24747 Kind, ValExpr, HelperValStmt);
24748}
24749
24752 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
24753 SourceLocation KindLoc, SourceLocation EndLoc) {
24754 if (getLangOpts().OpenMP < 50) {
24755 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
24756 Kind != OMPC_DEFAULTMAP_scalar) {
24757 std::string Value;
24758 SourceLocation Loc;
24759 Value += "'";
24760 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
24761 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
24762 OMPC_DEFAULTMAP_MODIFIER_tofrom);
24763 Loc = MLoc;
24764 } else {
24765 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
24766 OMPC_DEFAULTMAP_scalar);
24767 Loc = KindLoc;
24768 }
24769 Value += "'";
24770 Diag(Loc, diag::err_omp_unexpected_clause_value)
24771 << Value << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24772 return nullptr;
24773 }
24774 } else {
24775 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
24776 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
24777 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
24778 if (!isDefaultmapKind || !isDefaultmapModifier) {
24779 StringRef KindValue = getLangOpts().OpenMP < 52
24780 ? "'scalar', 'aggregate', 'pointer'"
24781 : "'scalar', 'aggregate', 'pointer', 'all'";
24782 if (getLangOpts().OpenMP == 50) {
24783 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
24784 "'firstprivate', 'none', 'default'";
24785 if (!isDefaultmapKind && isDefaultmapModifier) {
24786 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24787 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24788 } else if (isDefaultmapKind && !isDefaultmapModifier) {
24789 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24790 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24791 } else {
24792 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24793 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24794 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24795 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24796 }
24797 } else {
24798 StringRef ModifierValue =
24799 getLangOpts().OpenMP < 60
24800 ? "'alloc', 'from', 'to', 'tofrom', "
24801 "'firstprivate', 'none', 'default', 'present'"
24802 : "'storage', 'from', 'to', 'tofrom', "
24803 "'firstprivate', 'private', 'none', 'default', 'present'";
24804 if (!isDefaultmapKind && isDefaultmapModifier) {
24805 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24806 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24807 } else if (isDefaultmapKind && !isDefaultmapModifier) {
24808 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24809 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24810 } else {
24811 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24812 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24813 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24814 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24815 }
24816 }
24817 return nullptr;
24818 }
24819
24820 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
24821 // At most one defaultmap clause for each category can appear on the
24822 // directive.
24823 if (DSAStack->checkDefaultmapCategory(Kind)) {
24824 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
24825 return nullptr;
24826 }
24827 }
24828 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
24829 // Variable category is not specified - mark all categories.
24830 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
24831 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
24832 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
24833 } else {
24834 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
24835 }
24836
24837 return new (getASTContext())
24838 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
24839}
24840
24843 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
24844 if (!CurLexicalContext->isFileContext() &&
24845 !CurLexicalContext->isExternCContext() &&
24846 !CurLexicalContext->isExternCXXContext() &&
24847 !isa<CXXRecordDecl>(CurLexicalContext) &&
24848 !isa<ClassTemplateDecl>(CurLexicalContext) &&
24849 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
24850 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
24851 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
24852 return false;
24853 }
24854
24855 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
24856 if (getLangOpts().HIP)
24857 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
24858
24859 DeclareTargetNesting.push_back(DTCI);
24860 return true;
24861}
24862
24865 assert(!DeclareTargetNesting.empty() &&
24866 "check isInOpenMPDeclareTargetContext() first!");
24867 return DeclareTargetNesting.pop_back_val();
24868}
24869
24872 for (auto &It : DTCI.ExplicitlyMapped)
24873 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
24874}
24875
24877 if (DeclareTargetNesting.empty())
24878 return;
24879 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
24880 unsigned OMPVersion = getLangOpts().OpenMP;
24881 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
24882 << getOpenMPDirectiveName(DTCI.Kind, OMPVersion);
24883}
24884
24886 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
24888 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
24889 /*ObjectType=*/QualType(),
24890 /*AllowBuiltinCreation=*/true);
24891
24892 if (Lookup.isAmbiguous())
24893 return nullptr;
24894 Lookup.suppressDiagnostics();
24895
24896 if (!Lookup.isSingleResult()) {
24897 VarOrFuncDeclFilterCCC CCC(SemaRef);
24898 if (TypoCorrection Corrected =
24899 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
24901 SemaRef.diagnoseTypo(Corrected,
24902 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
24903 << Id.getName());
24904 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
24905 return nullptr;
24906 }
24907
24908 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
24909 return nullptr;
24910 }
24911
24912 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
24913 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
24915 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
24916 return nullptr;
24917 }
24918 return ND;
24919}
24920
24922 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
24924 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
24926 "Expected variable, function or function template.");
24927
24928 if (auto *VD = dyn_cast<VarDecl>(ND)) {
24929 // Only global variables can be marked as declare target.
24930 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24931 !VD->isStaticDataMember()) {
24932 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
24933 << VD->getNameAsString();
24934 return;
24935 }
24936 }
24937 // Diagnose marking after use as it may lead to incorrect diagnosis and
24938 // codegen.
24939 if (getLangOpts().OpenMP >= 50 &&
24940 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
24941 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
24942
24943 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
24944 if (getLangOpts().HIP)
24945 Diag(Loc, diag::warn_hip_omp_target_directives);
24946
24947 // 'local' is incompatible with 'device_type(host)' because 'local'
24948 // variables exist only on the device.
24949 if (MT == OMPDeclareTargetDeclAttr::MT_Local &&
24950 DTCI.DT == OMPDeclareTargetDeclAttr::DT_Host) {
24951 Diag(Loc, diag::err_omp_declare_target_local_host_only);
24952 return;
24953 }
24954
24955 // Explicit declare target lists have precedence.
24956 const unsigned Level = -1;
24957
24958 auto *VD = cast<ValueDecl>(ND);
24959 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24960 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24961 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
24962 (*ActiveAttr)->getLevel() == Level) {
24963 Diag(Loc, diag::err_omp_device_type_mismatch)
24964 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
24965 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
24966 (*ActiveAttr)->getDevType());
24967 return;
24968 }
24969 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
24970 (*ActiveAttr)->getLevel() == Level) {
24971 Diag(Loc, diag::err_omp_declare_target_var_in_both_clauses)
24972 << ND
24973 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(
24974 (*ActiveAttr)->getMapType())
24975 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(MT);
24976 return;
24977 }
24978
24979 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
24980 return;
24981
24982 Expr *IndirectE = nullptr;
24983 bool IsIndirect = false;
24984 if (DTCI.Indirect) {
24985 IndirectE = *DTCI.Indirect;
24986 if (!IndirectE)
24987 IsIndirect = true;
24988 }
24989 // FIXME: 'local' with 'device_type(nohost)' is not yet fully supported
24990 // in codegen. Treat as 'device_type(any)' for now. The variable will
24991 // exist on both host and device, but the host copy is unused.
24992 auto DT = DTCI.DT;
24993 if (MT == OMPDeclareTargetDeclAttr::MT_Local &&
24994 DT == OMPDeclareTargetDeclAttr::DT_NoHost) {
24995 Diag(Loc, diag::warn_omp_declare_target_local_nohost);
24996 DT = OMPDeclareTargetDeclAttr::DT_Any;
24997 }
24998
24999 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
25000 getASTContext(), MT, DT, IndirectE, IsIndirect, Level,
25001 SourceRange(Loc, Loc));
25002 ND->addAttr(A);
25003 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
25004 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
25005 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
25006 if (auto *VD = dyn_cast<VarDecl>(ND);
25007 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
25008 VD->hasGlobalStorage())
25010}
25011
25013 Sema &SemaRef, Decl *D) {
25014 if (!D || !isa<VarDecl>(D))
25015 return;
25016 auto *VD = cast<VarDecl>(D);
25017 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
25018 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
25019 if (SemaRef.LangOpts.OpenMP >= 50 &&
25020 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
25021 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
25022 VD->hasGlobalStorage()) {
25023 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
25024 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter &&
25025 *MapTy != OMPDeclareTargetDeclAttr::MT_Local)) {
25026 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
25027 // If a lambda declaration and definition appears between a
25028 // declare target directive and the matching end declare target
25029 // directive, all variables that are captured by the lambda
25030 // expression must also appear in a to clause.
25031 SemaRef.Diag(VD->getLocation(),
25032 diag::err_omp_lambda_capture_in_declare_target_not_to);
25033 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
25034 << VD << 0 << SR;
25035 return;
25036 }
25037 }
25038 if (MapTy)
25039 return;
25040 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
25041 SemaRef.Diag(SL, diag::note_used_here) << SR;
25042}
25043
25045 Sema &SemaRef, DSAStackTy *Stack,
25046 ValueDecl *VD) {
25047 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
25048 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
25049 /*FullCheck=*/false);
25050}
25051
25053 SourceLocation IdLoc) {
25054 if (!D || D->isInvalidDecl())
25055 return;
25056 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
25057 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
25058 if (auto *VD = dyn_cast<VarDecl>(D)) {
25059 // Only global variables can be marked as declare target.
25060 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
25061 !VD->isStaticDataMember())
25062 return;
25063 // 2.10.6: threadprivate variable cannot appear in a declare target
25064 // directive.
25065 if (DSAStack->isThreadPrivate(VD)) {
25066 Diag(SL, diag::err_omp_threadprivate_in_target);
25067 reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false));
25068 return;
25069 }
25070 }
25071 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
25072 D = FTD->getTemplatedDecl();
25073 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
25074 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
25075 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
25076 if (IdLoc.isValid() && Res &&
25077 (*Res == OMPDeclareTargetDeclAttr::MT_Link ||
25078 *Res == OMPDeclareTargetDeclAttr::MT_Local)) {
25079 Diag(IdLoc, diag::err_omp_function_in_target_clause_list)
25080 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(*Res);
25081 Diag(FD->getLocation(), diag::note_defined_here) << FD;
25082 return;
25083 }
25084 }
25085 if (auto *VD = dyn_cast<ValueDecl>(D)) {
25086 // Problem if any with var declared with incomplete type will be reported
25087 // as normal, so no need to check it here.
25088 if ((E || !VD->getType()->isIncompleteType()) &&
25090 return;
25091 if (!E && isInOpenMPDeclareTargetContext()) {
25092 // Checking declaration inside declare target region.
25093 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
25095 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
25096 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
25097 unsigned Level = DeclareTargetNesting.size();
25098 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
25099 return;
25100 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
25101 Expr *IndirectE = nullptr;
25102 bool IsIndirect = false;
25103 if (DTCI.Indirect) {
25104 IndirectE = *DTCI.Indirect;
25105 if (!IndirectE)
25106 IsIndirect = true;
25107 }
25108 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
25109 getASTContext(),
25110 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
25111 : OMPDeclareTargetDeclAttr::MT_To,
25112 DTCI.DT, IndirectE, IsIndirect, Level,
25113 SourceRange(DTCI.Loc, DTCI.Loc));
25114 D->addAttr(A);
25115 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
25116 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
25117 }
25118 return;
25119 }
25120 }
25121 if (!E)
25122 return;
25124}
25125
25126/// This class visits every VarDecl that the initializer references and adds
25127/// OMPDeclareTargetDeclAttr to each of them.
25128class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
25129 SmallVector<VarDecl *> DeclVector;
25130 Attr *A;
25131
25132public:
25133 /// A StmtVisitor class function that visits all DeclRefExpr and adds
25134 /// OMPDeclareTargetDeclAttr to them.
25136 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
25137 VD->addAttr(A);
25138 DeclVector.push_back(VD);
25139 }
25140 }
25141 /// A function that iterates across each of the Expr's children.
25142 void VisitExpr(Expr *Ex) {
25143 for (auto *Child : Ex->children()) {
25144 Visit(Child);
25145 }
25146 }
25147 /// A function that keeps a record of all the Decls that are variables, has
25148 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
25149 /// each Decl one at a time and use the inherited 'visit' functions to look
25150 /// for DeclRefExpr.
25152 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
25153 DeclVector.push_back(cast<VarDecl>(TD));
25154 llvm::SmallDenseSet<Decl *> Visited;
25155 while (!DeclVector.empty()) {
25156 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
25157 if (!Visited.insert(TargetVarDecl).second)
25158 continue;
25159
25160 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
25161 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
25162 if (Expr *Ex = TargetVarDecl->getInit())
25163 Visit(Ex);
25164 }
25165 }
25166 }
25167};
25168
25169/// Adding OMPDeclareTargetDeclAttr to variables with static storage
25170/// duration that are referenced in the initializer expression list of
25171/// variables with static storage duration in declare target directive.
25173 GlobalDeclRefChecker Checker;
25174 if (isa<VarDecl>(TargetDecl))
25175 Checker.declareTargetInitializer(TargetDecl);
25176}
25177
25179 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
25180 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
25181 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
25182 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
25183 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
25188
25189 // Process motion-modifiers, flag errors for duplicate modifiers.
25190 unsigned Count = 0;
25191 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
25192 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
25193 llvm::is_contained(Modifiers, MotionModifiers[I])) {
25194 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
25195 continue;
25196 }
25197 assert(Count < NumberOfOMPMotionModifiers &&
25198 "Modifiers exceed the allowed number of motion modifiers");
25199 Modifiers[Count] = MotionModifiers[I];
25200 ModifiersLoc[Count] = MotionModifiersLoc[I];
25201 ++Count;
25202 }
25203
25204 MappableVarListInfo MVLI(VarList);
25206 MapperIdScopeSpec, MapperId, UnresolvedMappers);
25207 if (MVLI.ProcessedVarList.empty())
25208 return nullptr;
25209 if (IteratorExpr)
25210 if (auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
25211 if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
25212 DSAStack->addIteratorVarDecl(VD);
25213 return OMPToClause::Create(
25214 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
25215 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
25216 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
25217 MapperId);
25218}
25219
25221 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
25222 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
25223 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
25224 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
25225 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
25230
25231 // Process motion-modifiers, flag errors for duplicate modifiers.
25232 unsigned Count = 0;
25233 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
25234 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
25235 llvm::is_contained(Modifiers, MotionModifiers[I])) {
25236 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
25237 continue;
25238 }
25239 assert(Count < NumberOfOMPMotionModifiers &&
25240 "Modifiers exceed the allowed number of motion modifiers");
25241 Modifiers[Count] = MotionModifiers[I];
25242 ModifiersLoc[Count] = MotionModifiersLoc[I];
25243 ++Count;
25244 }
25245
25246 MappableVarListInfo MVLI(VarList);
25247 checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
25248 MapperIdScopeSpec, MapperId, UnresolvedMappers);
25249 if (MVLI.ProcessedVarList.empty())
25250 return nullptr;
25251 if (IteratorExpr)
25252 if (auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
25253 if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
25254 DSAStack->addIteratorVarDecl(VD);
25255 return OMPFromClause::Create(
25256 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
25257 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
25258 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
25259 MapperId);
25260}
25261
25263 ArrayRef<Expr *> VarList, const OMPVarListLocTy &Locs,
25264 OpenMPUseDevicePtrFallbackModifier FallbackModifier,
25265 SourceLocation FallbackModifierLoc) {
25266 MappableVarListInfo MVLI(VarList);
25267 SmallVector<Expr *, 8> PrivateCopies;
25269
25270 for (Expr *RefExpr : VarList) {
25271 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
25272 SourceLocation ELoc;
25273 SourceRange ERange;
25274 Expr *SimpleRefExpr = RefExpr;
25275 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
25276 if (Res.second) {
25277 // It will be analyzed later.
25278 MVLI.ProcessedVarList.push_back(RefExpr);
25279 PrivateCopies.push_back(nullptr);
25280 Inits.push_back(nullptr);
25281 }
25282 ValueDecl *D = Res.first;
25283 if (!D)
25284 continue;
25285
25286 QualType Type = D->getType();
25287 Type = Type.getNonReferenceType().getUnqualifiedType();
25288
25289 auto *VD = dyn_cast<VarDecl>(D);
25290
25291 // Item should be a pointer or reference to pointer.
25292 if (!Type->isPointerType()) {
25293 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
25294 << 0 << RefExpr->getSourceRange();
25295 continue;
25296 }
25297
25298 // Build the private variable and the expression that refers to it.
25299 auto VDPrivate =
25300 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
25301 D->hasAttrs() ? &D->getAttrs() : nullptr,
25302 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
25303 if (VDPrivate->isInvalidDecl())
25304 continue;
25305
25306 SemaRef.CurContext->addDecl(VDPrivate);
25307 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
25308 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
25309
25310 // Add temporary variable to initialize the private copy of the pointer.
25311 VarDecl *VDInit =
25312 buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp");
25313 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
25314 SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
25315 SemaRef.AddInitializerToDecl(
25316 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
25317 /*DirectInit=*/false);
25318
25319 // If required, build a capture to implement the privatization initialized
25320 // with the current list item value.
25321 DeclRefExpr *Ref = nullptr;
25322 if (!VD)
25323 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
25324 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
25325 PrivateCopies.push_back(VDPrivateRefExpr);
25326 Inits.push_back(VDInitRefExpr);
25327
25328 // We need to add a data sharing attribute for this variable to make sure it
25329 // is correctly captured. A variable that shows up in a use_device_ptr has
25330 // similar properties of a first private variable.
25331 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
25332
25333 // Create a mappable component for the list item. List items in this clause
25334 // only need a component.
25335 MVLI.VarBaseDeclarations.push_back(D);
25336 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
25337 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
25338 /*IsNonContiguous=*/false);
25339 }
25340
25341 if (MVLI.ProcessedVarList.empty())
25342 return nullptr;
25343
25345 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
25346 MVLI.VarBaseDeclarations, MVLI.VarComponents, FallbackModifier,
25347 FallbackModifierLoc);
25348}
25349
25350OMPClause *
25352 const OMPVarListLocTy &Locs) {
25353 MappableVarListInfo MVLI(VarList);
25354
25355 for (Expr *RefExpr : VarList) {
25356 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
25357 SourceLocation ELoc;
25358 SourceRange ERange;
25359 Expr *SimpleRefExpr = RefExpr;
25360 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
25361 /*AllowArraySection=*/true,
25362 /*AllowAssumedSizeArray=*/true);
25363 if (Res.second) {
25364 // It will be analyzed later.
25365 MVLI.ProcessedVarList.push_back(RefExpr);
25366 }
25367 ValueDecl *D = Res.first;
25368 if (!D)
25369 continue;
25370 auto *VD = dyn_cast<VarDecl>(D);
25371
25372 // If required, build a capture to implement the privatization initialized
25373 // with the current list item value.
25374 DeclRefExpr *Ref = nullptr;
25375 if (!VD)
25376 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
25377 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
25378
25379 // We need to add a data sharing attribute for this variable to make sure it
25380 // is correctly captured. A variable that shows up in a use_device_addr has
25381 // similar properties of a first private variable.
25382 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
25383
25384 // Use the map-like approach to fully populate VarComponents
25386
25388 SemaRef, RefExpr, CurComponents, OMPC_use_device_addr,
25389 DSAStack->getCurrentDirective(),
25390 /*NoDiagnose=*/false);
25391
25392 if (!BE)
25393 continue;
25394
25395 assert(!CurComponents.empty() &&
25396 "use_device_addr clause expression with no components!");
25397
25398 // OpenMP use_device_addr: If a list item is an array section, the array
25399 // base must be a base language identifier. We caught the cases where
25400 // the array-section has a base-variable in getPrivateItem. e.g.
25401 // struct S {
25402 // int a[10];
25403 // }; S s1;
25404 // ... use_device_addr(s1.a[0]) // not ok, caught already
25405 //
25406 // But we still neeed to verify that the base-pointer is also a
25407 // base-language identifier, and catch cases like:
25408 // int *pa[10]; *p;
25409 // ... use_device_addr(pa[1][2]) // not ok, base-pointer is pa[1]
25410 // ... use_device_addr(p[1]) // ok
25411 // ... use_device_addr(this->p[1]) // ok
25413 CurComponents, DSAStack->getCurrentDirective());
25414 const Expr *AttachPtrExpr = AttachPtrResult.first;
25415
25416 if (AttachPtrExpr) {
25417 const Expr *BaseExpr = AttachPtrExpr->IgnoreParenImpCasts();
25418 bool IsValidBase = false;
25419
25420 if (isa<DeclRefExpr>(BaseExpr))
25421 IsValidBase = true;
25422 else if (const auto *ME = dyn_cast<MemberExpr>(BaseExpr);
25424 IsValidBase = true;
25425
25426 if (!IsValidBase) {
25427 SemaRef.Diag(ELoc,
25428 diag::err_omp_expected_base_pointer_var_name_member_expr)
25429 << (SemaRef.getCurrentThisType().isNull() ? 0 : 1)
25430 << AttachPtrExpr->getSourceRange();
25431 continue;
25432 }
25433 }
25434
25435 // Get the declaration from the components
25436 ValueDecl *CurDeclaration = CurComponents.back().getAssociatedDeclaration();
25437 assert((isa<CXXThisExpr>(BE) || CurDeclaration) &&
25438 "Unexpected null decl for use_device_addr clause.");
25439
25440 MVLI.VarBaseDeclarations.push_back(CurDeclaration);
25441 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
25442 MVLI.VarComponents.back().append(CurComponents.begin(),
25443 CurComponents.end());
25444 }
25445
25446 if (MVLI.ProcessedVarList.empty())
25447 return nullptr;
25448
25450 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
25451 MVLI.VarComponents);
25452}
25453
25454OMPClause *
25456 const OMPVarListLocTy &Locs) {
25457 MappableVarListInfo MVLI(VarList);
25458 for (Expr *RefExpr : VarList) {
25459 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
25460 SourceLocation ELoc;
25461 SourceRange ERange;
25462 Expr *SimpleRefExpr = RefExpr;
25463 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
25464 if (Res.second) {
25465 // It will be analyzed later.
25466 MVLI.ProcessedVarList.push_back(RefExpr);
25467 }
25468 ValueDecl *D = Res.first;
25469 if (!D)
25470 continue;
25471
25472 QualType Type = D->getType();
25473 // item should be a pointer or array or reference to pointer or array
25474 if (!Type.getNonReferenceType()->isPointerType() &&
25475 !Type.getNonReferenceType()->isArrayType()) {
25476 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
25477 << 0 << RefExpr->getSourceRange();
25478 continue;
25479 }
25480
25481 // Check if the declaration in the clause does not show up in any data
25482 // sharing attribute.
25483 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
25484 if (isOpenMPPrivate(DVar.CKind)) {
25485 unsigned OMPVersion = getLangOpts().OpenMP;
25486 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
25487 << getOpenMPClauseNameForDiag(DVar.CKind)
25488 << getOpenMPClauseNameForDiag(OMPC_is_device_ptr)
25489 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
25490 OMPVersion);
25492 continue;
25493 }
25494
25495 const Expr *ConflictExpr;
25496 if (DSAStack->checkMappableExprComponentListsForDecl(
25497 D, /*CurrentRegionOnly=*/true,
25498 [&ConflictExpr](
25500 OpenMPClauseKind) -> bool {
25501 ConflictExpr = R.front().getAssociatedExpression();
25502 return true;
25503 })) {
25504 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
25505 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
25506 << ConflictExpr->getSourceRange();
25507 continue;
25508 }
25509
25510 // Store the components in the stack so that they can be used to check
25511 // against other clauses later on.
25513 SimpleRefExpr, D, /*IsNonContiguous=*/false);
25514 DSAStack->addMappableExpressionComponents(
25515 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
25516
25517 // Record the expression we've just processed.
25518 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
25519
25520 // Create a mappable component for the list item. List items in this clause
25521 // only need a component. We use a null declaration to signal fields in
25522 // 'this'.
25523 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
25524 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
25525 "Unexpected device pointer expression!");
25526 MVLI.VarBaseDeclarations.push_back(
25527 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
25528 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
25529 MVLI.VarComponents.back().push_back(MC);
25530 }
25531
25532 if (MVLI.ProcessedVarList.empty())
25533 return nullptr;
25534
25536 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
25537 MVLI.VarComponents);
25538}
25539
25540OMPClause *
25542 const OMPVarListLocTy &Locs) {
25543 MappableVarListInfo MVLI(VarList);
25544 for (Expr *RefExpr : VarList) {
25545 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
25546 SourceLocation ELoc;
25547 SourceRange ERange;
25548 Expr *SimpleRefExpr = RefExpr;
25549 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
25550 /*AllowArraySection=*/true);
25551 if (Res.second) {
25552 // It will be analyzed later.
25553 MVLI.ProcessedVarList.push_back(RefExpr);
25554 }
25555 ValueDecl *D = Res.first;
25556 if (!D)
25557 continue;
25558
25559 // Check if the declaration in the clause does not show up in any data
25560 // sharing attribute.
25561 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
25562 if (isOpenMPPrivate(DVar.CKind)) {
25563 unsigned OMPVersion = getLangOpts().OpenMP;
25564 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
25565 << getOpenMPClauseNameForDiag(DVar.CKind)
25566 << getOpenMPClauseNameForDiag(OMPC_has_device_addr)
25567 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
25568 OMPVersion);
25570 continue;
25571 }
25572
25573 const Expr *ConflictExpr;
25574 if (DSAStack->checkMappableExprComponentListsForDecl(
25575 D, /*CurrentRegionOnly=*/true,
25576 [&ConflictExpr](
25578 OpenMPClauseKind) -> bool {
25579 ConflictExpr = R.front().getAssociatedExpression();
25580 return true;
25581 })) {
25582 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
25583 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
25584 << ConflictExpr->getSourceRange();
25585 continue;
25586 }
25587
25588 // Store the components in the stack so that they can be used to check
25589 // against other clauses later on.
25590 Expr *Component = SimpleRefExpr;
25591 auto *VD = dyn_cast<VarDecl>(D);
25592 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
25593 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
25594 Component =
25595 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
25597 Component, D, /*IsNonContiguous=*/false);
25598 DSAStack->addMappableExpressionComponents(
25599 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
25600
25601 // Record the expression we've just processed.
25602 if (!VD && !SemaRef.CurContext->isDependentContext()) {
25603 DeclRefExpr *Ref =
25604 buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
25605 assert(Ref && "has_device_addr capture failed");
25606 MVLI.ProcessedVarList.push_back(Ref);
25607 } else
25608 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
25609
25610 // Create a mappable component for the list item. List items in this clause
25611 // only need a component. We use a null declaration to signal fields in
25612 // 'this'.
25613 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
25614 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
25615 "Unexpected device pointer expression!");
25616 MVLI.VarBaseDeclarations.push_back(
25617 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
25618 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
25619 MVLI.VarComponents.back().push_back(MC);
25620 }
25621
25622 if (MVLI.ProcessedVarList.empty())
25623 return nullptr;
25624
25626 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
25627 MVLI.VarComponents);
25628}
25629
25631 Expr *Allocator, Expr *Alignment,
25632 OpenMPAllocateClauseModifier FirstAllocateModifier,
25633 SourceLocation FirstAllocateModifierLoc,
25634 OpenMPAllocateClauseModifier SecondAllocateModifier,
25635 SourceLocation SecondAllocateModifierLoc, ArrayRef<Expr *> VarList,
25636 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
25637 SourceLocation EndLoc) {
25638 if (Allocator) {
25639 // Allocator expression is dependent - skip it for now and build the
25640 // allocator when instantiated.
25641 bool AllocDependent =
25642 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
25643 Allocator->isInstantiationDependent() ||
25644 Allocator->containsUnexpandedParameterPack());
25645 if (!AllocDependent) {
25646 // OpenMP [2.11.4 allocate Clause, Description]
25647 // allocator is an expression of omp_allocator_handle_t type.
25649 return nullptr;
25650
25651 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
25652 if (AllocatorRes.isInvalid())
25653 return nullptr;
25654 AllocatorRes = SemaRef.PerformImplicitConversion(
25655 AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
25657 /*AllowExplicit=*/true);
25658 if (AllocatorRes.isInvalid())
25659 return nullptr;
25660 Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr;
25661 }
25662 } else {
25663 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
25664 // allocate clauses that appear on a target construct or on constructs in a
25665 // target region must specify an allocator expression unless a requires
25666 // directive with the dynamic_allocators clause is present in the same
25667 // compilation unit.
25668 if (getLangOpts().OpenMPIsTargetDevice &&
25669 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
25670 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
25671 }
25672 if (Alignment) {
25673 bool AlignmentDependent = Alignment->isTypeDependent() ||
25674 Alignment->isValueDependent() ||
25675 Alignment->isInstantiationDependent() ||
25677 if (!AlignmentDependent) {
25678 ExprResult AlignResult =
25679 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_allocate);
25680 Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr;
25681 }
25682 }
25683 // Analyze and build list of variables.
25685 for (Expr *RefExpr : VarList) {
25686 assert(RefExpr && "NULL expr in OpenMP allocate clause.");
25687 SourceLocation ELoc;
25688 SourceRange ERange;
25689 Expr *SimpleRefExpr = RefExpr;
25690 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
25691 if (Res.second) {
25692 // It will be analyzed later.
25693 Vars.push_back(RefExpr);
25694 }
25695 ValueDecl *D = Res.first;
25696 if (!D)
25697 continue;
25698
25699 auto *VD = dyn_cast<VarDecl>(D);
25700 DeclRefExpr *Ref = nullptr;
25701 if (!VD && !SemaRef.CurContext->isDependentContext())
25702 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
25703 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
25704 ? RefExpr->IgnoreParens()
25705 : Ref);
25706 }
25707
25708 if (Vars.empty())
25709 return nullptr;
25710
25711 if (Allocator)
25712 DSAStack->addInnerAllocatorExpr(Allocator);
25713
25715 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
25716 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
25717 SecondAllocateModifierLoc, EndLoc, Vars);
25718}
25719
25721 SourceLocation StartLoc,
25722 SourceLocation LParenLoc,
25723 SourceLocation EndLoc) {
25725 for (Expr *RefExpr : VarList) {
25726 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
25727 SourceLocation ELoc;
25728 SourceRange ERange;
25729 Expr *SimpleRefExpr = RefExpr;
25730 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
25731 if (Res.second)
25732 // It will be analyzed later.
25733 Vars.push_back(RefExpr);
25734 ValueDecl *D = Res.first;
25735 if (!D)
25736 continue;
25737
25738 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
25739 // A list-item cannot appear in more than one nontemporal clause.
25740 if (const Expr *PrevRef =
25741 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
25742 Diag(ELoc, diag::err_omp_used_in_clause_twice)
25743 << 0 << getOpenMPClauseNameForDiag(OMPC_nontemporal) << ERange;
25744 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
25745 << getOpenMPClauseNameForDiag(OMPC_nontemporal);
25746 continue;
25747 }
25748
25749 Vars.push_back(RefExpr);
25750 }
25751
25752 if (Vars.empty())
25753 return nullptr;
25754
25755 return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc,
25756 EndLoc, Vars);
25757}
25758
25760 Stmt *AStmt,
25761 SourceLocation StartLoc,
25762 SourceLocation EndLoc) {
25763 if (!AStmt)
25764 return StmtError();
25765
25766 SemaRef.setFunctionHasBranchProtectedScope();
25767
25768 return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
25769 AStmt);
25770}
25771
25773 SourceLocation StartLoc,
25774 SourceLocation LParenLoc,
25775 SourceLocation EndLoc) {
25777 for (Expr *RefExpr : VarList) {
25778 assert(RefExpr && "NULL expr in OpenMP inclusive clause.");
25779 SourceLocation ELoc;
25780 SourceRange ERange;
25781 Expr *SimpleRefExpr = RefExpr;
25782 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
25783 /*AllowArraySection=*/true);
25784 if (Res.second)
25785 // It will be analyzed later.
25786 Vars.push_back(RefExpr);
25787 ValueDecl *D = Res.first;
25788 if (!D)
25789 continue;
25790
25791 const DSAStackTy::DSAVarData DVar =
25792 DSAStack->getTopDSA(D, /*FromParent=*/true);
25793 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
25794 // A list item that appears in the inclusive or exclusive clause must appear
25795 // in a reduction clause with the inscan modifier on the enclosing
25796 // worksharing-loop, worksharing-loop SIMD, or simd construct.
25797 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
25798 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
25799 << RefExpr->getSourceRange();
25800
25801 if (DSAStack->getParentDirective() != OMPD_unknown)
25802 DSAStack->markDeclAsUsedInScanDirective(D);
25803 Vars.push_back(RefExpr);
25804 }
25805
25806 if (Vars.empty())
25807 return nullptr;
25808
25809 return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
25810 EndLoc, Vars);
25811}
25812
25814 SourceLocation StartLoc,
25815 SourceLocation LParenLoc,
25816 SourceLocation EndLoc) {
25818 for (Expr *RefExpr : VarList) {
25819 assert(RefExpr && "NULL expr in OpenMP exclusive clause.");
25820 SourceLocation ELoc;
25821 SourceRange ERange;
25822 Expr *SimpleRefExpr = RefExpr;
25823 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
25824 /*AllowArraySection=*/true);
25825 if (Res.second)
25826 // It will be analyzed later.
25827 Vars.push_back(RefExpr);
25828 ValueDecl *D = Res.first;
25829 if (!D)
25830 continue;
25831
25832 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
25833 DSAStackTy::DSAVarData DVar;
25834 if (ParentDirective != OMPD_unknown)
25835 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
25836 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
25837 // A list item that appears in the inclusive or exclusive clause must appear
25838 // in a reduction clause with the inscan modifier on the enclosing
25839 // worksharing-loop, worksharing-loop SIMD, or simd construct.
25840 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
25841 DVar.Modifier != OMPC_REDUCTION_inscan) {
25842 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
25843 << RefExpr->getSourceRange();
25844 } else {
25845 DSAStack->markDeclAsUsedInScanDirective(D);
25846 }
25847 Vars.push_back(RefExpr);
25848 }
25849
25850 if (Vars.empty())
25851 return nullptr;
25852
25853 return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
25854 EndLoc, Vars);
25855}
25856
25857/// Tries to find omp_alloctrait_t type.
25858static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
25859 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
25860 if (!OMPAlloctraitT.isNull())
25861 return true;
25862 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
25863 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
25864 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
25865 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
25866 return false;
25867 }
25868 Stack->setOMPAlloctraitT(PT.get());
25869 return true;
25870}
25871
25873 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
25875 ASTContext &Context = getASTContext();
25876 // OpenMP [2.12.5, target Construct]
25877 // allocator is an identifier of omp_allocator_handle_t type.
25878 if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack))
25879 return nullptr;
25880 // OpenMP [2.12.5, target Construct]
25881 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
25882 if (llvm::any_of(
25883 Data,
25884 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
25885 !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack))
25886 return nullptr;
25887 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
25888 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
25889 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
25890 StringRef Allocator =
25891 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
25892 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
25893 PredefinedAllocators.insert(SemaRef.LookupSingleName(
25894 SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
25895 }
25896
25898 for (const UsesAllocatorsData &D : Data) {
25899 Expr *AllocatorExpr = nullptr;
25900 // Check allocator expression.
25901 if (D.Allocator->isTypeDependent()) {
25902 AllocatorExpr = D.Allocator;
25903 } else {
25904 // Traits were specified - need to assign new allocator to the specified
25905 // allocator, so it must be an lvalue.
25906 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
25907 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
25908 bool IsPredefinedAllocator = false;
25909 if (DRE) {
25910 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
25911 getAllocatorKind(SemaRef, DSAStack, AllocatorExpr);
25912 IsPredefinedAllocator =
25913 AllocatorTy !=
25914 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
25915 }
25916 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
25917 QualType AllocatorExprType = AllocatorExpr->getType();
25918 bool IsTypeCompatible = IsPredefinedAllocator;
25919 IsTypeCompatible = IsTypeCompatible ||
25920 Context.hasSameUnqualifiedType(AllocatorExprType,
25921 OMPAllocatorHandleT);
25922 IsTypeCompatible =
25923 IsTypeCompatible ||
25924 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
25925 bool IsNonConstantLValue =
25926 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
25927 if (!DRE || !IsTypeCompatible ||
25928 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
25929 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
25930 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
25931 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
25932 continue;
25933 }
25934 // OpenMP [2.12.5, target Construct]
25935 // Predefined allocators appearing in a uses_allocators clause cannot have
25936 // traits specified.
25937 if (IsPredefinedAllocator && D.AllocatorTraits) {
25939 diag::err_omp_predefined_allocator_with_traits)
25941 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
25942 << cast<NamedDecl>(DRE->getDecl())->getName()
25943 << D.Allocator->getSourceRange();
25944 continue;
25945 }
25946 // OpenMP [2.12.5, target Construct]
25947 // Non-predefined allocators appearing in a uses_allocators clause must
25948 // have traits specified.
25949 if (getLangOpts().OpenMP < 52) {
25950 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
25952 diag::err_omp_nonpredefined_allocator_without_traits);
25953 continue;
25954 }
25955 }
25956 // No allocator traits - just convert it to rvalue.
25957 if (!D.AllocatorTraits)
25958 AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
25959 DSAStack->addUsesAllocatorsDecl(
25960 DRE->getDecl(),
25961 IsPredefinedAllocator
25962 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
25963 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
25964 }
25965 Expr *AllocatorTraitsExpr = nullptr;
25966 if (D.AllocatorTraits) {
25968 AllocatorTraitsExpr = D.AllocatorTraits;
25969 } else {
25970 // OpenMP [2.12.5, target Construct]
25971 // Arrays that contain allocator traits that appear in a uses_allocators
25972 // clause must be constant arrays, have constant values and be defined
25973 // in the same scope as the construct in which the clause appears.
25974 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
25975 // Check that traits expr is a constant array.
25976 QualType TraitTy;
25977 if (const ArrayType *Ty =
25978 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
25979 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
25980 TraitTy = ConstArrayTy->getElementType();
25981 if (TraitTy.isNull() ||
25982 !(Context.hasSameUnqualifiedType(TraitTy,
25983 DSAStack->getOMPAlloctraitT()) ||
25984 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
25985 /*CompareUnqualified=*/true))) {
25987 diag::err_omp_expected_array_alloctraits)
25988 << AllocatorTraitsExpr->getType();
25989 continue;
25990 }
25991 // Do not map by default allocator traits if it is a standalone
25992 // variable.
25993 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
25994 DSAStack->addUsesAllocatorsDecl(
25995 DRE->getDecl(),
25996 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
25997 }
25998 }
25999 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
26000 NewD.Allocator = AllocatorExpr;
26001 NewD.AllocatorTraits = AllocatorTraitsExpr;
26002 NewD.LParenLoc = D.LParenLoc;
26003 NewD.RParenLoc = D.RParenLoc;
26004 }
26005 return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc,
26006 EndLoc, NewData);
26007}
26008
26010 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
26011 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
26013 for (Expr *RefExpr : Locators) {
26014 assert(RefExpr && "NULL expr in OpenMP affinity clause.");
26015 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
26016 // It will be analyzed later.
26017 Vars.push_back(RefExpr);
26018 continue;
26019 }
26020
26021 SourceLocation ELoc = RefExpr->getExprLoc();
26022 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
26023
26024 if (!SimpleExpr->isLValue()) {
26025 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
26026 << 1 << 0 << RefExpr->getSourceRange();
26027 continue;
26028 }
26029
26030 ExprResult Res;
26031 {
26033 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
26034 }
26035 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
26037 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
26038 << 1 << 0 << RefExpr->getSourceRange();
26039 continue;
26040 }
26041 Vars.push_back(SimpleExpr);
26042 }
26043
26044 return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc,
26045 ColonLoc, EndLoc, Modifier, Vars);
26046}
26047
26049 SourceLocation KindLoc,
26050 SourceLocation StartLoc,
26051 SourceLocation LParenLoc,
26052 SourceLocation EndLoc) {
26053 if (Kind == OMPC_BIND_unknown) {
26054 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
26055 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
26056 /*Last=*/unsigned(OMPC_BIND_unknown))
26057 << getOpenMPClauseNameForDiag(OMPC_bind);
26058 return nullptr;
26059 }
26060
26061 return OMPBindClause::Create(getASTContext(), Kind, KindLoc, StartLoc,
26062 LParenLoc, EndLoc);
26063}
26064
26066 SourceLocation StartLoc,
26067 SourceLocation LParenLoc,
26068 SourceLocation EndLoc) {
26069 Expr *ValExpr = Size;
26070 Stmt *HelperValStmt = nullptr;
26071
26072 // OpenMP [2.5, Restrictions]
26073 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
26074 // value.
26075 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem,
26076 /*StrictlyPositive=*/false))
26077 return nullptr;
26078
26079 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
26081 DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP);
26082 if (CaptureRegion != OMPD_unknown &&
26083 !SemaRef.CurContext->isDependentContext()) {
26084 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
26085 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
26086 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
26087 HelperValStmt = buildPreInits(getASTContext(), Captures);
26088 }
26089
26091 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
26092}
26093
26097 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc,
26098 SourceLocation M2Loc, SourceLocation EndLoc) {
26099
26100 if ((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ||
26102 std::string Values = getListOfPossibleValues(
26103 OMPC_dyn_groupprivate, /*First=*/0, OMPC_DYN_GROUPPRIVATE_unknown);
26104 Diag((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ? M1Loc
26105 : M2Loc,
26106 diag::err_omp_unexpected_clause_value)
26107 << Values << getOpenMPClauseName(OMPC_dyn_groupprivate);
26108 return nullptr;
26109 }
26110
26111 Expr *ValExpr = Size;
26112 Stmt *HelperValStmt = nullptr;
26113
26114 // OpenMP [2.5, Restrictions]
26115 // The dyn_groupprivate expression must evaluate to a positive integer
26116 // value.
26117 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_dyn_groupprivate,
26118 /*StrictlyPositive=*/false))
26119 return nullptr;
26120
26121 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
26123 DKind, OMPC_dyn_groupprivate, getLangOpts().OpenMP);
26124 if (CaptureRegion != OMPD_unknown &&
26125 !SemaRef.CurContext->isDependentContext()) {
26126 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
26127 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
26128 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
26129 HelperValStmt = buildPreInits(getASTContext(), Captures);
26130 }
26131
26133 StartLoc, LParenLoc, EndLoc, ValExpr, HelperValStmt, CaptureRegion, M1,
26134 M1Loc, M2, M2Loc);
26135}
26136
26139 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
26140 SourceLocation LParenLoc, SourceLocation EndLoc) {
26141
26142 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
26143 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
26144 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
26145 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
26146 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
26147 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_doacross);
26148 return nullptr;
26149 }
26150
26152 DSAStackTy::OperatorOffsetTy OpsOffs;
26153 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
26154 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
26155 SemaRef,
26156 DepType == OMPC_DOACROSS_source ||
26157 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
26158 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
26159 VarList, DSAStack, EndLoc);
26160 Vars = VarOffset.Vars;
26161 OpsOffs = VarOffset.OpsOffs;
26162 TotalDepCount = VarOffset.TotalDepCount;
26163 auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc,
26164 EndLoc, DepType, DepLoc, ColonLoc, Vars,
26165 TotalDepCount.getZExtValue());
26166 if (DSAStack->isParentOrderedRegion())
26167 DSAStack->addDoacrossDependClause(C, OpsOffs);
26168 return C;
26169}
26170
26172 SourceLocation StartLoc,
26173 SourceLocation LParenLoc,
26174 SourceLocation EndLoc) {
26175 return new (getASTContext())
26176 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
26177}
26178
26180 SourceLocation EndLoc) {
26181 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
26182}
26183
26185 SourceLocation LParenLoc,
26186 SourceLocation EndLoc) {
26187 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
26188}
26189
26193 switch (CK) {
26194 case OMPC_absent:
26195 return OMPAbsentClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
26196 case OMPC_contains:
26197 return OMPContainsClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
26198 default:
26199 llvm_unreachable("Unexpected OpenMP clause");
26200 }
26201}
26202
26204 SourceLocation Loc,
26205 SourceLocation RLoc) {
26206 switch (CK) {
26207 case OMPC_no_openmp:
26208 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
26209 case OMPC_no_openmp_routines:
26210 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
26211 case OMPC_no_parallelism:
26212 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
26213 case OMPC_no_openmp_constructs:
26214 return new (getASTContext()) OMPNoOpenMPConstructsClause(Loc, RLoc);
26215 default:
26216 llvm_unreachable("Unexpected OpenMP clause");
26217 }
26218}
26219
26221 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
26222 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
26223 Expr *Stride, SourceLocation RBLoc) {
26224 ASTContext &Context = getASTContext();
26225 if (Base->hasPlaceholderType() &&
26226 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
26227 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
26228 if (Result.isInvalid())
26229 return ExprError();
26230 Base = Result.get();
26231 }
26232 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
26233 ExprResult Result = SemaRef.CheckPlaceholderExpr(LowerBound);
26234 if (Result.isInvalid())
26235 return ExprError();
26236 Result = SemaRef.DefaultLvalueConversion(Result.get());
26237 if (Result.isInvalid())
26238 return ExprError();
26239 LowerBound = Result.get();
26240 }
26241 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
26242 ExprResult Result = SemaRef.CheckPlaceholderExpr(Length);
26243 if (Result.isInvalid())
26244 return ExprError();
26245 Result = SemaRef.DefaultLvalueConversion(Result.get());
26246 if (Result.isInvalid())
26247 return ExprError();
26248 Length = Result.get();
26249 }
26250 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
26251 ExprResult Result = SemaRef.CheckPlaceholderExpr(Stride);
26252 if (Result.isInvalid())
26253 return ExprError();
26254 Result = SemaRef.DefaultLvalueConversion(Result.get());
26255 if (Result.isInvalid())
26256 return ExprError();
26257 Stride = Result.get();
26258 }
26259
26260 // Build an unanalyzed expression if either operand is type-dependent.
26261 if (Base->isTypeDependent() ||
26262 (LowerBound &&
26263 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
26264 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
26265 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
26266 return new (Context) ArraySectionExpr(
26267 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
26268 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
26269 }
26270
26271 // Perform default conversions.
26273 QualType ResultTy;
26274 if (OriginalTy->isAnyPointerType()) {
26275 ResultTy = OriginalTy->getPointeeType();
26276 } else if (OriginalTy->isArrayType()) {
26277 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
26278 } else {
26279 return ExprError(
26280 Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
26281 << Base->getSourceRange());
26282 }
26283 // C99 6.5.2.1p1
26284 if (LowerBound) {
26285 auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
26286 LowerBound);
26287 if (Res.isInvalid())
26288 return ExprError(Diag(LowerBound->getExprLoc(),
26289 diag::err_omp_typecheck_section_not_integer)
26290 << 0 << LowerBound->getSourceRange());
26291 LowerBound = Res.get();
26292
26293 if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
26294 LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
26295 Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
26296 << 0 << LowerBound->getSourceRange();
26297 }
26298 if (Length) {
26299 auto Res =
26300 PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
26301 if (Res.isInvalid())
26302 return ExprError(Diag(Length->getExprLoc(),
26303 diag::err_omp_typecheck_section_not_integer)
26304 << 1 << Length->getSourceRange());
26305 Length = Res.get();
26306
26307 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
26308 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
26309 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
26310 << 1 << Length->getSourceRange();
26311 }
26312 if (Stride) {
26313 ExprResult Res =
26315 if (Res.isInvalid())
26316 return ExprError(Diag(Stride->getExprLoc(),
26317 diag::err_omp_typecheck_section_not_integer)
26318 << 1 << Stride->getSourceRange());
26319 Stride = Res.get();
26320
26321 if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
26322 Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
26323 Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
26324 << 1 << Stride->getSourceRange();
26325 }
26326
26327 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
26328 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
26329 // type. Note that functions are not objects, and that (in C99 parlance)
26330 // incomplete types are not object types.
26331 if (ResultTy->isFunctionType()) {
26332 Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
26333 << ResultTy << Base->getSourceRange();
26334 return ExprError();
26335 }
26336
26337 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
26338 diag::err_omp_section_incomplete_type, Base))
26339 return ExprError();
26340
26341 if (LowerBound && !OriginalTy->isAnyPointerType()) {
26343 if (LowerBound->EvaluateAsInt(Result, Context)) {
26344 // OpenMP 5.0, [2.1.5 Array Sections]
26345 // The array section must be a subset of the original array.
26346 llvm::APSInt LowerBoundValue = Result.Val.getInt();
26347 if (LowerBoundValue.isNegative()) {
26348 Diag(LowerBound->getExprLoc(),
26349 diag::err_omp_section_not_subset_of_array)
26350 << LowerBound->getSourceRange();
26351 return ExprError();
26352 }
26353 }
26354 }
26355
26356 if (Length) {
26358 if (Length->EvaluateAsInt(Result, Context)) {
26359 // OpenMP 5.0, [2.1.5 Array Sections]
26360 // The length must evaluate to non-negative integers.
26361 llvm::APSInt LengthValue = Result.Val.getInt();
26362 if (LengthValue.isNegative()) {
26363 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
26364 << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
26365 << Length->getSourceRange();
26366 return ExprError();
26367 }
26368 }
26369 } else if (SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.isValid() &&
26370 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
26371 !OriginalTy->isVariableArrayType()))) {
26372 // OpenMP 5.0, [2.1.5 Array Sections]
26373 // When the size of the array dimension is not known, the length must be
26374 // specified explicitly.
26375 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
26376 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
26377 return ExprError();
26378 }
26379
26380 if (Stride) {
26382 if (Stride->EvaluateAsInt(Result, Context)) {
26383 // OpenMP 5.0, [2.1.5 Array Sections]
26384 // The stride must evaluate to a positive integer.
26385 llvm::APSInt StrideValue = Result.Val.getInt();
26386 if (!StrideValue.isStrictlyPositive()) {
26387 Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
26388 << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
26389 << Stride->getSourceRange();
26390 return ExprError();
26391 }
26392 }
26393 }
26394
26395 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
26396 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(Base);
26397 if (Result.isInvalid())
26398 return ExprError();
26399 Base = Result.get();
26400 }
26401 return new (Context) ArraySectionExpr(
26402 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
26403 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
26404}
26405
26407 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
26408 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
26409 ASTContext &Context = getASTContext();
26410 if (Base->hasPlaceholderType()) {
26411 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
26412 if (Result.isInvalid())
26413 return ExprError();
26414 Result = SemaRef.DefaultLvalueConversion(Result.get());
26415 if (Result.isInvalid())
26416 return ExprError();
26417 Base = Result.get();
26418 }
26419 QualType BaseTy = Base->getType();
26420 // Delay analysis of the types/expressions if instantiation/specialization is
26421 // required.
26422 if (!BaseTy->isPointerType() && Base->isTypeDependent())
26423 return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
26424 LParenLoc, RParenLoc, Dims, Brackets);
26425 if (!BaseTy->isPointerType() ||
26426 (!Base->isTypeDependent() &&
26427 BaseTy->getPointeeType()->isIncompleteType()))
26428 return ExprError(Diag(Base->getExprLoc(),
26429 diag::err_omp_non_pointer_type_array_shaping_base)
26430 << Base->getSourceRange());
26431
26432 SmallVector<Expr *, 4> NewDims;
26433 bool ErrorFound = false;
26434 for (Expr *Dim : Dims) {
26435 if (Dim->hasPlaceholderType()) {
26436 ExprResult Result = SemaRef.CheckPlaceholderExpr(Dim);
26437 if (Result.isInvalid()) {
26438 ErrorFound = true;
26439 continue;
26440 }
26441 Result = SemaRef.DefaultLvalueConversion(Result.get());
26442 if (Result.isInvalid()) {
26443 ErrorFound = true;
26444 continue;
26445 }
26446 Dim = Result.get();
26447 }
26448 if (!Dim->isTypeDependent()) {
26451 if (Result.isInvalid()) {
26452 ErrorFound = true;
26453 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
26454 << Dim->getSourceRange();
26455 continue;
26456 }
26457 Dim = Result.get();
26458 Expr::EvalResult EvResult;
26459 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
26460 // OpenMP 5.0, [2.1.4 Array Shaping]
26461 // Each si is an integral type expression that must evaluate to a
26462 // positive integer.
26463 llvm::APSInt Value = EvResult.Val.getInt();
26464 if (!Value.isStrictlyPositive()) {
26465 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
26466 << toString(Value, /*Radix=*/10, /*Signed=*/true)
26467 << Dim->getSourceRange();
26468 ErrorFound = true;
26469 continue;
26470 }
26471 }
26472 }
26473 NewDims.push_back(Dim);
26474 }
26475 if (ErrorFound)
26476 return ExprError();
26477 return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
26478 LParenLoc, RParenLoc, NewDims, Brackets);
26479}
26480
26482 SourceLocation IteratorKwLoc,
26483 SourceLocation LLoc,
26484 SourceLocation RLoc,
26486 ASTContext &Context = getASTContext();
26488 bool IsCorrect = true;
26489 for (const OMPIteratorData &D : Data) {
26490 TypeSourceInfo *TInfo = nullptr;
26491 SourceLocation StartLoc;
26492 QualType DeclTy;
26493 if (!D.Type.getAsOpaquePtr()) {
26494 // OpenMP 5.0, 2.1.6 Iterators
26495 // In an iterator-specifier, if the iterator-type is not specified then
26496 // the type of that iterator is of int type.
26497 DeclTy = Context.IntTy;
26498 StartLoc = D.DeclIdentLoc;
26499 } else {
26500 DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo);
26501 StartLoc = TInfo->getTypeLoc().getBeginLoc();
26502 }
26503
26504 bool IsDeclTyDependent = DeclTy->isDependentType() ||
26505 DeclTy->containsUnexpandedParameterPack() ||
26506 DeclTy->isInstantiationDependentType();
26507 if (!IsDeclTyDependent) {
26508 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
26509 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
26510 // The iterator-type must be an integral or pointer type.
26511 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
26512 << DeclTy;
26513 IsCorrect = false;
26514 continue;
26515 }
26516 if (DeclTy.isConstant(Context)) {
26517 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
26518 // The iterator-type must not be const qualified.
26519 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
26520 << DeclTy;
26521 IsCorrect = false;
26522 continue;
26523 }
26524 }
26525
26526 // Iterator declaration.
26527 assert(D.DeclIdent && "Identifier expected.");
26528 // Always try to create iterator declarator to avoid extra error messages
26529 // about unknown declarations use.
26530 auto *VD =
26531 VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc,
26532 D.DeclIdent, DeclTy, TInfo, SC_None);
26533 VD->setImplicit();
26534 if (S) {
26535 // Check for conflicting previous declaration.
26536 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
26539 Previous.suppressDiagnostics();
26540 SemaRef.LookupName(Previous, S);
26541
26542 SemaRef.FilterLookupForScope(Previous, SemaRef.CurContext, S,
26543 /*ConsiderLinkage=*/false,
26544 /*AllowInlineNamespace=*/false);
26545 if (!Previous.empty()) {
26546 NamedDecl *Old = Previous.getRepresentativeDecl();
26547 Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
26548 Diag(Old->getLocation(), diag::note_previous_definition);
26549 } else {
26550 SemaRef.PushOnScopeChains(VD, S);
26551 }
26552 } else {
26553 SemaRef.CurContext->addDecl(VD);
26554 }
26555
26556 /// Act on the iterator variable declaration.
26558
26559 Expr *Begin = D.Range.Begin;
26560 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
26561 ExprResult BeginRes = SemaRef.PerformImplicitConversion(
26562 Begin, DeclTy, AssignmentAction::Converting);
26563 Begin = BeginRes.get();
26564 }
26565 Expr *End = D.Range.End;
26566 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
26567 ExprResult EndRes = SemaRef.PerformImplicitConversion(
26568 End, DeclTy, AssignmentAction::Converting);
26569 End = EndRes.get();
26570 }
26571 Expr *Step = D.Range.Step;
26572 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
26573 if (!Step->getType()->isIntegralType(Context)) {
26574 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
26575 << Step << Step->getSourceRange();
26576 IsCorrect = false;
26577 continue;
26578 }
26579 std::optional<llvm::APSInt> Result =
26580 Step->getIntegerConstantExpr(Context);
26581 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
26582 // If the step expression of a range-specification equals zero, the
26583 // behavior is unspecified.
26584 if (Result && Result->isZero()) {
26585 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
26586 << Step << Step->getSourceRange();
26587 IsCorrect = false;
26588 continue;
26589 }
26590 }
26591 if (!Begin || !End || !IsCorrect) {
26592 IsCorrect = false;
26593 continue;
26594 }
26595 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
26596 IDElem.IteratorDecl = VD;
26597 IDElem.AssignmentLoc = D.AssignLoc;
26598 IDElem.Range.Begin = Begin;
26599 IDElem.Range.End = End;
26600 IDElem.Range.Step = Step;
26601 IDElem.ColonLoc = D.ColonLoc;
26602 IDElem.SecondColonLoc = D.SecColonLoc;
26603 }
26604 if (!IsCorrect) {
26605 // Invalidate all created iterator declarations if error is found.
26606 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
26607 if (Decl *ID = D.IteratorDecl)
26608 ID->setInvalidDecl();
26609 }
26610 return ExprError();
26611 }
26613 if (!SemaRef.CurContext->isDependentContext()) {
26614 // Build number of ityeration for each iteration range.
26615 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
26616 // ((Begini-Stepi-1-Endi) / -Stepi);
26618 // (Endi - Begini)
26619 ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub,
26620 D.Range.End, D.Range.Begin);
26621 if (!Res.isUsable()) {
26622 IsCorrect = false;
26623 continue;
26624 }
26625 ExprResult St, St1;
26626 if (D.Range.Step) {
26627 St = D.Range.Step;
26628 // (Endi - Begini) + Stepi
26629 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(),
26630 St.get());
26631 if (!Res.isUsable()) {
26632 IsCorrect = false;
26633 continue;
26634 }
26635 // (Endi - Begini) + Stepi - 1
26636 Res = SemaRef.CreateBuiltinBinOp(
26637 D.AssignmentLoc, BO_Sub, Res.get(),
26638 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
26639 if (!Res.isUsable()) {
26640 IsCorrect = false;
26641 continue;
26642 }
26643 // ((Endi - Begini) + Stepi - 1) / Stepi
26644 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(),
26645 St.get());
26646 if (!Res.isUsable()) {
26647 IsCorrect = false;
26648 continue;
26649 }
26650 St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
26651 D.Range.Step);
26652 // (Begini - Endi)
26653 ExprResult Res1 = SemaRef.CreateBuiltinBinOp(
26654 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
26655 if (!Res1.isUsable()) {
26656 IsCorrect = false;
26657 continue;
26658 }
26659 // (Begini - Endi) - Stepi
26660 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(),
26661 St1.get());
26662 if (!Res1.isUsable()) {
26663 IsCorrect = false;
26664 continue;
26665 }
26666 // (Begini - Endi) - Stepi - 1
26667 Res1 = SemaRef.CreateBuiltinBinOp(
26668 D.AssignmentLoc, BO_Sub, Res1.get(),
26669 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
26670 if (!Res1.isUsable()) {
26671 IsCorrect = false;
26672 continue;
26673 }
26674 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
26675 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(),
26676 St1.get());
26677 if (!Res1.isUsable()) {
26678 IsCorrect = false;
26679 continue;
26680 }
26681 // Stepi > 0.
26682 ExprResult CmpRes = SemaRef.CreateBuiltinBinOp(
26683 D.AssignmentLoc, BO_GT, D.Range.Step,
26684 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
26685 if (!CmpRes.isUsable()) {
26686 IsCorrect = false;
26687 continue;
26688 }
26689 Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
26690 CmpRes.get(), Res.get(), Res1.get());
26691 if (!Res.isUsable()) {
26692 IsCorrect = false;
26693 continue;
26694 }
26695 }
26696 Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false);
26697 if (!Res.isUsable()) {
26698 IsCorrect = false;
26699 continue;
26700 }
26701
26702 // Build counter update.
26703 // Build counter.
26704 auto *CounterVD = VarDecl::Create(Context, SemaRef.CurContext,
26705 D.IteratorDecl->getBeginLoc(),
26706 D.IteratorDecl->getBeginLoc(), nullptr,
26707 Res.get()->getType(), nullptr, SC_None);
26708 CounterVD->setImplicit();
26709 ExprResult RefRes =
26710 SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue,
26711 D.IteratorDecl->getBeginLoc());
26712 // Build counter update.
26713 // I = Begini + counter * Stepi;
26714 ExprResult UpdateRes;
26715 if (D.Range.Step) {
26716 UpdateRes = SemaRef.CreateBuiltinBinOp(
26717 D.AssignmentLoc, BO_Mul,
26718 SemaRef.DefaultLvalueConversion(RefRes.get()).get(), St.get());
26719 } else {
26720 UpdateRes = SemaRef.DefaultLvalueConversion(RefRes.get());
26721 }
26722 if (!UpdateRes.isUsable()) {
26723 IsCorrect = false;
26724 continue;
26725 }
26726 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
26727 D.Range.Begin, UpdateRes.get());
26728 if (!UpdateRes.isUsable()) {
26729 IsCorrect = false;
26730 continue;
26731 }
26732 ExprResult VDRes =
26733 SemaRef.BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl),
26734 cast<VarDecl>(D.IteratorDecl)->getType(),
26735 VK_LValue, D.IteratorDecl->getBeginLoc());
26736 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
26737 VDRes.get(), UpdateRes.get());
26738 if (!UpdateRes.isUsable()) {
26739 IsCorrect = false;
26740 continue;
26741 }
26742 UpdateRes =
26743 SemaRef.ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true);
26744 if (!UpdateRes.isUsable()) {
26745 IsCorrect = false;
26746 continue;
26747 }
26748 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
26749 D.AssignmentLoc, UO_PreInc, RefRes.get());
26750 if (!CounterUpdateRes.isUsable()) {
26751 IsCorrect = false;
26752 continue;
26753 }
26754 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(CounterUpdateRes.get(),
26755 /*DiscardedValue=*/true);
26756 if (!CounterUpdateRes.isUsable()) {
26757 IsCorrect = false;
26758 continue;
26759 }
26760 OMPIteratorHelperData &HD = Helpers.emplace_back();
26761 HD.CounterVD = CounterVD;
26762 HD.Upper = Res.get();
26763 HD.Update = UpdateRes.get();
26764 HD.CounterUpdate = CounterUpdateRes.get();
26765 }
26766 } else {
26767 Helpers.assign(ID.size(), {});
26768 }
26769 if (!IsCorrect) {
26770 // Invalidate all created iterator declarations if error is found.
26771 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
26772 if (Decl *ID = D.IteratorDecl)
26773 ID->setInvalidDecl();
26774 }
26775 return ExprError();
26776 }
26777 return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc,
26778 LLoc, RLoc, ID, Helpers);
26779}
26780
26781/// Check if \p AssumptionStr is a known assumption and warn if not.
26783 StringRef AssumptionStr) {
26784 if (llvm::getKnownAssumptionStrings().count(AssumptionStr))
26785 return;
26786
26787 unsigned BestEditDistance = 3;
26788 StringRef Suggestion;
26789 for (const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) {
26790 unsigned EditDistance =
26791 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
26792 if (EditDistance < BestEditDistance) {
26793 Suggestion = KnownAssumptionIt.getKey();
26794 BestEditDistance = EditDistance;
26795 }
26796 }
26797
26798 if (!Suggestion.empty())
26799 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
26800 << AssumptionStr << Suggestion;
26801 else
26802 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
26803 << AssumptionStr;
26804}
26805
26807 // Handle the case where the attribute has a text message.
26808 StringRef Str;
26809 SourceLocation AttrStrLoc;
26810 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
26811 return;
26812
26813 checkOMPAssumeAttr(SemaRef, AttrStrLoc, Str);
26814
26815 D->addAttr(::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
26816}
26817
26819 : 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)
Result
Implement __builtin_bit_cast and related operations.
#define X(type, name)
Definition Value.h:97
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
llvm::MachO::TargetList TargetList
Definition MachO.h:52
This file defines OpenMP AST classes for clauses.
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:50
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 bool hasConstQualifiedMappingType(QualType T)
static void updatePreInits(OMPLoopTransformationDirective *Transform, SmallVectorImpl< Stmt * > &PreInits)
Updates OriginalInits by checking Transform against loop transformation directives and appending thei...
static bool checkGenericLoopLastprivate(Sema &S, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind K, DSAStackTy *Stack)
static 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 OMPClause * createTransparentClause(Sema &SemaRef, ASTContext &Ctx, Expr *ImpexTypeArg, Stmt *HelperValStmt, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
static bool checkOpenMPIterationSpace(OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA, unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, llvm::MutableArrayRef< LoopIterationSpace > ResultIterSpaces, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures, const llvm::SmallPtrSetImpl< const Decl * > &CollapsedLoopVarDecls, llvm::SmallPtrSetImpl< const Decl * > &CollapsedLoopInductionVars)
Called on a for stmt to check and extract its iteration space for further processing (such as collaps...
static bool isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind, bool StrictlyPositive, bool BuildCapture=false, OpenMPDirectiveKind DKind=OMPD_unknown, OpenMPDirectiveKind *CaptureRegion=nullptr, Stmt **HelperValStmt=nullptr)
static bool checkExprsInMultidimClause(SemaBase &SemaRef, const ClauseT *Clause, const OMPXBareClause *BareClause)
Check the number of expressions specified in a multidimensional clause and return whether an error wa...
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 checkMultidimClauses(SemaBase &SemaRef, ArrayRef< OMPClause * > Clauses, bool MayHaveBareClause=false)
Check the number of expressions specified in clauses that can contain multidimensional values,...
static bool checkOrderedOrderSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind, Scope *CurScope, SourceLocation Loc)
static const Expr * getExprAsWritten(const Expr *E)
static bool checkMapConflicts(Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E, bool CurrentRegionOnly, OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents, OpenMPClauseKind CKind)
static bool isOpenMPDeviceDelayedContext(Sema &S)
static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef)
Convert integer expression E to make it have at least Bits bits.
static SmallVector< SemaOpenMP::CapturedParamNameType > getUnknownRegionParams(Sema &SemaRef)
static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack, QualType CanonType, const Expr *E)
static bool hasNoMutableFields(const CXXRecordDecl *RD)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTeamsRegionParams(Sema &SemaRef)
static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc, StringRef AssumptionStr)
Check if AssumptionStr is a known assumption and warn if not.
static void applyOMPAllocateAttribute(Sema &S, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator, Expr *Alignment, SourceRange SR)
static ExprResult buildImplicitMapper(Sema &S, QualType BaseType, DSAStackTy *Stack)
static 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 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.
static OpenMPMapClauseKind getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M, bool IsAggregateOrDeclareTarget, bool HasConstQualifier)
#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 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 OMPAffinityClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Creates clause with a modifier a list of locator items.
static OMPAlignedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Expr *A)
Creates clause with a list of variables VL and alignment A.
static OMPAssumeDirective * Create(const ASTContext &Ctx, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AStmt)
This represents 'bind' clause in the 'pragma omp ...' directives.
static OMPBindClause * Create(const ASTContext &C, OpenMPBindClauseKind K, SourceLocation KLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'bind' clause with kind K ('teams', 'parallel', or 'thread').
static OMPCancelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind CancelRegion)
Creates directive.
static OMPCancellationPointDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Creates directive.
Class that represents a component of a mappable expression. E.g. for an expression S....
SmallVector< MappableComponent, 8 > MappableExprComponentList
static std::pair< const Expr *, std::optional< size_t > > findAttachPtrExpr(MappableExprComponentListRef Components, OpenMPDirectiveKind CurDirKind)
Find the attach pointer expression from a list of mappable expression components.
ArrayRef< MappableComponent > MappableExprComponentListRef
SmallVector< MappableExprComponentList, 8 > MappableExprComponentLists
static OMPCopyinClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
static OMPCopyprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
This represents 'defaultmap' clause in the 'pragma omp ...' directive.
This represents implicit clause 'depend' for the 'pragma omp task' directive.
static OMPDependClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, DependDataTy Data, Expr *DepModifier, ArrayRef< Expr * > VL, unsigned NumLoops)
Creates clause with a list of variables VL.
static OMPDepobjClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Depobj)
Creates clause.
This represents 'destroy' clause in the 'pragma omp depobj' directive or the 'pragma omp interop' dir...
This represents 'detach' clause in the 'pragma omp task' directive.
This represents 'device' clause in the 'pragma omp ...' directive.
static OMPDispatchDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, SourceLocation TargetCallLoc)
Creates directive with a list of Clauses.
This represents 'dist_schedule' clause in the 'pragma omp ...' directive.
static OMPDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents the 'doacross' clause for the 'pragma omp ordered' directive.
static OMPDoacrossClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VL, unsigned NumLoops)
Creates clause with a list of expressions VL.
This represents 'dyn_groupprivate' clause in 'pragma omp target ...' and 'pragma omp teams ....
static OMPErrorDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
static OMPExclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'filter' clause in the 'pragma omp ...' directive.
This represents implicit clause 'flush' for the 'pragma omp flush' directive. This clause does not ex...
static OMPFlushClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPFromClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, Expr *IteratorExpr, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
static OMPFuseDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumGeneratedTopLevelLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for pragma omp fuse'.
static OMPGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'grainsize' clause in the 'pragma omp ...' directive.
static OMPHasDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
This represents 'hint' clause in the 'pragma omp ...' directive.
static OMPInclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPInitClause * Create(const ASTContext &C, Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Creates a fully specified clause.
static OMPInterchangeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp interchange'.
static OMPInteropDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
static OMPIsDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPMapClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapModifiers, ArrayRef< SourceLocation > MapModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId, OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc)
Creates clause with a list of variables VL.
static OMPMaskedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'nocontext' clause in the 'pragma omp ...' directive.
This represents 'nogroup' clause in the 'pragma omp ...' directive.
This represents clause 'nontemporal' in the 'pragma omp ...' directives.
static OMPNontemporalClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'novariants' clause in the 'pragma omp ...' directive.
This represents 'num_tasks' clause in the 'pragma omp ...' directive.
static OMPNumTeamsClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, OpenMPNumTeamsClauseModifier Modifier, Expr *ModifierExpr, SourceLocation ModifierLoc, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents 'order' clause in the 'pragma omp ...' directive.
SourceLocation getKindKwLoc() const
Returns location of clause kind.
OpenMPOrderClauseKind getKind() const
Returns kind of the clause.
static OMPParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'priority' clause in the 'pragma omp ...' directive.
static OMPReverseDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, unsigned NumLoops, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp reverse'.
This represents 'simd' clause in the 'pragma omp ...' directive.
static OMPScanDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
static OMPSplitDirective * 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 split'.
static OMPStripeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp stripe'.
static OMPTargetDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetEnterDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetExitDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetParallelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool CanBeParallelFor)
Creates directive with a list of Clauses.
static OMPTargetUpdateDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPThreadLimitClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents 'threads' clause in the 'pragma omp ...' directive.
static OMPTileDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp tile'.
static OMPToClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, Expr *IteratorModifier, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
bool isExtensionActive(llvm::omp::TraitProperty TP)
Check the extension trait TP is active.
void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const
Create a variant match info object from this trait info object.
bool anyScoreOrCondition(llvm::function_ref< bool(Expr *&, bool)> Cond)
static OMPUnrollDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, unsigned NumGeneratedTopLevelLoops, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp unroll'.
This represents the 'use' clause in 'pragma omp ...' directives.
static OMPUseDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPUseDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< Expr * > PrivateVars, ArrayRef< Expr * > Inits, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, OpenMPUseDevicePtrFallbackModifier FallbackModifier, SourceLocation FallbackModifierLoc)
Creates clause with a list of variables Vars.
This represents clause 'uses_allocators' in the 'pragma omp target'-based directives.
static OMPUsesAllocatorsClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< OMPUsesAllocatorsClause::Data > Data)
Creates clause with a list of allocators Data.
This represents 'ompx_attribute' clause in a directive that might generate an outlined function.
This represents 'ompx_bare' clause in the 'pragma omp target teams ...' directive.
This represents 'ompx_dyn_cgroup_mem' clause in the 'pragma omp target ...' directive.
APSInt & getInt()
Definition APValue.h:508
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
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:809
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:885
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:805
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:924
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:7222
Expr * getBase()
Get base of the array section.
Definition Expr.h:7300
Expr * getLength()
Get length of array section.
Definition Expr.h:7310
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition Expr.cpp:5402
Expr * getLowerBound()
Get lower bound of array section.
Definition Expr.h:7304
SourceLocation getColonLocFirst() const
Definition Expr.h:7331
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3786
QualType getElementType() const
Definition TypeBase.h:3798
Attr - This represents one attribute.
Definition Attr.h:46
Represents an attribute applied to a statement.
Definition Stmt.h:2213
static AttributedStmt * Create(const ASTContext &C, SourceLocation Loc, ArrayRef< const Attr * > Attrs, Stmt *SubStmt)
Definition Stmt.cpp:441
SourceLocation getBeginLoc() const
Definition Stmt.h:2252
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4044
Expr * getLHS() const
Definition Expr.h:4094
static bool isRelationalOp(Opcode Opc)
Definition Expr.h:4138
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition Expr.cpp:2187
static Opcode getOpForCompoundAssignment(Opcode Opc)
Definition Expr.h:4191
SourceLocation getOperatorLoc() const
Definition Expr.h:4086
SourceLocation getExprLoc() const
Definition Expr.h:4085
static Opcode reverseComparisonOp(Opcode Opc)
Definition Expr.h:4163
Expr * getRHS() const
Definition Expr.h:4096
Opcode getOpcode() const
Definition Expr.h:4089
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition Expr.cpp:2149
BinaryOperatorKind Opcode
Definition Expr.h:4049
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:2633
Represents a C++ conversion function within a class.
Definition DeclCXX.h:2968
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:1238
bool hasDefinition() const
Definition DeclCXX.h:561
Represents a C++ nested-name-specifier or a global scope specifier.
Definition DeclSpec.h:76
bool isValid() const
A scope specifier is present, and it refers to a real scope.
Definition DeclSpec.h:188
SourceLocation getBeginLoc() const
Definition DeclSpec.h:86
bool isSet() const
Deprecated.
Definition DeclSpec.h:201
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:186
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2949
SourceLocation getBeginLoc() const
Definition Expr.h:3283
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:1523
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3132
Expr * getCallee()
Definition Expr.h:3096
arg_range arguments()
Definition Expr.h:3201
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:4979
unsigned getNumParams() const
Definition Decl.h:5017
void setNothrow(bool Nothrow=true)
Definition Decl.cpp:5704
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:5700
ImplicitParamDecl * getParam(unsigned i) const
Definition Decl.h:5019
This captures a statement into a function.
Definition Stmt.h:3947
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
Definition Stmt.cpp:1493
SourceRange getSourceRange() const LLVM_READONLY
Definition Stmt.h:4150
Stmt * getCapturedStmt()
Retrieve the statement being captured.
Definition Stmt.h:4051
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
Definition Stmt.cpp:1517
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.h:4142
capture_range captures()
Definition Stmt.h:4085
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3682
Declaration of a class template.
Complex values, per C99 6.2.5p11.
Definition TypeBase.h:3339
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition Stmt.h:1750
SourceLocation getBeginLoc() const
Definition Stmt.h:1864
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
Definition Stmt.cpp:399
ConditionalOperator - The ?
Definition Expr.h:4397
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:1466
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2126
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
Definition DeclBase.h:2255
bool isFileContext() const
Definition DeclBase.h:2197
DeclContextLookupResult lookup_result
Definition DeclBase.h:2594
ASTContext & getParentASTContext() const
Definition DeclBase.h:2155
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:2215
bool isTranslationUnit() const
Definition DeclBase.h:2202
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:2390
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:1276
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:494
ValueDecl * getDecl()
Definition Expr.h:1344
NonOdrUseReason isNonOdrUse() const
Is this expression a non-odr-use reference, and if so, why?
Definition Expr.h:1474
SourceLocation getEndLoc() const LLVM_READONLY
Definition Expr.cpp:557
SourceLocation getBeginLoc() const
Definition Expr.h:1355
SourceLocation getLocation() const
Definition Expr.h:1352
ConstexprSpecKind getConstexprSpecifier() const
Definition DeclSpec.h:839
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1641
SourceLocation getEndLoc() const
Definition Stmt.h:1664
const DeclGroupRef getDeclGroup() const
Definition Stmt.h:1659
const Decl * getSingleDecl() const
Definition Stmt.h:1656
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.h:1667
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:581
bool hasAttrs() const
Definition DeclBase.h:526
void addAttr(Attr *A)
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition DeclBase.h:601
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:591
bool isReferenced() const
Whether any declaration of this entity was referenced.
Definition DeclBase.cpp:601
bool isCanonicalDecl() const
Whether this particular Decl is a canonical one.
Definition DeclBase.h:1001
bool isInvalidDecl() const
Definition DeclBase.h:596
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition DeclBase.h:567
void setAccess(AccessSpecifier AS)
Definition DeclBase.h:510
SourceLocation getLocation() const
Definition DeclBase.h:447
void setImplicit(bool I=true)
Definition DeclBase.h:602
void setReferenced(bool R=true)
Definition DeclBase.h:631
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
Definition DeclBase.h:1066
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
Definition DeclBase.cpp:576
DeclContext * getDeclContext()
Definition DeclBase.h:456
AccessSpecifier getAccess() const
Definition DeclBase.h:515
AttrVec & getAttrs()
Definition DeclBase.h:532
void setDeclContext(DeclContext *DC)
setDeclContext - Set both the semantic and lexical DeclContext to DC.
Definition DeclBase.cpp:382
bool hasAttr() const
Definition DeclBase.h:585
void setLexicalDeclContext(DeclContext *DC)
Definition DeclBase.cpp:386
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition DeclBase.h:995
Kind getKind() const
Definition DeclBase.h:450
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:435
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:1952
const DeclSpec & getDeclSpec() const
getDeclSpec - Return the declaration-specifier that this declarator was declared with.
Definition DeclSpec.h:2099
SourceLocation getIdentifierLoc() const
Definition DeclSpec.h:2388
void SetIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc)
Set the name of this declarator to be the given identifier.
Definition DeclSpec.h:2391
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclSpec.h:2135
void setFunctionDefinitionKind(FunctionDefinitionKind Val)
Definition DeclSpec.h:2785
const CXXScopeSpec & getCXXScopeSpec() const
getCXXScopeSpec - Return the C++ scope specifier (global scope or nested-name-specifier) that is part...
Definition DeclSpec.h:2114
bool isInvalidType() const
Definition DeclSpec.h:2766
const IdentifierInfo * getIdentifier() const
Definition DeclSpec.h:2382
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:681
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition Expr.cpp:3104
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition Expr.h:177
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition Expr.h:447
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition Expr.h:194
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
Definition Expr.h:241
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Skip past any parentheses and lvalue casts which might surround this expression until reaching a fixe...
Definition Expr.cpp:3116
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:3099
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3087
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:3095
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition Expr.h:284
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition Expr.h:454
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition Expr.h:223
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3079
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:144
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
Definition Decl.h:3195
bool isMutable() const
Determines whether this field is mutable (C++ only).
Definition Decl.h:3295
bool isBitField() const
Determines whether this field is a bitfield.
Definition Decl.h:3298
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4823
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
Definition Decl.h:3442
static FloatingLiteral * Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L)
Definition Expr.cpp:1082
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition Stmt.h:2898
Stmt * getBody()
Definition Stmt.h:2942
Represents a function declaration or definition.
Definition Decl.h:2027
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2828
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2805
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition Decl.h:2497
FunctionDecl * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
bool isConsteval() const
Definition Decl.h:2509
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3803
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:5371
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:2269
Stmt * getThen()
Definition Stmt.h:2358
static IfStmt * Create(const ASTContext &Ctx, SourceLocation IL, IfStatementKind Kind, Stmt *Init, VarDecl *Var, Expr *Cond, SourceLocation LPL, SourceLocation RPL, Stmt *Then, SourceLocation EL=SourceLocation(), Stmt *Else=nullptr)
Create an IfStmt.
Definition Stmt.cpp:1044
Expr * getCond()
Definition Stmt.h:2346
Stmt * getElse()
Definition Stmt.h:2367
SourceLocation getBeginLoc() const
Definition Stmt.h:2481
ImaginaryLiteral - We support imaginary integer and floating point literals, like "1....
Definition Expr.h:1737
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition Expr.cpp:2079
ImplicitConversionSequence - Represents an implicit conversion sequence, which may be a standard conv...
Definition Overload.h:622
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateCopy(SourceLocation InitLoc, SourceLocation EqualLoc, bool AllowExplicitConvs=false)
Create a copy initialization.
Describes the sequence of initializations required to initialize a given object or reference with a s...
ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)
Perform the actual initialization of the given entity based on the computed initialization sequence.
Describes an entity that is being initialized.
static InitializedEntity InitializeTemporary(QualType Type)
Create the initialization entity for a temporary.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Definition Expr.cpp:981
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:3453
Expr * getBase() const
Definition Expr.h:3447
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:3431
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:3565
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:1847
void setDeclName(DeclarationName N)
Set the name of this declaration.
Definition Decl.h:343
A C++ nested-name-specifier augmented with source location information.
static OMPAlignClause * Create(const ASTContext &C, Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'align' clause with the given alignment.
static OMPAllocateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, Expr *Allocator, Expr *Alignment, SourceLocation ColonLoc, OpenMPAllocateClauseModifier Modifier1, SourceLocation Modifier1Loc, OpenMPAllocateClauseModifier Modifier2, SourceLocation Modifier2Loc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static bool classof(const OMPClause *T)
static OMPAllocateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL, ArrayRef< OMPClause * > CL)
This represents 'allocator' clause in the 'pragma omp ...' directive.
Expr * getBase()
Fetches base expression of array shaping expression.
Definition ExprOpenMP.h:90
static OMPArrayShapingExpr * Create(const ASTContext &Context, QualType T, Expr *Op, SourceLocation L, SourceLocation R, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > BracketRanges)
Definition Expr.cpp:5510
Pseudo declaration for capturing expressions.
Definition DeclOpenMP.h:445
static OMPCapturedExprDecl * Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, QualType T, SourceLocation StartLoc)
static OMPClauseWithPostUpdate * get(OMPClause *C)
Class that handles pre-initialization statement for some clauses, like 'schedule',...
static OMPClauseWithPreInit * get(OMPClause *C)
This is a basic class for representing single OpenMP clause.
SourceLocation getBeginLoc() const
Returns the starting location of the clause.
SourceLocation getEndLoc() const
Returns the ending location of the clause.
OpenMPClauseKind getClauseKind() const
Returns kind of OpenMP clause (private, shared, reduction, etc.).
This represents 'collapse' clause in the 'pragma omp ...' directive.
static OMPCountsClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Counts, std::optional< unsigned > FillIdx, SourceLocation FillLoc)
Build a 'counts' AST node.
This represents 'pragma omp declare mapper ...' directive.
Definition DeclOpenMP.h:349
static OMPDeclareMapperDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, DeclarationName VarName, ArrayRef< OMPClause * > Clauses, OMPDeclareMapperDecl *PrevDeclInScope)
Creates declare mapper node.
This represents 'pragma omp declare reduction ...' directive.
Definition DeclOpenMP.h:239
static OMPDeclareReductionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, OMPDeclareReductionDecl *PrevDeclInScope)
Create declare reduction node.
This represents 'default' clause in the 'pragma omp ...' directive.
This represents 'final' clause in the 'pragma omp ...' directive.
Representation of the 'full' clause of the 'pragma omp unroll' directive.
static OMPFullClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Build an AST node for a 'full' clause.
This represents 'pragma omp groupprivate ...' directive.
Definition DeclOpenMP.h:173
static OMPGroupPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
This represents 'if' clause in the 'pragma omp ...' directive.
static OMPIteratorExpr * Create(const ASTContext &Context, QualType T, SourceLocation IteratorKwLoc, SourceLocation L, SourceLocation R, ArrayRef< IteratorDefinition > Data, ArrayRef< OMPIteratorHelperData > Helpers)
Definition Expr.cpp:5637
static OMPLoopRangeClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc, Expr *First, Expr *Count)
Build a 'looprange' clause AST node.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
Representation of the 'partial' clause of the 'pragma omp unroll' directive.
static OMPPartialClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Factor)
Build an AST node for a 'partial' clause.
Expr * getFactor() const
Returns the argument of the clause or nullptr if not set.
This class represents the 'permutation' clause in the 'pragma omp interchange' directive.
unsigned getNumLoops() const
Returns the number of list items.
MutableArrayRef< Expr * > getArgsRefs()
Returns the permutation index expressions.
static OMPPermutationClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Args)
Build a 'permutation' clause AST node.
This represents 'pragma omp requires...' directive.
Definition DeclOpenMP.h:479
clauselist_range clauselists()
Definition DeclOpenMP.h:504
static OMPRequiresDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< OMPClause * > CL)
Create requires node.
This represents 'safelen' clause in the 'pragma omp ...' directive.
Expr * getSafelen() const
Return safe iteration space distance.
This represents 'simdlen' clause in the 'pragma omp ...' directive.
Expr * getSimdlen() const
Return safe iteration space distance.
static OMPSizesClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Sizes)
Build a 'sizes' AST node.
This represents 'pragma omp threadprivate ...' directive.
Definition DeclOpenMP.h:110
static OMPThreadPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
This represents 'threadset' clause in the 'pragma omp task ...' directive.
void * getAsOpaquePtr() const
Definition Ownership.h:91
PtrTy get() const
Definition Ownership.h:81
static OpaquePtr make(DeclGroupRef P)
Definition Ownership.h:61
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1184
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition Expr.h:1234
void setIsUnique(bool V)
Definition Expr.h:1236
Represents a parameter to a function.
Definition Decl.h:1817
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:2934
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:5198
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:2970
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition TypeBase.h:8536
QualType withRestrict() const
Definition TypeBase.h:1190
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
Definition Type.cpp:3686
QualType withConst() const
Definition TypeBase.h:1174
void addConst()
Add the const type qualifier to this QualType.
Definition TypeBase.h:1171
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:8447
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:8632
QualType getCanonicalType() const
Definition TypeBase.h:8499
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8541
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:8601
const Type * getTypePtrOrNull() const
Definition TypeBase.h:8451
Represents a struct/union/class.
Definition Decl.h:4360
field_range fields() const
Definition Decl.h:4563
field_iterator field_begin() const
Definition Decl.cpp:5272
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3637
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:380
Scope * getBreakParent()
getBreakParent - Return the closest scope that a break statement would be affected by.
Definition Scope.h:304
bool isOpenMPOrderClauseScope() const
Determine whether this scope is some OpenMP directive with order clause which specifies concurrent sc...
Definition Scope.h:540
const Scope * getParent() const
getParent - Return the scope that this is nested in.
Definition Scope.h:280
bool isOpenMPLoopScope() const
Determine whether this scope is a loop having OpenMP loop directive attached.
Definition Scope.h:533
@ OpenMPOrderClauseScope
This is a scope of some OpenMP directive with order clause which specifies concurrent.
Definition Scope.h:148
A generic diagnostic builder for errors which may or may not be deferred.
Definition SemaBase.h:111
SemaBase(Sema &S)
Definition SemaBase.cpp:7
ASTContext & getASTContext() const
Definition SemaBase.cpp:9
Sema & SemaRef
Definition SemaBase.h:40
const LangOptions & getLangOpts() const
Definition SemaBase.cpp:11
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Definition SemaBase.cpp:61
StmtResult ActOnOpenMPTargetParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel for' after parsing of the associated statement.
OMPClause * ActOnOpenMPNocontextClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nocontext' clause.
OMPClause * ActOnOpenMPXDynCGroupMemClause(Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_dyn_cgroup_mem' clause.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid)
Called at the end of 'pragma omp declare reduction'.
bool isInOpenMPTaskUntiedContext() const
Return true if currently in OpenMP task with untied clause context.
OMPClause * ActOnOpenMPUntiedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'untied' clause.
OMPClause * ActOnOpenMPSafelenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'safelen' clause.
OMPClause * ActOnOpenMPThreadsetClause(OpenMPThreadsetKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'threadset' clause.
OMPClause * ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'holds' clause.
StmtResult ActOnOpenMPParallelMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop simd' after parsing of the associated sta...
StmtResult ActOnOpenMPParallelMasterDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel master' after parsing of the associated statement.
StmtResult ActOnOpenMPDispatchDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp dispatch' after parsing of the.
OMPClause * ActOnOpenMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'read' clause.
OMPClause * ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'filter' clause.
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)
Finish current declare reduction construct initializer.
ExprResult ActOnOpenMPCall(ExprResult Call, Scope *Scope, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig)
Given the potential call expression Call, determine if there is a specialization via the OpenMP decla...
void setOpenMPDeviceNum(int Num)
Setter and getter functions for device_num.
OMPClause * ActOnOpenMPFullClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-form 'full' clauses.
StmtResult ActOnOpenMPSplitDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp split' after parsing of its associated statement.
StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target enter data' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'detach' clause.
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 * ActOnOpenMPCountsClause(ArrayRef< Expr * > CountExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, std::optional< unsigned > FillIdx, SourceLocation FillLoc, unsigned FillCount)
Called on well-formed 'counts' clause after parsing its arguments.
OMPClause * ActOnOpenMPHasDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'has_device_addr' clause.
StmtResult ActOnOpenMPErrorDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, bool InExContext=true)
Called on well-formed '#pragma omp error'.
OMPClause * ActOnOpenMPPartialClause(Expr *FactorExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'partial' clauses.
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.
StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel sections' after parsing of the associated statement.
OMPClause * ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'update' clause.
OMPClause * ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data, Expr *DepModifier, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depend' clause.
OMPClause * ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'doacross' clause.
VarDecl * ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
StmtResult ActOnOpenMPTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for' after parsing of the associated sta...
StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp master' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskgroup'.
VarDecl * isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo=false, unsigned StopAt=0)
Check if the specified variable is used in one of the private clauses (private, firstprivate,...
OMPClause * ActOnOpenMPUseDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, OpenMPUseDevicePtrFallbackModifier FallbackModifier, SourceLocation FallbackModifierLoc)
Called on well-formed 'use_device_ptr' clause.
StmtResult ActOnOpenMPMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop simd' after parsing of the associated statement.
friend class Sema
Definition SemaOpenMP.h:54
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:112
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:437
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:250
void setOpenMPDeviceNumID(StringRef ID)
StmtResult ActOnOpenMPDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for' after parsing of the associated statement...
QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare mapper' construct.
StmtResult ActOnOpenMPTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPMessageClause(Expr *MS, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'message' clause.
int getOpenMPDeviceNum() const
StmtResult ActOnOpenMPScanDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scan'.
OMPClause * ActOnOpenMPScheduleClause(OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'schedule' clause.
void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init)
Check if the current region is an OpenMP loop region and if it is, mark loop control variable,...
OMPClause * ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
void DiagnoseUnterminatedOpenMPDeclareTarget()
Report unterminated 'omp declare target' or 'omp begin declare target' at the end of a compilation un...
void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, const FunctionDecl *Callee, SourceLocation Loc)
Finishes analysis of the deferred functions calls that may be declared as host/nohost during device/h...
OMPClause * ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'simdlen' clause.
std::optional< std::pair< FunctionDecl *, Expr * > > checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, OMPTraitInfo &TI, unsigned NumAppendArgs, SourceRange SR)
Checks '#pragma omp declare variant' variant function and original functions after parsing of the ass...
StmtResult ActOnOpenMPParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for simd' after parsing of the associated statement.
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
Definition SemaOpenMP.h:56
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.
OMPClause * ActOnOpenMPNumTeamsClause(ArrayRef< Expr * > VarList, OpenMPNumTeamsClauseModifier Modifier, Expr *ModifierExpr, SourceLocation ModifierLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_teams' clause.
StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt)
Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to an OpenMP loop directive.
OMPClause * ActOnOpenMPTransparentClause(Expr *Transparent, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'transparent' clause.
OMPClause * ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'hint' clause.
OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK, SourceLocation Loc, SourceLocation RLoc)
StmtResult ActOnOpenMPTargetTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute' after parsing of the associated statement...
StmtResult ActOnOpenMPParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for' after parsing of the associated statement.
OMPClause * ActOnOpenMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'capture' clause.
StmtResult ActOnOpenMPForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for' after parsing of the associated statement.
StmtResult ActOnOpenMPAtomicDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp atomic' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target update'.
StmtResult ActOnOpenMPOrderedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp ordered' after parsing of the associated statement.
StmtResult ActOnOpenMPReverseDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp reverse'.
ExprResult ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > Brackets)
OMPClause * ActOnOpenMPNumThreadsClause(OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'num_threads' clause.
OMPClause * ActOnOpenMPAtClause(OpenMPAtClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'at' clause.
StmtResult ActOnOpenMPTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop' after parsing of the associated statement.
OMPClause * ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'init' clause.
OMPClause * ActOnOpenMPUseDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_addr' clause.
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
OMPClause * ActOnOpenMPAllocateClause(Expr *Allocator, Expr *Alignment, OpenMPAllocateClauseModifier FirstModifier, SourceLocation FirstModifierLoc, OpenMPAllocateClauseModifier SecondModifier, SourceLocation SecondModifierLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocate' clause.
std::pair< StringRef, QualType > CapturedParamNameType
Definition SemaOpenMP.h:57
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:378
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:1316
Expr * get() const
Definition Sema.h:7847
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition Sema.h:12594
Abstract base class used for diagnosing integer constant expression violations.
Definition Sema.h:7798
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:869
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition Sema.h:1142
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:9415
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
Definition Sema.h:9456
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
Definition Sema.h:9458
@ LookupAnyName
Look up any declaration with any name.
Definition Sema.h:9460
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:1534
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
Definition Sema.h:4802
@ AR_inaccessible
Definition Sema.h:1688
Scope * getScopeForContext(DeclContext *Ctx)
Determines the active Scope associated with the given declaration context.
Definition Sema.cpp:2428
FPOptionsOverride CurFPFeatureOverrides()
Definition Sema.h:2078
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:1309
void ActOnCapturedRegionError()
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
Definition SemaDecl.cpp:81
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
Definition SemaExpr.cpp:761
ASTContext & getASTContext() const
Definition Sema.h:940
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:9408
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition Sema.h:1213
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:933
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:1308
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:1307
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
Definition Sema.cpp:2674
llvm::SmallSetVector< DeclContext *, 16 > AssociatedNamespaceSet
Definition Sema.h:9407
DeclContext * getCurLexicalContext() const
Definition Sema.h:1146
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:645
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
Definition Sema.h:15620
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
Definition Sema.cpp:2629
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition Sema.h:1447
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:15575
void setFunctionHasBranchProtectedScope()
Definition Sema.cpp:2614
std::pair< StringRef, QualType > CapturedParamNameType
Definition Sema.h:11323
ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS=nullptr, bool isClassName=false, bool HasTrailingDot=false, ParsedType ObjectType=nullptr, bool IsCtorOrDtorName=false, bool WantNontrivialTypeSourceInfo=false, bool IsClassTemplateDeductionContext=true, ImplicitTypenameContext AllowImplicitTypename=ImplicitTypenameContext::No, IdentifierInfo **CorrectedII=nullptr)
If the identifier refers to a type name within this scope, return the declaration of that type.
Definition SemaDecl.cpp:276
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
@ PotentiallyEvaluated
The current expression is potentially evaluated at run time, which means that code may be generated t...
Definition Sema.h:6828
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
Definition Sema.h:6797
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
Definition SemaStmt.cpp:76
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
Definition Sema.h:1268
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:2220
sema::CapturedRegionScopeInfo * getCurCapturedRegion()
Retrieve the current captured region, if any.
Definition Sema.cpp:3003
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:437
FullExprArg MakeFullExpr(Expr *Arg)
Definition Sema.h:7861
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition Sema.h:8743
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
void setBegin(SourceLocation b)
SourceLocation getBegin() const
void setEnd(SourceLocation e)
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
Definition Stmt.h:86
SourceLocation getEndLoc() const LLVM_READONLY
Definition Stmt.cpp:367
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
child_range children()
Definition Stmt.cpp:304
StmtClass getStmtClass() const
Definition Stmt.h:1503
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical, bool ProfileLambdaExpr=false) const
Produce a unique representation of the given statement.
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
Definition Stmt.cpp:210
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4890
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:3548
SourceLocation getBeginLoc() const
Get the begin source location.
Definition TypeLoc.cpp:193
A container of type source information.
Definition TypeBase.h:8418
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:8429
The base class of the type hierarchy.
Definition TypeBase.h:1875
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
Definition TypeBase.h:9237
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:8787
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:2123
bool isArrayType() const
Definition TypeBase.h:8783
bool isArithmeticType() const
Definition Type.cpp:2426
bool isPointerType() const
Definition TypeBase.h:8684
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:9094
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9344
bool isReferenceType() const
Definition TypeBase.h:8708
bool isEnumeralType() const
Definition TypeBase.h:8815
bool isScalarType() const
Definition TypeBase.h:9156
bool isVariableArrayType() const
Definition TypeBase.h:8795
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
Definition Type.cpp:2160
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
Definition Type.cpp:2380
bool isAnyCharacterType() const
Determine whether this type is any of the built-in character types.
Definition Type.cpp:2233
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
Definition TypeBase.h:9044
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition TypeBase.h:2854
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition TypeBase.h:9019
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition TypeBase.h:2846
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
Definition Type.cpp:2507
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
bool isAnyComplexType() const
Definition TypeBase.h:8819
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
Definition TypeBase.h:2465
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition Type.cpp:2314
bool isFunctionProtoType() const
Definition TypeBase.h:2661
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
Definition TypeBase.h:9200
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2864
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition TypeBase.h:9330
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition Type.cpp:2531
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
Definition TypeBase.h:9294
bool isFunctionType() const
Definition TypeBase.h:8680
bool isStructureOrClassType() const
Definition Type.cpp:743
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2409
bool isFloatingType() const
Definition Type.cpp:2393
bool isAnyPointerType() const
Definition TypeBase.h:8692
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9277
bool isRecordType() const
Definition TypeBase.h:8811
bool isUnionType() const
Definition Type.cpp:755
bool isFunctionNoProtoType() const
Definition TypeBase.h:2660
Represents the declaration of a typedef-name via the 'typedef' type specifier.
Definition Decl.h:3702
Base class for declarations which introduce a typedef-name.
Definition Decl.h:3597
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:2291
Opcode getOpcode() const
Definition Expr.h:2286
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:437
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:3693
const Expr * getExprStmt() const
Definition Stmt.cpp:420
Represents a variable declaration or definition.
Definition Decl.h:932
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition Decl.cpp:2130
bool isFunctionOrMethodVarDecl() const
Similar to isLocalVarDecl, but excludes variables declared in blocks.
Definition Decl.h:1288
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition Decl.h:1591
TLSKind getTLSKind() const
Definition Decl.cpp:2147
bool hasInit() const
Definition Decl.cpp:2377
void setInitStyle(InitializationStyle Style)
Definition Decl.h:1474
InitializationStyle getInitStyle() const
The style of initialization for this declaration.
Definition Decl.h:1488
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
Definition Decl.cpp:2239
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2169
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition Decl.cpp:2236
@ CInit
C-style initialization with assignment.
Definition Decl.h:937
@ CallInit
Call-style initialization (C++98)
Definition Decl.h:940
bool isStaticDataMember() const
Determines whether this is a static data member.
Definition Decl.h:1304
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1247
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition Decl.h:1214
bool isFileVarDecl() const
Returns true for file scoped variable declaration.
Definition Decl.h:1363
const Expr * getInit() const
Definition Decl.h:1389
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition Decl.h:1190
@ TLS_None
Not a TLS variable.
Definition Decl.h:952
void setInit(Expr *I)
Definition Decl.cpp:2456
@ DeclarationOnly
This declaration is only a declaration.
Definition Decl.h:1316
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
Definition Decl.h:1274
bool isDirectInit() const
Whether the initializer is a direct-initializer (list or call).
Definition Decl.h:1493
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
Definition Decl.h:1250
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition Decl.h:1174
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:2507
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
Definition Decl.h:1283
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Definition Decl.h:1379
Retains information about a captured region.
Definition ScopeInfo.h:812
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:1524
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
OpenMPOriginalSharingModifier
OpenMP 6.0 original sharing modifiers.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
@ NUM_OVERLOADED_OPERATORS
Privates[]
This class represents the 'transparent' clause in the 'pragma omp task' directive.
bool isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a teams directive in the outermost n...
bool isa(CodeGen::Address addr)
Definition Address.h:330
bool checkFailClauseParameter(OpenMPClauseKind FailClauseParameter)
Checks if the parameter to the fail clause in "#pragma atomic compare fail" is restricted only to mem...
@ CPlusPlus
MutableArrayRef< TemplateParameterList * > MultiTemplateParamsArg
Definition Ownership.h:263
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
OpenMPDefaultClauseVariableCategory
OpenMP variable-category for 'default' clause.
@ OMPC_DEFAULT_VC_unknown
bool isOpenMPLoopTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive.
OpenMPDefaultmapClauseModifier
OpenMP modifiers for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_MODIFIER_last
@ OMPC_DEFAULTMAP_MODIFIER_unknown
OpenMPOrderClauseModifier
OpenMP modifiers for 'order' clause.
@ OMPC_ORDER_MODIFIER_unknown
@ OMPC_ORDER_MODIFIER_last
@ Comparison
A comparison.
Definition Sema.h:667
ExprObjectKind
A further classification of the kind of object referenced by an l-value or x-value.
Definition Specifiers.h:150
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition Specifiers.h:152
OpenMPAtClauseKind
OpenMP attributes for 'at' clause.
@ OMPC_AT_unknown
Expr * AssertSuccess(ExprResult R)
Definition Ownership.h:275
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
Definition Lambda.h:37
@ LCK_This
Capturing the *this object by reference.
Definition Lambda.h:34
OpenMPReductionClauseModifier
OpenMP modifiers for 'reduction' clause.
@ OMPC_REDUCTION_unknown
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ Seq
'seq' clause, allowed on 'loop' and 'routine' directives.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
Definition OpenMPKinds.h:39
@ OMPC_SCHEDULE_MODIFIER_last
Definition OpenMPKinds.h:44
@ OMPC_SCHEDULE_MODIFIER_unknown
Definition OpenMPKinds.h:40
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
Definition Specifiers.h:124
@ AS_public
Definition Specifiers.h:125
@ AS_none
Definition Specifiers.h:128
SmallVector< Attr *, 4 > AttrVec
AttrVec - A vector of Attr, which is how they are stored on the AST.
ActionResult< Decl * > DeclResult
Definition Ownership.h:255
const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ CR_Default
@ CR_OpenMP
OpenMPNumTeamsClauseModifier
@ OMPC_NUMTEAMS_unknown
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
bool isOpenMPPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of private clauses like 'private', 'firstprivate',...
@ SC_Auto
Definition Specifiers.h:257
@ SC_Register
Definition Specifiers.h:258
@ SC_None
Definition Specifiers.h:251
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:5420
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:344
@ Parameter
The parameter type of a method or function.
Definition TypeBase.h:908
@ Result
The result type of a method or function.
Definition TypeBase.h:905
ActionResult< ParsedType > TypeResult
Definition Ownership.h:251
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
@ OMPC_BIND_unknown
OpenMPLastprivateModifier
OpenMP 'lastprivate' clause modifier.
@ OMPC_LASTPRIVATE_unknown
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
Definition OpenMPKinds.h:55
@ OMPC_DEPEND_unknown
Definition OpenMPKinds.h:59
bool isOpenMPCanonicalLoopSequenceTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive that applies to a canonical loop...
OpenMPGrainsizeClauseModifier
@ OMPC_GRAINSIZE_unknown
bool IsXLHSInRHSPart
True if UE has the first form and false if the second.
bool IsPostfixUpdate
True if original value of 'x' must be stored in 'v', not an updated one.
bool isOpenMPCanonicalLoopNestTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive that applies to a canonical loop...
OpenMPNumTasksClauseModifier
@ OMPC_NUMTASKS_unknown
OpenMPUseDevicePtrFallbackModifier
OpenMP 6.1 use_device_ptr fallback modifier.
@ OMPC_USE_DEVICE_PTR_FALLBACK_unknown
ExprResult ExprError()
Definition Ownership.h:265
bool isOpenMPOrderConcurrentNestableDirective(OpenMPDirectiveKind DKind, const LangOptions &LangOpts)
Checks if the specified directive is an order concurrent nestable directive that can be nested within...
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
bool isOpenMPCapturingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive can capture variables.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
@ OMPC_SEVERITY_unknown
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
static constexpr unsigned NumberOfOMPMotionModifiers
Number of allowed motion-modifiers.
OpenMPMotionModifierKind
OpenMP modifier kind for 'to' or 'from' clause.
Definition OpenMPKinds.h:92
@ OMPC_MOTION_MODIFIER_unknown
Definition OpenMPKinds.h:96
OpenMPDefaultmapClauseKind
OpenMP attributes for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_unknown
OpenMPAllocateClauseModifier
OpenMP modifiers for 'allocate' clause.
@ OMPC_ALLOCATE_unknown
bool isOpenMPThreadPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of threadprivate clauses like 'threadprivate',...
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
Definition OpenMPKinds.h:63
@ OMPC_LINEAR_unknown
Definition OpenMPKinds.h:67
bool isOpenMPExecutableDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "executable".
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
Definition OpenMPKinds.h:25
OpenMPDynGroupprivateClauseModifier
@ OMPC_DYN_GROUPPRIVATE_unknown
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
bool isOpenMPInformationalDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "informational".
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
Definition Specifiers.h:133
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition Specifiers.h:136
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition Specifiers.h:140
SmallVector< CXXBaseSpecifier *, 4 > CXXCastPath
A simple array of base specifiers.
Definition ASTContext.h:147
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_NUMTHREADS_unknown
OpenMPAtomicDefaultMemOrderClauseKind
OpenMP attributes for 'atomic_default_mem_order' clause.
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
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:5991
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
Definition OpenMPKinds.h:28
bool isOpenMPNestingDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a distribute directive in the outerm...
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
OpenMPOrderClauseKind
OpenMP attributes for 'order' clause.
@ OMPC_ORDER_unknown
@ Implicit
An implicit conversion.
Definition Sema.h:440
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
Definition OpenMPKinds.h:31
@ OMPC_SCHEDULE_unknown
Definition OpenMPKinds.h:35
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
ActionResult< Stmt * > StmtResult
Definition Ownership.h:250
OpenMPThreadsetKind
OpenMP modifiers for 'threadset' clause.
@ OMPC_THREADSET_unknown
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Definition OpenMPKinds.h:71
@ OMPC_MAP_unknown
Definition OpenMPKinds.h:75
@ NOUR_Unevaluated
This name appears in an unevaluated operand.
Definition Specifiers.h:178
unsigned long uint64_t
int const char * function
Definition c++config.h:31
#define false
Definition stdbool.h:26
#define true
Definition stdbool.h:25
unsigned operator()(argument_type DK)
OpenMPDirectiveKind argument_type
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Clang specific specialization of the OMPContext to lookup target features.
const Expr * RHS
The original right-hand side.
Definition ExprCXX.h:317
BinaryOperatorKind Opcode
The original opcode, prior to rewriting.
Definition ExprCXX.h:313
const Expr * LHS
The original left-hand side.
Definition ExprCXX.h:315
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:652
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:654
Extra information about a function prototype.
Definition TypeBase.h:5456
llvm::SmallVector< OMPInteropPref, 4 > Prefs
One entry of a prefer_type list.
llvm::SmallVector< Expr *, 2 > Attrs
Iterator definition representation.
Definition ExprOpenMP.h:160
Helper expressions and declaration for OMPIteratorExpr class for each iteration space.
Definition ExprOpenMP.h:111
Expr * CounterUpdate
Updater for the internal counter: ++CounterVD;.
Definition ExprOpenMP.h:121
Expr * Upper
Normalized upper bound.
Definition ExprOpenMP.h:116
Expr * Update
Update expression for the originally specified iteration variable, calculated as VD = Begin + Counter...
Definition ExprOpenMP.h:119
VarDecl * CounterVD
Internal normalized counter.
Definition ExprOpenMP.h:113
This structure contains most locations needed for by an OMPVarListClause.
SourceLocation StartLoc
Starting location of the clause (the clause keyword).
SourceLocation LParenLoc
Location of '('.
SourceLocation EndLoc
Ending location of the clause.
std::optional< Expr * > Indirect
The directive with indirect clause.
Definition SemaOpenMP.h:323
OpenMPDirectiveKind Kind
The directive kind, begin declare target or declare target.
Definition SemaOpenMP.h:320
OMPDeclareTargetDeclAttr::DevTypeTy DT
The 'device_type' as parsed from the clause.
Definition SemaOpenMP.h:317
SourceLocation Loc
The directive location.
Definition SemaOpenMP.h:326
llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped
Explicitly listed variables and functions in a 'to' or 'link' clause.
Definition SemaOpenMP.h:314
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.