Thanks to visit codestin.com
Credit goes to clang.llvm.org

clang 22.0.0git
SemaOpenMP.cpp
Go to the documentation of this file.
1//===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ---------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file implements semantic analysis for OpenMP directives and
10/// clauses.
11///
12//===----------------------------------------------------------------------===//
13
16
17#include "TreeTransform.h"
21#include "clang/AST/Decl.h"
22#include "clang/AST/DeclCXX.h"
26#include "clang/AST/StmtCXX.h"
35#include "clang/Sema/Lookup.h"
37#include "clang/Sema/Scope.h"
39#include "clang/Sema/Sema.h"
40#include "llvm/ADT/IndexedMap.h"
41#include "llvm/ADT/PointerEmbeddedInt.h"
42#include "llvm/ADT/STLExtras.h"
43#include "llvm/ADT/Sequence.h"
44#include "llvm/ADT/SetVector.h"
45#include "llvm/ADT/SmallSet.h"
46#include "llvm/ADT/StringExtras.h"
47#include "llvm/Frontend/OpenMP/OMPAssume.h"
48#include "llvm/Frontend/OpenMP/OMPConstants.h"
49#include "llvm/IR/Assumptions.h"
50#include <optional>
51
52using namespace clang;
53using namespace llvm::omp;
54
55//===----------------------------------------------------------------------===//
56// Stack of data-sharing attributes for variables
57//===----------------------------------------------------------------------===//
58
60 Sema &SemaRef, Expr *E,
62 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
63
65
66namespace {
67/// Default data sharing attributes, which can be applied to directive.
68enum DefaultDataSharingAttributes {
69 DSA_unspecified = 0, /// Data sharing attribute not specified.
70 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
71 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
72 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
73 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
74};
75
76/// Variable Category attributes to restrict the modifier of the
77/// default clause (DefaultDataSharingAttributes)
78/// Not mentioning any Variable category attribute indicates
79/// the modifier (DefaultDataSharingAttributes) is for all variables.
80enum DefaultDataSharingVCAttributes {
81 DSA_VC_all = 0, /// for all variables.
82 DSA_VC_aggregate, /// for aggregate variables.
83 DSA_VC_allocatable, /// for allocatable variables.
84 DSA_VC_pointer, /// for pointer variables.
85 DSA_VC_scalar, /// for scalar variables.
86};
87
88/// Stack for tracking declarations used in OpenMP directives and
89/// clauses and their data-sharing attributes.
90class DSAStackTy {
91public:
92 struct DSAVarData {
93 OpenMPDirectiveKind DKind = OMPD_unknown;
94 OpenMPClauseKind CKind = OMPC_unknown;
95 unsigned Modifier = 0;
96 const Expr *RefExpr = nullptr;
97 DeclRefExpr *PrivateCopy = nullptr;
98 SourceLocation ImplicitDSALoc;
99 bool AppliedToPointee = false;
100 DSAVarData() = default;
101 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
102 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
103 SourceLocation ImplicitDSALoc, unsigned Modifier,
104 bool AppliedToPointee)
105 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
106 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
107 AppliedToPointee(AppliedToPointee) {}
108 };
109 using OperatorOffsetTy =
110 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
111 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
112 /// Kind of the declaration used in the uses_allocators clauses.
113 enum class UsesAllocatorsDeclKind {
114 /// Predefined allocator
115 PredefinedAllocator,
116 /// User-defined allocator
117 UserDefinedAllocator,
118 /// The declaration that represent allocator trait
119 AllocatorTrait,
120 };
121
122private:
123 struct DSAInfo {
124 OpenMPClauseKind Attributes = OMPC_unknown;
125 unsigned Modifier = 0;
126 /// Pointer to a reference expression and a flag which shows that the
127 /// variable is marked as lastprivate(true) or not (false).
128 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
129 DeclRefExpr *PrivateCopy = nullptr;
130 /// true if the attribute is applied to the pointee, not the variable
131 /// itself.
132 bool AppliedToPointee = false;
133 };
134 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
135 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
136 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
137 using LoopControlVariablesMapTy =
138 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
139 /// Struct that associates a component with the clause kind where they are
140 /// found.
141 struct MappedExprComponentTy {
143 OpenMPClauseKind Kind = OMPC_unknown;
144 };
145 using MappedExprComponentsTy =
146 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
147 using CriticalsWithHintsTy =
148 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
149 struct ReductionData {
150 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
151 SourceRange ReductionRange;
152 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
153 ReductionData() = default;
154 void set(BinaryOperatorKind BO, SourceRange RR) {
155 ReductionRange = RR;
156 ReductionOp = BO;
157 }
158 void set(const Expr *RefExpr, SourceRange RR) {
159 ReductionRange = RR;
160 ReductionOp = RefExpr;
161 }
162 };
163 using DeclReductionMapTy =
164 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
165 struct DefaultmapInfo {
166 OpenMPDefaultmapClauseModifier ImplicitBehavior =
168 SourceLocation SLoc;
169 DefaultmapInfo() = default;
170 DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc)
171 : ImplicitBehavior(M), SLoc(Loc) {}
172 };
173
174 struct SharingMapTy {
175 DeclSAMapTy SharingMap;
176 DeclReductionMapTy ReductionMap;
177 UsedRefMapTy AlignedMap;
178 UsedRefMapTy NontemporalMap;
179 MappedExprComponentsTy MappedExprComponents;
180 LoopControlVariablesMapTy LCVMap;
181 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
182 SourceLocation DefaultAttrLoc;
183 DefaultDataSharingVCAttributes DefaultVCAttr = DSA_VC_all;
184 SourceLocation DefaultAttrVCLoc;
185 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1];
186 OpenMPDirectiveKind Directive = OMPD_unknown;
187 DeclarationNameInfo DirectiveName;
188 Scope *CurScope = nullptr;
189 DeclContext *Context = nullptr;
190 SourceLocation ConstructLoc;
191 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
192 /// get the data (loop counters etc.) about enclosing loop-based construct.
193 /// This data is required during codegen.
194 DoacrossClauseMapTy DoacrossDepends;
195 /// First argument (Expr *) contains optional argument of the
196 /// 'ordered' clause, the second one is true if the regions has 'ordered'
197 /// clause, false otherwise.
198 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
199 bool RegionHasOrderConcurrent = false;
200 unsigned AssociatedLoops = 1;
201 bool HasMutipleLoops = false;
202 const Decl *PossiblyLoopCounter = nullptr;
203 bool NowaitRegion = false;
204 bool UntiedRegion = false;
205 bool CancelRegion = false;
206 bool LoopStart = false;
207 bool BodyComplete = false;
208 SourceLocation PrevScanLocation;
209 SourceLocation PrevOrderedLocation;
210 SourceLocation InnerTeamsRegionLoc;
211 /// Reference to the taskgroup task_reduction reference expression.
212 Expr *TaskgroupReductionRef = nullptr;
213 llvm::DenseSet<QualType> MappedClassesQualTypes;
214 SmallVector<Expr *, 4> InnerUsedAllocators;
215 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
216 /// List of globals marked as declare target link in this target region
217 /// (isOpenMPTargetExecutionDirective(Directive) == true).
218 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
219 /// List of decls used in inclusive/exclusive clauses of the scan directive.
220 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
221 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
222 UsesAllocatorsDecls;
223 /// Data is required on creating capture fields for implicit
224 /// default first|private clause.
225 struct ImplicitDefaultFDInfoTy {
226 /// Field decl.
227 const FieldDecl *FD = nullptr;
228 /// Nesting stack level
229 size_t StackLevel = 0;
230 /// Capture variable decl.
231 VarDecl *VD = nullptr;
232 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
233 VarDecl *VD)
234 : FD(FD), StackLevel(StackLevel), VD(VD) {}
235 };
236 /// List of captured fields
237 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
238 ImplicitDefaultFirstprivateFDs;
239 Expr *DeclareMapperVar = nullptr;
240 SmallVector<VarDecl *, 16> IteratorVarDecls;
241 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
242 Scope *CurScope, SourceLocation Loc)
243 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
244 ConstructLoc(Loc) {}
245 SharingMapTy() = default;
246 };
247
248 using StackTy = SmallVector<SharingMapTy, 4>;
249
250 /// Stack of used declaration and their data-sharing attributes.
251 DeclSAMapTy Threadprivates;
252 DeclSAMapTy Groupprivates;
253 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
254 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
255 /// true, if check for DSA must be from parent directive, false, if
256 /// from current directive.
257 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
258 Sema &SemaRef;
259 bool ForceCapturing = false;
260 /// true if all the variables in the target executable directives must be
261 /// captured by reference.
262 bool ForceCaptureByReferenceInTargetExecutable = false;
263 CriticalsWithHintsTy Criticals;
264 unsigned IgnoredStackElements = 0;
265
266 /// Iterators over the stack iterate in order from innermost to outermost
267 /// directive.
268 using const_iterator = StackTy::const_reverse_iterator;
269 const_iterator begin() const {
270 return Stack.empty() ? const_iterator()
271 : Stack.back().first.rbegin() + IgnoredStackElements;
272 }
273 const_iterator end() const {
274 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
275 }
276 using iterator = StackTy::reverse_iterator;
277 iterator begin() {
278 return Stack.empty() ? iterator()
279 : Stack.back().first.rbegin() + IgnoredStackElements;
280 }
281 iterator end() {
282 return Stack.empty() ? iterator() : Stack.back().first.rend();
283 }
284
285 // Convenience operations to get at the elements of the stack.
286
287 bool isStackEmpty() const {
288 return Stack.empty() ||
289 Stack.back().second != CurrentNonCapturingFunctionScope ||
290 Stack.back().first.size() <= IgnoredStackElements;
291 }
292 size_t getStackSize() const {
293 return isStackEmpty() ? 0
294 : Stack.back().first.size() - IgnoredStackElements;
295 }
296
297 SharingMapTy *getTopOfStackOrNull() {
298 size_t Size = getStackSize();
299 if (Size == 0)
300 return nullptr;
301 return &Stack.back().first[Size - 1];
302 }
303 const SharingMapTy *getTopOfStackOrNull() const {
304 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
305 }
306 SharingMapTy &getTopOfStack() {
307 assert(!isStackEmpty() && "no current directive");
308 return *getTopOfStackOrNull();
309 }
310 const SharingMapTy &getTopOfStack() const {
311 return const_cast<DSAStackTy &>(*this).getTopOfStack();
312 }
313
314 SharingMapTy *getSecondOnStackOrNull() {
315 size_t Size = getStackSize();
316 if (Size <= 1)
317 return nullptr;
318 return &Stack.back().first[Size - 2];
319 }
320 const SharingMapTy *getSecondOnStackOrNull() const {
321 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
322 }
323
324 /// Get the stack element at a certain level (previously returned by
325 /// \c getNestingLevel).
326 ///
327 /// Note that nesting levels count from outermost to innermost, and this is
328 /// the reverse of our iteration order where new inner levels are pushed at
329 /// the front of the stack.
330 SharingMapTy &getStackElemAtLevel(unsigned Level) {
331 assert(Level < getStackSize() && "no such stack element");
332 return Stack.back().first[Level];
333 }
334 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
335 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
336 }
337
338 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
339
340 /// Checks if the variable is a local for OpenMP region.
341 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
342
343 /// Vector of previously declared requires directives
344 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
345 /// omp_allocator_handle_t type.
346 QualType OMPAllocatorHandleT;
347 /// omp_depend_t type.
348 QualType OMPDependT;
349 /// omp_event_handle_t type.
350 QualType OMPEventHandleT;
351 /// omp_alloctrait_t type.
352 QualType OMPAlloctraitT;
353 /// Expression for the predefined allocators.
354 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
355 nullptr};
356 /// Vector of previously encountered target directives
357 SmallVector<SourceLocation, 2> TargetLocations;
358 SourceLocation AtomicLocation;
359 /// Vector of declare variant construct traits.
360 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
361
362public:
363 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
364
365 /// Sets omp_allocator_handle_t type.
366 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
367 /// Gets omp_allocator_handle_t type.
368 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
369 /// Sets omp_alloctrait_t type.
370 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
371 /// Gets omp_alloctrait_t type.
372 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
373 /// Sets the given default allocator.
374 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
375 Expr *Allocator) {
376 OMPPredefinedAllocators[AllocatorKind] = Allocator;
377 }
378 /// Returns the specified default allocator.
379 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
380 return OMPPredefinedAllocators[AllocatorKind];
381 }
382 /// Sets omp_depend_t type.
383 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
384 /// Gets omp_depend_t type.
385 QualType getOMPDependT() const { return OMPDependT; }
386
387 /// Sets omp_event_handle_t type.
388 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
389 /// Gets omp_event_handle_t type.
390 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
391
392 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
393 OpenMPClauseKind getClauseParsingMode() const {
394 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
395 return ClauseKindMode;
396 }
397 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
398
399 bool isBodyComplete() const {
400 const SharingMapTy *Top = getTopOfStackOrNull();
401 return Top && Top->BodyComplete;
402 }
403 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
404
405 bool isForceVarCapturing() const { return ForceCapturing; }
406 void setForceVarCapturing(bool V) { ForceCapturing = V; }
407
408 void setForceCaptureByReferenceInTargetExecutable(bool V) {
409 ForceCaptureByReferenceInTargetExecutable = V;
410 }
411 bool isForceCaptureByReferenceInTargetExecutable() const {
412 return ForceCaptureByReferenceInTargetExecutable;
413 }
414
415 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
416 Scope *CurScope, SourceLocation Loc) {
417 assert(!IgnoredStackElements &&
418 "cannot change stack while ignoring elements");
419 if (Stack.empty() ||
420 Stack.back().second != CurrentNonCapturingFunctionScope)
421 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
422 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
423 Stack.back().first.back().DefaultAttrLoc = Loc;
424 }
425
426 void pop() {
427 assert(!IgnoredStackElements &&
428 "cannot change stack while ignoring elements");
429 assert(!Stack.back().first.empty() &&
430 "Data-sharing attributes stack is empty!");
431 Stack.back().first.pop_back();
432 }
433
434 /// RAII object to temporarily leave the scope of a directive when we want to
435 /// logically operate in its parent.
436 class ParentDirectiveScope {
437 DSAStackTy &Self;
438 bool Active;
439
440 public:
441 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
442 : Self(Self), Active(false) {
443 if (Activate)
444 enable();
445 }
446 ~ParentDirectiveScope() { disable(); }
447 void disable() {
448 if (Active) {
449 --Self.IgnoredStackElements;
450 Active = false;
451 }
452 }
453 void enable() {
454 if (!Active) {
455 ++Self.IgnoredStackElements;
456 Active = true;
457 }
458 }
459 };
460
461 /// Marks that we're started loop parsing.
462 void loopInit() {
463 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
464 "Expected loop-based directive.");
465 getTopOfStack().LoopStart = true;
466 }
467 /// Start capturing of the variables in the loop context.
468 void loopStart() {
469 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
470 "Expected loop-based directive.");
471 getTopOfStack().LoopStart = false;
472 }
473 /// true, if variables are captured, false otherwise.
474 bool isLoopStarted() const {
475 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
476 "Expected loop-based directive.");
477 return !getTopOfStack().LoopStart;
478 }
479 /// Marks (or clears) declaration as possibly loop counter.
480 void resetPossibleLoopCounter(const Decl *D = nullptr) {
481 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
482 }
483 /// Gets the possible loop counter decl.
484 const Decl *getPossiblyLoopCounter() const {
485 return getTopOfStack().PossiblyLoopCounter;
486 }
487 /// Start new OpenMP region stack in new non-capturing function.
488 void pushFunction() {
489 assert(!IgnoredStackElements &&
490 "cannot change stack while ignoring elements");
491 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
492 assert(!isa<CapturingScopeInfo>(CurFnScope));
493 CurrentNonCapturingFunctionScope = CurFnScope;
494 }
495 /// Pop region stack for non-capturing function.
496 void popFunction(const FunctionScopeInfo *OldFSI) {
497 assert(!IgnoredStackElements &&
498 "cannot change stack while ignoring elements");
499 if (!Stack.empty() && Stack.back().second == OldFSI) {
500 assert(Stack.back().first.empty());
501 Stack.pop_back();
502 }
503 CurrentNonCapturingFunctionScope = nullptr;
504 for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
505 if (!isa<CapturingScopeInfo>(FSI)) {
506 CurrentNonCapturingFunctionScope = FSI;
507 break;
508 }
509 }
510 }
511
512 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
513 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
514 }
515 std::pair<const OMPCriticalDirective *, llvm::APSInt>
516 getCriticalWithHint(const DeclarationNameInfo &Name) const {
517 auto I = Criticals.find(Name.getAsString());
518 if (I != Criticals.end())
519 return I->second;
520 return std::make_pair(nullptr, llvm::APSInt());
521 }
522 /// If 'aligned' declaration for given variable \a D was not seen yet,
523 /// add it and return NULL; otherwise return previous occurrence's expression
524 /// for diagnostics.
525 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
526 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
527 /// add it and return NULL; otherwise return previous occurrence's expression
528 /// for diagnostics.
529 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
530
531 /// Register specified variable as loop control variable.
532 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
533 /// Check if the specified variable is a loop control variable for
534 /// current region.
535 /// \return The index of the loop control variable in the list of associated
536 /// for-loops (from outer to inner).
537 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
538 /// Check if the specified variable is a loop control variable for
539 /// parent region.
540 /// \return The index of the loop control variable in the list of associated
541 /// for-loops (from outer to inner).
542 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
543 /// Check if the specified variable is a loop control variable for
544 /// current region.
545 /// \return The index of the loop control variable in the list of associated
546 /// for-loops (from outer to inner).
547 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
548 unsigned Level) const;
549 /// Get the loop control variable for the I-th loop (or nullptr) in
550 /// parent directive.
551 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
552
553 /// Marks the specified decl \p D as used in scan directive.
554 void markDeclAsUsedInScanDirective(ValueDecl *D) {
555 if (SharingMapTy *Stack = getSecondOnStackOrNull())
556 Stack->UsedInScanDirective.insert(D);
557 }
558
559 /// Checks if the specified declaration was used in the inner scan directive.
560 bool isUsedInScanDirective(ValueDecl *D) const {
561 if (const SharingMapTy *Stack = getTopOfStackOrNull())
562 return Stack->UsedInScanDirective.contains(D);
563 return false;
564 }
565
566 /// Adds explicit data sharing attribute to the specified declaration.
567 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
568 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
569 bool AppliedToPointee = false);
570
571 /// Adds additional information for the reduction items with the reduction id
572 /// represented as an operator.
573 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
575 /// Adds additional information for the reduction items with the reduction id
576 /// represented as reduction identifier.
577 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
578 const Expr *ReductionRef);
579 /// Returns the location and reduction operation from the innermost parent
580 /// region for the given \p D.
581 const DSAVarData
582 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
584 Expr *&TaskgroupDescriptor) const;
585 /// Returns the location and reduction operation from the innermost parent
586 /// region for the given \p D.
587 const DSAVarData
588 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
589 const Expr *&ReductionRef,
590 Expr *&TaskgroupDescriptor) const;
591 /// Return reduction reference expression for the current taskgroup or
592 /// parallel/worksharing directives with task reductions.
593 Expr *getTaskgroupReductionRef() const {
594 assert((getTopOfStack().Directive == OMPD_taskgroup ||
595 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
596 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
597 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
598 "taskgroup reference expression requested for non taskgroup or "
599 "parallel/worksharing directive.");
600 return getTopOfStack().TaskgroupReductionRef;
601 }
602 /// Checks if the given \p VD declaration is actually a taskgroup reduction
603 /// descriptor variable at the \p Level of OpenMP regions.
604 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
605 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
606 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
607 ->getDecl() == VD;
608 }
609
610 /// Returns data sharing attributes from top of the stack for the
611 /// specified declaration.
612 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
613 /// Returns data-sharing attributes for the specified declaration.
614 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
615 /// Returns data-sharing attributes for the specified declaration.
616 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
617 /// Checks if the specified variables has data-sharing attributes which
618 /// match specified \a CPred predicate in any directive which matches \a DPred
619 /// predicate.
620 const DSAVarData
621 hasDSA(ValueDecl *D,
622 const llvm::function_ref<bool(OpenMPClauseKind, bool,
623 DefaultDataSharingAttributes)>
624 CPred,
625 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
626 bool FromParent) const;
627 /// Checks if the specified variables has data-sharing attributes which
628 /// match specified \a CPred predicate in any innermost directive which
629 /// matches \a DPred predicate.
630 const DSAVarData
631 hasInnermostDSA(ValueDecl *D,
632 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
633 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
634 bool FromParent) const;
635 /// Checks if the specified variables has explicit data-sharing
636 /// attributes which match specified \a CPred predicate at the specified
637 /// OpenMP region.
638 bool
639 hasExplicitDSA(const ValueDecl *D,
640 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
641 unsigned Level, bool NotLastprivate = false) const;
642
643 /// Returns true if the directive at level \Level matches in the
644 /// specified \a DPred predicate.
645 bool hasExplicitDirective(
646 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
647 unsigned Level) const;
648
649 /// Finds a directive which matches specified \a DPred predicate.
650 bool hasDirective(
651 const llvm::function_ref<bool(
652 OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)>
653 DPred,
654 bool FromParent) const;
655
656 /// Returns currently analyzed directive.
657 OpenMPDirectiveKind getCurrentDirective() const {
658 const SharingMapTy *Top = getTopOfStackOrNull();
659 return Top ? Top->Directive : OMPD_unknown;
660 }
661 /// Returns directive kind at specified level.
662 OpenMPDirectiveKind getDirective(unsigned Level) const {
663 assert(!isStackEmpty() && "No directive at specified level.");
664 return getStackElemAtLevel(Level).Directive;
665 }
666 /// Returns the capture region at the specified level.
667 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
668 unsigned OpenMPCaptureLevel) const {
669 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
670 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
671 return CaptureRegions[OpenMPCaptureLevel];
672 }
673 /// Returns parent directive.
674 OpenMPDirectiveKind getParentDirective() const {
675 const SharingMapTy *Parent = getSecondOnStackOrNull();
676 return Parent ? Parent->Directive : OMPD_unknown;
677 }
678
679 /// Add requires decl to internal vector
680 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
681
682 /// Checks if the defined 'requires' directive has specified type of clause.
683 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
684 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
685 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
686 return isa<ClauseType>(C);
687 });
688 });
689 }
690
691 /// Checks for a duplicate clause amongst previously declared requires
692 /// directives
693 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
694 bool IsDuplicate = false;
695 for (OMPClause *CNew : ClauseList) {
696 for (const OMPRequiresDecl *D : RequiresDecls) {
697 for (const OMPClause *CPrev : D->clauselists()) {
698 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
699 SemaRef.Diag(CNew->getBeginLoc(),
700 diag::err_omp_requires_clause_redeclaration)
701 << getOpenMPClauseNameForDiag(CNew->getClauseKind());
702 SemaRef.Diag(CPrev->getBeginLoc(),
703 diag::note_omp_requires_previous_clause)
704 << getOpenMPClauseNameForDiag(CPrev->getClauseKind());
705 IsDuplicate = true;
706 }
707 }
708 }
709 }
710 return IsDuplicate;
711 }
712
713 /// Add location of previously encountered target to internal vector
714 void addTargetDirLocation(SourceLocation LocStart) {
715 TargetLocations.push_back(LocStart);
716 }
717
718 /// Add location for the first encountered atomic directive.
719 void addAtomicDirectiveLoc(SourceLocation Loc) {
720 if (AtomicLocation.isInvalid())
721 AtomicLocation = Loc;
722 }
723
724 /// Returns the location of the first encountered atomic directive in the
725 /// module.
726 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
727
728 // Return previously encountered target region locations.
729 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
730 return TargetLocations;
731 }
732
733 /// Set default data sharing attribute to none.
734 void setDefaultDSANone(SourceLocation Loc) {
735 getTopOfStack().DefaultAttr = DSA_none;
736 getTopOfStack().DefaultAttrLoc = Loc;
737 }
738 /// Set default data sharing attribute to shared.
739 void setDefaultDSAShared(SourceLocation Loc) {
740 getTopOfStack().DefaultAttr = DSA_shared;
741 getTopOfStack().DefaultAttrLoc = Loc;
742 }
743 /// Set default data sharing attribute to private.
744 void setDefaultDSAPrivate(SourceLocation Loc) {
745 getTopOfStack().DefaultAttr = DSA_private;
746 getTopOfStack().DefaultAttrLoc = Loc;
747 }
748 /// Set default data sharing attribute to firstprivate.
749 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
750 getTopOfStack().DefaultAttr = DSA_firstprivate;
751 getTopOfStack().DefaultAttrLoc = Loc;
752 }
753 /// Set default data sharing variable category attribute to aggregate.
754 void setDefaultDSAVCAggregate(SourceLocation VCLoc) {
755 getTopOfStack().DefaultVCAttr = DSA_VC_aggregate;
756 getTopOfStack().DefaultAttrVCLoc = VCLoc;
757 }
758 /// Set default data sharing variable category attribute to all.
759 void setDefaultDSAVCAll(SourceLocation VCLoc) {
760 getTopOfStack().DefaultVCAttr = DSA_VC_all;
761 getTopOfStack().DefaultAttrVCLoc = VCLoc;
762 }
763 /// Set default data sharing variable category attribute to allocatable.
764 void setDefaultDSAVCAllocatable(SourceLocation VCLoc) {
765 getTopOfStack().DefaultVCAttr = DSA_VC_allocatable;
766 getTopOfStack().DefaultAttrVCLoc = VCLoc;
767 }
768 /// Set default data sharing variable category attribute to pointer.
769 void setDefaultDSAVCPointer(SourceLocation VCLoc) {
770 getTopOfStack().DefaultVCAttr = DSA_VC_pointer;
771 getTopOfStack().DefaultAttrVCLoc = VCLoc;
772 }
773 /// Set default data sharing variable category attribute to scalar.
774 void setDefaultDSAVCScalar(SourceLocation VCLoc) {
775 getTopOfStack().DefaultVCAttr = DSA_VC_scalar;
776 getTopOfStack().DefaultAttrVCLoc = VCLoc;
777 }
778 /// Set default data mapping attribute to Modifier:Kind
779 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
780 OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) {
781 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
782 DMI.ImplicitBehavior = M;
783 DMI.SLoc = Loc;
784 }
785 /// Check whether the implicit-behavior has been set in defaultmap
786 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
787 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
788 return getTopOfStack()
789 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
790 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
791 getTopOfStack()
792 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
793 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
794 getTopOfStack()
795 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
796 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
797 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
799 }
800
801 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
802 return ConstructTraits;
803 }
804 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
805 bool ScopeEntry) {
806 if (ScopeEntry)
807 ConstructTraits.append(Traits.begin(), Traits.end());
808 else
809 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
810 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
811 assert(Top == Trait && "Something left a trait on the stack!");
812 (void)Trait;
813 (void)Top;
814 }
815 }
816
817 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
818 return getStackSize() <= Level ? DSA_unspecified
819 : getStackElemAtLevel(Level).DefaultAttr;
820 }
821 DefaultDataSharingAttributes getDefaultDSA() const {
822 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
823 }
824 SourceLocation getDefaultDSALocation() const {
825 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
826 }
828 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
829 return isStackEmpty()
831 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
832 }
834 getDefaultmapModifierAtLevel(unsigned Level,
835 OpenMPDefaultmapClauseKind Kind) const {
836 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
837 }
838 bool isDefaultmapCapturedByRef(unsigned Level,
839 OpenMPDefaultmapClauseKind Kind) const {
841 getDefaultmapModifierAtLevel(Level, Kind);
842 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
843 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
844 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
845 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
846 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
847 (M == OMPC_DEFAULTMAP_MODIFIER_present) ||
848 (M == OMPC_DEFAULTMAP_MODIFIER_storage);
849 }
850 return true;
851 }
852 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
854 switch (Kind) {
855 case OMPC_DEFAULTMAP_scalar:
856 case OMPC_DEFAULTMAP_pointer:
857 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
858 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
859 (M == OMPC_DEFAULTMAP_MODIFIER_default);
860 case OMPC_DEFAULTMAP_aggregate:
861 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
862 default:
863 break;
864 }
865 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
866 }
867 bool mustBeFirstprivateAtLevel(unsigned Level,
868 OpenMPDefaultmapClauseKind Kind) const {
870 getDefaultmapModifierAtLevel(Level, Kind);
871 return mustBeFirstprivateBase(M, Kind);
872 }
873 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
874 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
875 return mustBeFirstprivateBase(M, Kind);
876 }
877
878 /// Checks if the specified variable is a threadprivate.
879 bool isThreadPrivate(VarDecl *D) {
880 const DSAVarData DVar = getTopDSA(D, false);
881 return isOpenMPThreadPrivate(DVar.CKind);
882 }
883
884 /// Marks current region as ordered (it has an 'ordered' clause).
885 void setOrderedRegion(bool IsOrdered, const Expr *Param,
886 OMPOrderedClause *Clause) {
887 if (IsOrdered)
888 getTopOfStack().OrderedRegion.emplace(Param, Clause);
889 else
890 getTopOfStack().OrderedRegion.reset();
891 }
892 /// Returns true, if region is ordered (has associated 'ordered' clause),
893 /// false - otherwise.
894 bool isOrderedRegion() const {
895 if (const SharingMapTy *Top = getTopOfStackOrNull())
896 return Top->OrderedRegion.has_value();
897 return false;
898 }
899 /// Returns optional parameter for the ordered region.
900 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
901 if (const SharingMapTy *Top = getTopOfStackOrNull())
902 if (Top->OrderedRegion)
903 return *Top->OrderedRegion;
904 return std::make_pair(nullptr, nullptr);
905 }
906 /// Returns true, if parent region is ordered (has associated
907 /// 'ordered' clause), false - otherwise.
908 bool isParentOrderedRegion() const {
909 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
910 return Parent->OrderedRegion.has_value();
911 return false;
912 }
913 /// Returns optional parameter for the ordered region.
914 std::pair<const Expr *, OMPOrderedClause *>
915 getParentOrderedRegionParam() const {
916 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
917 if (Parent->OrderedRegion)
918 return *Parent->OrderedRegion;
919 return std::make_pair(nullptr, nullptr);
920 }
921 /// Marks current region as having an 'order' clause.
922 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
923 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
924 }
925 /// Returns true, if parent region is order (has associated
926 /// 'order' clause), false - otherwise.
927 bool isParentOrderConcurrent() const {
928 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
929 return Parent->RegionHasOrderConcurrent;
930 return false;
931 }
932 /// Marks current region as nowait (it has a 'nowait' clause).
933 void setNowaitRegion(bool IsNowait = true) {
934 getTopOfStack().NowaitRegion = IsNowait;
935 }
936 /// Returns true, if parent region is nowait (has associated
937 /// 'nowait' clause), false - otherwise.
938 bool isParentNowaitRegion() const {
939 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
940 return Parent->NowaitRegion;
941 return false;
942 }
943 /// Marks current region as untied (it has a 'untied' clause).
944 void setUntiedRegion(bool IsUntied = true) {
945 getTopOfStack().UntiedRegion = IsUntied;
946 }
947 /// Return true if current region is untied.
948 bool isUntiedRegion() const {
949 const SharingMapTy *Top = getTopOfStackOrNull();
950 return Top ? Top->UntiedRegion : false;
951 }
952 /// Marks parent region as cancel region.
953 void setParentCancelRegion(bool Cancel = true) {
954 if (SharingMapTy *Parent = getSecondOnStackOrNull())
955 Parent->CancelRegion |= Cancel;
956 }
957 /// Return true if current region has inner cancel construct.
958 bool isCancelRegion() const {
959 const SharingMapTy *Top = getTopOfStackOrNull();
960 return Top ? Top->CancelRegion : false;
961 }
962
963 /// Mark that parent region already has scan directive.
964 void setParentHasScanDirective(SourceLocation Loc) {
965 if (SharingMapTy *Parent = getSecondOnStackOrNull())
966 Parent->PrevScanLocation = Loc;
967 }
968 /// Return true if current region has inner cancel construct.
969 bool doesParentHasScanDirective() const {
970 const SharingMapTy *Top = getSecondOnStackOrNull();
971 return Top ? Top->PrevScanLocation.isValid() : false;
972 }
973 /// Return true if current region has inner cancel construct.
974 SourceLocation getParentScanDirectiveLoc() const {
975 const SharingMapTy *Top = getSecondOnStackOrNull();
976 return Top ? Top->PrevScanLocation : SourceLocation();
977 }
978 /// Mark that parent region already has ordered directive.
979 void setParentHasOrderedDirective(SourceLocation Loc) {
980 if (SharingMapTy *Parent = getSecondOnStackOrNull())
981 Parent->PrevOrderedLocation = Loc;
982 }
983 /// Return true if current region has inner ordered construct.
984 bool doesParentHasOrderedDirective() const {
985 const SharingMapTy *Top = getSecondOnStackOrNull();
986 return Top ? Top->PrevOrderedLocation.isValid() : false;
987 }
988 /// Returns the location of the previously specified ordered directive.
989 SourceLocation getParentOrderedDirectiveLoc() const {
990 const SharingMapTy *Top = getSecondOnStackOrNull();
991 return Top ? Top->PrevOrderedLocation : SourceLocation();
992 }
993
994 /// Set collapse value for the region.
995 void setAssociatedLoops(unsigned Val) {
996 getTopOfStack().AssociatedLoops = Val;
997 if (Val > 1)
998 getTopOfStack().HasMutipleLoops = true;
999 }
1000 /// Return collapse value for region.
1001 unsigned getAssociatedLoops() const {
1002 const SharingMapTy *Top = getTopOfStackOrNull();
1003 return Top ? Top->AssociatedLoops : 0;
1004 }
1005 /// Returns true if the construct is associated with multiple loops.
1006 bool hasMutipleLoops() const {
1007 const SharingMapTy *Top = getTopOfStackOrNull();
1008 return Top ? Top->HasMutipleLoops : false;
1009 }
1010
1011 /// Marks current target region as one with closely nested teams
1012 /// region.
1013 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
1014 if (SharingMapTy *Parent = getSecondOnStackOrNull())
1015 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
1016 }
1017 /// Returns true, if current region has closely nested teams region.
1018 bool hasInnerTeamsRegion() const {
1019 return getInnerTeamsRegionLoc().isValid();
1020 }
1021 /// Returns location of the nested teams region (if any).
1022 SourceLocation getInnerTeamsRegionLoc() const {
1023 const SharingMapTy *Top = getTopOfStackOrNull();
1024 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
1025 }
1026
1027 Scope *getCurScope() const {
1028 const SharingMapTy *Top = getTopOfStackOrNull();
1029 return Top ? Top->CurScope : nullptr;
1030 }
1031 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
1032 SourceLocation getConstructLoc() const {
1033 const SharingMapTy *Top = getTopOfStackOrNull();
1034 return Top ? Top->ConstructLoc : SourceLocation();
1035 }
1036
1037 /// Do the check specified in \a Check to all component lists and return true
1038 /// if any issue is found.
1039 bool checkMappableExprComponentListsForDecl(
1040 const ValueDecl *VD, bool CurrentRegionOnly,
1041 const llvm::function_ref<
1044 Check) const {
1045 if (isStackEmpty())
1046 return false;
1047 auto SI = begin();
1048 auto SE = end();
1049
1050 if (SI == SE)
1051 return false;
1052
1053 if (CurrentRegionOnly)
1054 SE = std::next(SI);
1055 else
1056 std::advance(SI, 1);
1057
1058 for (; SI != SE; ++SI) {
1059 auto MI = SI->MappedExprComponents.find(VD);
1060 if (MI != SI->MappedExprComponents.end())
1062 MI->second.Components)
1063 if (Check(L, MI->second.Kind))
1064 return true;
1065 }
1066 return false;
1067 }
1068
1069 /// Do the check specified in \a Check to all component lists at a given level
1070 /// and return true if any issue is found.
1071 bool checkMappableExprComponentListsForDeclAtLevel(
1072 const ValueDecl *VD, unsigned Level,
1073 const llvm::function_ref<
1076 Check) const {
1077 if (getStackSize() <= Level)
1078 return false;
1079
1080 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1081 auto MI = StackElem.MappedExprComponents.find(VD);
1082 if (MI != StackElem.MappedExprComponents.end())
1084 MI->second.Components)
1085 if (Check(L, MI->second.Kind))
1086 return true;
1087 return false;
1088 }
1089
1090 /// Create a new mappable expression component list associated with a given
1091 /// declaration and initialize it with the provided list of components.
1092 void addMappableExpressionComponents(
1093 const ValueDecl *VD,
1095 OpenMPClauseKind WhereFoundClauseKind) {
1096 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1097 // Create new entry and append the new components there.
1098 MEC.Components.resize(MEC.Components.size() + 1);
1099 MEC.Components.back().append(Components.begin(), Components.end());
1100 MEC.Kind = WhereFoundClauseKind;
1101 }
1102
1103 unsigned getNestingLevel() const {
1104 assert(!isStackEmpty());
1105 return getStackSize() - 1;
1106 }
1107 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1108 SharingMapTy *Parent = getSecondOnStackOrNull();
1109 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1110 Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1111 }
1112 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1113 getDoacrossDependClauses() const {
1114 const SharingMapTy &StackElem = getTopOfStack();
1115 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1116 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1117 return llvm::make_range(Ref.begin(), Ref.end());
1118 }
1119 return llvm::make_range(StackElem.DoacrossDepends.end(),
1120 StackElem.DoacrossDepends.end());
1121 }
1122
1123 // Store types of classes which have been explicitly mapped
1124 void addMappedClassesQualTypes(QualType QT) {
1125 SharingMapTy &StackElem = getTopOfStack();
1126 StackElem.MappedClassesQualTypes.insert(QT);
1127 }
1128
1129 // Return set of mapped classes types
1130 bool isClassPreviouslyMapped(QualType QT) const {
1131 const SharingMapTy &StackElem = getTopOfStack();
1132 return StackElem.MappedClassesQualTypes.contains(QT);
1133 }
1134
1135 /// Adds global declare target to the parent target region.
1136 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1137 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1138 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1139 "Expected declare target link global.");
1140 for (auto &Elem : *this) {
1141 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1142 Elem.DeclareTargetLinkVarDecls.push_back(E);
1143 return;
1144 }
1145 }
1146 }
1147
1148 /// Returns the list of globals with declare target link if current directive
1149 /// is target.
1150 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1151 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1152 "Expected target executable directive.");
1153 return getTopOfStack().DeclareTargetLinkVarDecls;
1154 }
1155
1156 /// Adds list of allocators expressions.
1157 void addInnerAllocatorExpr(Expr *E) {
1158 getTopOfStack().InnerUsedAllocators.push_back(E);
1159 }
1160 /// Return list of used allocators.
1161 ArrayRef<Expr *> getInnerAllocators() const {
1162 return getTopOfStack().InnerUsedAllocators;
1163 }
1164 /// Marks the declaration as implicitly firstprivate nin the task-based
1165 /// regions.
1166 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1167 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1168 }
1169 /// Checks if the decl is implicitly firstprivate in the task-based region.
1170 bool isImplicitTaskFirstprivate(Decl *D) const {
1171 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1172 }
1173
1174 /// Marks decl as used in uses_allocators clause as the allocator.
1175 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1176 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1177 }
1178 /// Checks if specified decl is used in uses allocator clause as the
1179 /// allocator.
1180 std::optional<UsesAllocatorsDeclKind>
1181 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1182 const SharingMapTy &StackElem = getTopOfStack();
1183 auto I = StackElem.UsesAllocatorsDecls.find(D);
1184 if (I == StackElem.UsesAllocatorsDecls.end())
1185 return std::nullopt;
1186 return I->getSecond();
1187 }
1188 std::optional<UsesAllocatorsDeclKind>
1189 isUsesAllocatorsDecl(const Decl *D) const {
1190 const SharingMapTy &StackElem = getTopOfStack();
1191 auto I = StackElem.UsesAllocatorsDecls.find(D);
1192 if (I == StackElem.UsesAllocatorsDecls.end())
1193 return std::nullopt;
1194 return I->getSecond();
1195 }
1196
1197 void addDeclareMapperVarRef(Expr *Ref) {
1198 SharingMapTy &StackElem = getTopOfStack();
1199 StackElem.DeclareMapperVar = Ref;
1200 }
1201 const Expr *getDeclareMapperVarRef() const {
1202 const SharingMapTy *Top = getTopOfStackOrNull();
1203 return Top ? Top->DeclareMapperVar : nullptr;
1204 }
1205
1206 /// Add a new iterator variable.
1207 void addIteratorVarDecl(VarDecl *VD) {
1208 SharingMapTy &StackElem = getTopOfStack();
1209 StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl());
1210 }
1211 /// Check if variable declaration is an iterator VarDecl.
1212 bool isIteratorVarDecl(const VarDecl *VD) const {
1213 const SharingMapTy *Top = getTopOfStackOrNull();
1214 if (!Top)
1215 return false;
1216
1217 return llvm::is_contained(Top->IteratorVarDecls, VD->getCanonicalDecl());
1218 }
1219 /// get captured field from ImplicitDefaultFirstprivateFDs
1220 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1221 const_iterator I = begin();
1222 const_iterator EndI = end();
1223 size_t StackLevel = getStackSize();
1224 for (; I != EndI; ++I) {
1225 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1226 break;
1227 StackLevel--;
1228 }
1229 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1230 if (I == EndI)
1231 return nullptr;
1232 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1233 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1234 return IFD.VD;
1235 return nullptr;
1236 }
1237 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1238 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1239 const_iterator I = begin();
1240 const_iterator EndI = end();
1241 for (; I != EndI; ++I)
1242 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1243 break;
1244 if (I == EndI)
1245 return false;
1246 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1247 if (IFD.VD == VD)
1248 return true;
1249 return false;
1250 }
1251 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1252 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1253 iterator I = begin();
1254 const_iterator EndI = end();
1255 size_t StackLevel = getStackSize();
1256 for (; I != EndI; ++I) {
1257 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1258 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1259 break;
1260 }
1261 StackLevel--;
1262 }
1263 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1264 }
1265};
1266
1267bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1268 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1269}
1270
1271bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1272 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1273 DKind == OMPD_unknown;
1274}
1275
1276} // namespace
1277
1278static const Expr *getExprAsWritten(const Expr *E) {
1279 if (const auto *FE = dyn_cast<FullExpr>(E))
1280 E = FE->getSubExpr();
1281
1282 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1283 E = MTE->getSubExpr();
1284
1285 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1286 E = Binder->getSubExpr();
1287
1288 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1289 E = ICE->getSubExprAsWritten();
1290 return E->IgnoreParens();
1291}
1292
1294 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1295}
1296
1297static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1298 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1299 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1300 D = ME->getMemberDecl();
1301
1303 return D;
1304}
1305
1307 return const_cast<ValueDecl *>(
1308 getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1309}
1310
1312 if (C == OMPC_threadprivate)
1313 return getOpenMPClauseName(C).str() + " or thread local";
1314 return getOpenMPClauseName(C).str();
1315}
1316
1317DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1318 ValueDecl *D) const {
1319 D = getCanonicalDecl(D);
1320 auto *VD = dyn_cast<VarDecl>(D);
1321 const auto *FD = dyn_cast<FieldDecl>(D);
1322 DSAVarData DVar;
1323 if (Iter == end()) {
1324 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1325 // in a region but not in construct]
1326 // File-scope or namespace-scope variables referenced in called routines
1327 // in the region are shared unless they appear in a threadprivate
1328 // directive.
1329 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1330 DVar.CKind = OMPC_shared;
1331
1332 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1333 // in a region but not in construct]
1334 // Variables with static storage duration that are declared in called
1335 // routines in the region are shared.
1336 if (VD && VD->hasGlobalStorage())
1337 DVar.CKind = OMPC_shared;
1338
1339 // Non-static data members are shared by default.
1340 if (FD)
1341 DVar.CKind = OMPC_shared;
1342
1343 return DVar;
1344 }
1345
1346 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1347 // in a Construct, C/C++, predetermined, p.1]
1348 // Variables with automatic storage duration that are declared in a scope
1349 // inside the construct are private.
1350 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1351 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1352 DVar.CKind = OMPC_private;
1353 return DVar;
1354 }
1355
1356 DVar.DKind = Iter->Directive;
1357 // Explicitly specified attributes and local variables with predetermined
1358 // attributes.
1359 if (Iter->SharingMap.count(D)) {
1360 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1361 DVar.RefExpr = Data.RefExpr.getPointer();
1362 DVar.PrivateCopy = Data.PrivateCopy;
1363 DVar.CKind = Data.Attributes;
1364 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1365 DVar.Modifier = Data.Modifier;
1366 DVar.AppliedToPointee = Data.AppliedToPointee;
1367 return DVar;
1368 }
1369
1370 DefaultDataSharingAttributes IterDA = Iter->DefaultAttr;
1371 switch (Iter->DefaultVCAttr) {
1372 case DSA_VC_aggregate:
1373 if (!VD->getType()->isAggregateType())
1374 IterDA = DSA_none;
1375 break;
1376 case DSA_VC_allocatable:
1377 if (!(VD->getType()->isPointerType() ||
1378 VD->getType()->isVariableArrayType()))
1379 IterDA = DSA_none;
1380 break;
1381 case DSA_VC_pointer:
1382 if (!VD->getType()->isPointerType())
1383 IterDA = DSA_none;
1384 break;
1385 case DSA_VC_scalar:
1386 if (!VD->getType()->isScalarType())
1387 IterDA = DSA_none;
1388 break;
1389 case DSA_VC_all:
1390 break;
1391 }
1392
1393 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1394 // in a Construct, C/C++, implicitly determined, p.1]
1395 // In a parallel or task construct, the data-sharing attributes of these
1396 // variables are determined by the default clause, if present.
1397 switch (IterDA) {
1398 case DSA_shared:
1399 DVar.CKind = OMPC_shared;
1400 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1401 return DVar;
1402 case DSA_none:
1403 return DVar;
1404 case DSA_firstprivate:
1405 if (VD && VD->getStorageDuration() == SD_Static &&
1406 VD->getDeclContext()->isFileContext()) {
1407 DVar.CKind = OMPC_unknown;
1408 } else {
1409 DVar.CKind = OMPC_firstprivate;
1410 }
1411 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1412 return DVar;
1413 case DSA_private:
1414 // each variable with static storage duration that is declared
1415 // in a namespace or global scope and referenced in the construct,
1416 // and that does not have a predetermined data-sharing attribute
1417 if (VD && VD->getStorageDuration() == SD_Static &&
1418 VD->getDeclContext()->isFileContext()) {
1419 DVar.CKind = OMPC_unknown;
1420 } else {
1421 DVar.CKind = OMPC_private;
1422 }
1423 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1424 return DVar;
1425 case DSA_unspecified:
1426 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1427 // in a Construct, implicitly determined, p.2]
1428 // In a parallel construct, if no default clause is present, these
1429 // variables are shared.
1430 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1431 if ((isOpenMPParallelDirective(DVar.DKind) &&
1432 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1433 isOpenMPTeamsDirective(DVar.DKind)) {
1434 DVar.CKind = OMPC_shared;
1435 return DVar;
1436 }
1437
1438 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1439 // in a Construct, implicitly determined, p.4]
1440 // In a task construct, if no default clause is present, a variable that in
1441 // the enclosing context is determined to be shared by all implicit tasks
1442 // bound to the current team is shared.
1443 if (isOpenMPTaskingDirective(DVar.DKind)) {
1444 DSAVarData DVarTemp;
1445 const_iterator I = Iter, E = end();
1446 do {
1447 ++I;
1448 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1449 // Referenced in a Construct, implicitly determined, p.6]
1450 // In a task construct, if no default clause is present, a variable
1451 // whose data-sharing attribute is not determined by the rules above is
1452 // firstprivate.
1453 DVarTemp = getDSA(I, D);
1454 if (DVarTemp.CKind != OMPC_shared) {
1455 DVar.RefExpr = nullptr;
1456 DVar.CKind = OMPC_firstprivate;
1457 return DVar;
1458 }
1459 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1460 DVar.CKind =
1461 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1462 return DVar;
1463 }
1464 }
1465 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1466 // in a Construct, implicitly determined, p.3]
1467 // For constructs other than task, if no default clause is present, these
1468 // variables inherit their data-sharing attributes from the enclosing
1469 // context.
1470 return getDSA(++Iter, D);
1471}
1472
1473const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1474 const Expr *NewDE) {
1475 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1476 D = getCanonicalDecl(D);
1477 SharingMapTy &StackElem = getTopOfStack();
1478 auto [It, Inserted] = StackElem.AlignedMap.try_emplace(D, NewDE);
1479 if (Inserted) {
1480 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1481 return nullptr;
1482 }
1483 assert(It->second && "Unexpected nullptr expr in the aligned map");
1484 return It->second;
1485}
1486
1487const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1488 const Expr *NewDE) {
1489 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1490 D = getCanonicalDecl(D);
1491 SharingMapTy &StackElem = getTopOfStack();
1492 auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(D, NewDE);
1493 if (Inserted) {
1494 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1495 return nullptr;
1496 }
1497 assert(It->second && "Unexpected nullptr expr in the aligned map");
1498 return It->second;
1499}
1500
1501void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1502 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1503 D = getCanonicalDecl(D);
1504 SharingMapTy &StackElem = getTopOfStack();
1505 StackElem.LCVMap.try_emplace(
1506 D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1507}
1508
1509const DSAStackTy::LCDeclInfo
1510DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1511 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1512 D = getCanonicalDecl(D);
1513 const SharingMapTy &StackElem = getTopOfStack();
1514 auto It = StackElem.LCVMap.find(D);
1515 if (It != StackElem.LCVMap.end())
1516 return It->second;
1517 return {0, nullptr};
1518}
1519
1520const DSAStackTy::LCDeclInfo
1521DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1522 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1523 D = getCanonicalDecl(D);
1524 for (unsigned I = Level + 1; I > 0; --I) {
1525 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1526 auto It = StackElem.LCVMap.find(D);
1527 if (It != StackElem.LCVMap.end())
1528 return It->second;
1529 }
1530 return {0, nullptr};
1531}
1532
1533const DSAStackTy::LCDeclInfo
1534DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1535 const SharingMapTy *Parent = getSecondOnStackOrNull();
1536 assert(Parent && "Data-sharing attributes stack is empty");
1537 D = getCanonicalDecl(D);
1538 auto It = Parent->LCVMap.find(D);
1539 if (It != Parent->LCVMap.end())
1540 return It->second;
1541 return {0, nullptr};
1542}
1543
1544const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1545 const SharingMapTy *Parent = getSecondOnStackOrNull();
1546 assert(Parent && "Data-sharing attributes stack is empty");
1547 if (Parent->LCVMap.size() < I)
1548 return nullptr;
1549 for (const auto &Pair : Parent->LCVMap)
1550 if (Pair.second.first == I)
1551 return Pair.first;
1552 return nullptr;
1553}
1554
1555void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1556 DeclRefExpr *PrivateCopy, unsigned Modifier,
1557 bool AppliedToPointee) {
1558 D = getCanonicalDecl(D);
1559 if (A == OMPC_threadprivate) {
1560 DSAInfo &Data = Threadprivates[D];
1561 Data.Attributes = A;
1562 Data.RefExpr.setPointer(E);
1563 Data.PrivateCopy = nullptr;
1564 Data.Modifier = Modifier;
1565 } else if (A == OMPC_groupprivate) {
1566 DSAInfo &Data = Groupprivates[D];
1567 Data.Attributes = A;
1568 Data.RefExpr.setPointer(E);
1569 Data.PrivateCopy = nullptr;
1570 Data.Modifier = Modifier;
1571 } else {
1572 DSAInfo &Data = getTopOfStack().SharingMap[D];
1573 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1574 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1575 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1576 (isLoopControlVariable(D).first && A == OMPC_private));
1577 Data.Modifier = Modifier;
1578 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1579 Data.RefExpr.setInt(/*IntVal=*/true);
1580 return;
1581 }
1582 const bool IsLastprivate =
1583 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1584 Data.Attributes = A;
1585 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1586 Data.PrivateCopy = PrivateCopy;
1587 Data.AppliedToPointee = AppliedToPointee;
1588 if (PrivateCopy) {
1589 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1590 Data.Modifier = Modifier;
1591 Data.Attributes = A;
1592 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1593 Data.PrivateCopy = nullptr;
1594 Data.AppliedToPointee = AppliedToPointee;
1595 }
1596 }
1597}
1598
1599/// Build a variable declaration for OpenMP loop iteration variable.
1601 StringRef Name, const AttrVec *Attrs = nullptr,
1602 DeclRefExpr *OrigRef = nullptr) {
1603 DeclContext *DC = SemaRef.CurContext;
1604 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1605 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
1606 auto *Decl =
1607 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
1608 if (Attrs) {
1609 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1610 I != E; ++I)
1611 Decl->addAttr(*I);
1612 }
1613 Decl->setImplicit();
1614 if (OrigRef) {
1615 Decl->addAttr(
1616 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1617 }
1618 return Decl;
1619}
1620
1622 SourceLocation Loc,
1623 bool RefersToCapture = false) {
1624 D->setReferenced();
1625 D->markUsed(S.Context);
1627 SourceLocation(), D, RefersToCapture, Loc, Ty,
1628 VK_LValue);
1629}
1630
1631void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1632 BinaryOperatorKind BOK) {
1633 D = getCanonicalDecl(D);
1634 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1635 assert(
1636 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1637 "Additional reduction info may be specified only for reduction items.");
1638 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1639 assert(ReductionData.ReductionRange.isInvalid() &&
1640 (getTopOfStack().Directive == OMPD_taskgroup ||
1641 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1642 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1643 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1644 "Additional reduction info may be specified only once for reduction "
1645 "items.");
1646 ReductionData.set(BOK, SR);
1647 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1648 if (!TaskgroupReductionRef) {
1649 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1650 SemaRef.Context.VoidPtrTy, ".task_red.");
1651 TaskgroupReductionRef =
1652 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1653 }
1654}
1655
1656void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1657 const Expr *ReductionRef) {
1658 D = getCanonicalDecl(D);
1659 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1660 assert(
1661 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1662 "Additional reduction info may be specified only for reduction items.");
1663 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1664 assert(ReductionData.ReductionRange.isInvalid() &&
1665 (getTopOfStack().Directive == OMPD_taskgroup ||
1666 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1667 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1668 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1669 "Additional reduction info may be specified only once for reduction "
1670 "items.");
1671 ReductionData.set(ReductionRef, SR);
1672 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1673 if (!TaskgroupReductionRef) {
1674 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1675 SemaRef.Context.VoidPtrTy, ".task_red.");
1676 TaskgroupReductionRef =
1677 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1678 }
1679}
1680
1681const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1682 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1683 Expr *&TaskgroupDescriptor) const {
1684 D = getCanonicalDecl(D);
1685 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1686 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1687 const DSAInfo &Data = I->SharingMap.lookup(D);
1688 if (Data.Attributes != OMPC_reduction ||
1689 Data.Modifier != OMPC_REDUCTION_task)
1690 continue;
1691 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1692 if (!ReductionData.ReductionOp ||
1693 isa<const Expr *>(ReductionData.ReductionOp))
1694 return DSAVarData();
1695 SR = ReductionData.ReductionRange;
1696 BOK = cast<ReductionData::BOKPtrType>(ReductionData.ReductionOp);
1697 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1698 "expression for the descriptor is not "
1699 "set.");
1700 TaskgroupDescriptor = I->TaskgroupReductionRef;
1701 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1702 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1703 /*AppliedToPointee=*/false);
1704 }
1705 return DSAVarData();
1706}
1707
1708const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1709 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1710 Expr *&TaskgroupDescriptor) const {
1711 D = getCanonicalDecl(D);
1712 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1713 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1714 const DSAInfo &Data = I->SharingMap.lookup(D);
1715 if (Data.Attributes != OMPC_reduction ||
1716 Data.Modifier != OMPC_REDUCTION_task)
1717 continue;
1718 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1719 if (!ReductionData.ReductionOp ||
1720 !isa<const Expr *>(ReductionData.ReductionOp))
1721 return DSAVarData();
1722 SR = ReductionData.ReductionRange;
1723 ReductionRef = cast<const Expr *>(ReductionData.ReductionOp);
1724 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1725 "expression for the descriptor is not "
1726 "set.");
1727 TaskgroupDescriptor = I->TaskgroupReductionRef;
1728 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1729 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1730 /*AppliedToPointee=*/false);
1731 }
1732 return DSAVarData();
1733}
1734
1735bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1736 D = D->getCanonicalDecl();
1737 for (const_iterator E = end(); I != E; ++I) {
1738 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1739 isOpenMPTargetExecutionDirective(I->Directive)) {
1740 if (I->CurScope) {
1741 Scope *TopScope = I->CurScope->getParent();
1742 Scope *CurScope = getCurScope();
1743 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1744 CurScope = CurScope->getParent();
1745 return CurScope != TopScope;
1746 }
1747 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1748 if (I->Context == DC)
1749 return true;
1750 return false;
1751 }
1752 }
1753 return false;
1754}
1755
1757 bool AcceptIfMutable = true,
1758 bool *IsClassType = nullptr) {
1759 ASTContext &Context = SemaRef.getASTContext();
1760 Type = Type.getNonReferenceType().getCanonicalType();
1761 bool IsConstant = Type.isConstant(Context);
1762 Type = Context.getBaseElementType(Type);
1763 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1765 : nullptr;
1766 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1767 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1768 RD = CTD->getTemplatedDecl();
1769 if (IsClassType)
1770 *IsClassType = RD;
1771 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1772 RD->hasDefinition() && RD->hasMutableFields());
1773}
1774
1775static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1777 SourceLocation ELoc,
1778 bool AcceptIfMutable = true,
1779 bool ListItemNotVar = false) {
1780 ASTContext &Context = SemaRef.getASTContext();
1781 bool IsClassType;
1782 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
1783 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1784 : IsClassType ? diag::err_omp_const_not_mutable_variable
1785 : diag::err_omp_const_variable;
1786 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseNameForDiag(CKind);
1787 if (!ListItemNotVar && D) {
1788 const VarDecl *VD = dyn_cast<VarDecl>(D);
1789 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1791 SemaRef.Diag(D->getLocation(),
1792 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1793 << D;
1794 }
1795 return true;
1796 }
1797 return false;
1798}
1799
1800const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1801 bool FromParent) {
1802 D = getCanonicalDecl(D);
1803 DSAVarData DVar;
1804
1805 auto *VD = dyn_cast<VarDecl>(D);
1806 auto TI = Threadprivates.find(D);
1807 if (TI != Threadprivates.end()) {
1808 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1809 DVar.CKind = OMPC_threadprivate;
1810 DVar.Modifier = TI->getSecond().Modifier;
1811 return DVar;
1812 }
1813 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1814 DVar.RefExpr = buildDeclRefExpr(
1815 SemaRef, VD, D->getType().getNonReferenceType(),
1816 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1817 DVar.CKind = OMPC_threadprivate;
1818 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1819 return DVar;
1820 }
1821 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1822 // in a Construct, C/C++, predetermined, p.1]
1823 // Variables appearing in threadprivate directives are threadprivate.
1824 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1825 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1826 SemaRef.getLangOpts().OpenMPUseTLS &&
1827 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1828 (VD && VD->getStorageClass() == SC_Register &&
1829 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1830 DVar.RefExpr = buildDeclRefExpr(
1831 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1832 DVar.CKind = OMPC_threadprivate;
1833 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1834 return DVar;
1835 }
1836 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1837 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1838 !isLoopControlVariable(D).first) {
1839 const_iterator IterTarget =
1840 std::find_if(begin(), end(), [](const SharingMapTy &Data) {
1841 return isOpenMPTargetExecutionDirective(Data.Directive);
1842 });
1843 if (IterTarget != end()) {
1844 const_iterator ParentIterTarget = IterTarget + 1;
1845 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1846 if (isOpenMPLocal(VD, Iter)) {
1847 DVar.RefExpr =
1848 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1849 D->getLocation());
1850 DVar.CKind = OMPC_threadprivate;
1851 return DVar;
1852 }
1853 }
1854 if (!isClauseParsingMode() || IterTarget != begin()) {
1855 auto DSAIter = IterTarget->SharingMap.find(D);
1856 if (DSAIter != IterTarget->SharingMap.end() &&
1857 isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1858 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1859 DVar.CKind = OMPC_threadprivate;
1860 return DVar;
1861 }
1862 const_iterator End = end();
1863 if (!SemaRef.OpenMP().isOpenMPCapturedByRef(
1864 D, std::distance(ParentIterTarget, End),
1865 /*OpenMPCaptureLevel=*/0)) {
1866 DVar.RefExpr =
1867 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1868 IterTarget->ConstructLoc);
1869 DVar.CKind = OMPC_threadprivate;
1870 return DVar;
1871 }
1872 }
1873 }
1874 }
1875
1876 if (isStackEmpty())
1877 // Not in OpenMP execution region and top scope was already checked.
1878 return DVar;
1879
1880 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1881 // in a Construct, C/C++, predetermined, p.4]
1882 // Static data members are shared.
1883 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1884 // in a Construct, C/C++, predetermined, p.7]
1885 // Variables with static storage duration that are declared in a scope
1886 // inside the construct are shared.
1887 if (VD && VD->isStaticDataMember()) {
1888 // Check for explicitly specified attributes.
1889 const_iterator I = begin();
1890 const_iterator EndI = end();
1891 if (FromParent && I != EndI)
1892 ++I;
1893 if (I != EndI) {
1894 auto It = I->SharingMap.find(D);
1895 if (It != I->SharingMap.end()) {
1896 const DSAInfo &Data = It->getSecond();
1897 DVar.RefExpr = Data.RefExpr.getPointer();
1898 DVar.PrivateCopy = Data.PrivateCopy;
1899 DVar.CKind = Data.Attributes;
1900 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1901 DVar.DKind = I->Directive;
1902 DVar.Modifier = Data.Modifier;
1903 DVar.AppliedToPointee = Data.AppliedToPointee;
1904 return DVar;
1905 }
1906 }
1907
1908 DVar.CKind = OMPC_shared;
1909 return DVar;
1910 }
1911
1912 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1913 // The predetermined shared attribute for const-qualified types having no
1914 // mutable members was removed after OpenMP 3.1.
1915 if (SemaRef.LangOpts.OpenMP <= 31) {
1916 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1917 // in a Construct, C/C++, predetermined, p.6]
1918 // Variables with const qualified type having no mutable member are
1919 // shared.
1920 if (isConstNotMutableType(SemaRef, D->getType())) {
1921 // Variables with const-qualified type having no mutable member may be
1922 // listed in a firstprivate clause, even if they are static data members.
1923 DSAVarData DVarTemp = hasInnermostDSA(
1924 D,
1925 [](OpenMPClauseKind C, bool) {
1926 return C == OMPC_firstprivate || C == OMPC_shared;
1927 },
1928 MatchesAlways, FromParent);
1929 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1930 return DVarTemp;
1931
1932 DVar.CKind = OMPC_shared;
1933 return DVar;
1934 }
1935 }
1936
1937 // Explicitly specified attributes and local variables with predetermined
1938 // attributes.
1939 const_iterator I = begin();
1940 const_iterator EndI = end();
1941 if (FromParent && I != EndI)
1942 ++I;
1943 if (I == EndI)
1944 return DVar;
1945 auto It = I->SharingMap.find(D);
1946 if (It != I->SharingMap.end()) {
1947 const DSAInfo &Data = It->getSecond();
1948 DVar.RefExpr = Data.RefExpr.getPointer();
1949 DVar.PrivateCopy = Data.PrivateCopy;
1950 DVar.CKind = Data.Attributes;
1951 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1952 DVar.DKind = I->Directive;
1953 DVar.Modifier = Data.Modifier;
1954 DVar.AppliedToPointee = Data.AppliedToPointee;
1955 }
1956
1957 return DVar;
1958}
1959
1960const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1961 bool FromParent) const {
1962 if (isStackEmpty()) {
1963 const_iterator I;
1964 return getDSA(I, D);
1965 }
1966 D = getCanonicalDecl(D);
1967 const_iterator StartI = begin();
1968 const_iterator EndI = end();
1969 if (FromParent && StartI != EndI)
1970 ++StartI;
1971 return getDSA(StartI, D);
1972}
1973
1974const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1975 unsigned Level) const {
1976 if (getStackSize() <= Level)
1977 return DSAVarData();
1978 D = getCanonicalDecl(D);
1979 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1980 return getDSA(StartI, D);
1981}
1982
1983const DSAStackTy::DSAVarData
1984DSAStackTy::hasDSA(ValueDecl *D,
1985 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1986 DefaultDataSharingAttributes)>
1987 CPred,
1988 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1989 bool FromParent) const {
1990 if (isStackEmpty())
1991 return {};
1992 D = getCanonicalDecl(D);
1993 const_iterator I = begin();
1994 const_iterator EndI = end();
1995 if (FromParent && I != EndI)
1996 ++I;
1997 for (; I != EndI; ++I) {
1998 if (!DPred(I->Directive) &&
1999 !isImplicitOrExplicitTaskingRegion(I->Directive))
2000 continue;
2001 const_iterator NewI = I;
2002 DSAVarData DVar = getDSA(NewI, D);
2003 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
2004 return DVar;
2005 }
2006 return {};
2007}
2008
2009const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
2010 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
2011 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2012 bool FromParent) const {
2013 if (isStackEmpty())
2014 return {};
2015 D = getCanonicalDecl(D);
2016 const_iterator StartI = begin();
2017 const_iterator EndI = end();
2018 if (FromParent && StartI != EndI)
2019 ++StartI;
2020 if (StartI == EndI || !DPred(StartI->Directive))
2021 return {};
2022 const_iterator NewI = StartI;
2023 DSAVarData DVar = getDSA(NewI, D);
2024 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
2025 ? DVar
2026 : DSAVarData();
2027}
2028
2029bool DSAStackTy::hasExplicitDSA(
2030 const ValueDecl *D,
2031 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
2032 unsigned Level, bool NotLastprivate) const {
2033 if (getStackSize() <= Level)
2034 return false;
2035 D = getCanonicalDecl(D);
2036 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2037 auto I = StackElem.SharingMap.find(D);
2038 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
2039 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
2040 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
2041 return true;
2042 // Check predetermined rules for the loop control variables.
2043 auto LI = StackElem.LCVMap.find(D);
2044 if (LI != StackElem.LCVMap.end())
2045 return CPred(OMPC_private, /*AppliedToPointee=*/false);
2046 return false;
2047}
2048
2049bool DSAStackTy::hasExplicitDirective(
2050 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2051 unsigned Level) const {
2052 if (getStackSize() <= Level)
2053 return false;
2054 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2055 return DPred(StackElem.Directive);
2056}
2057
2058bool DSAStackTy::hasDirective(
2059 const llvm::function_ref<bool(OpenMPDirectiveKind,
2060 const DeclarationNameInfo &, SourceLocation)>
2061 DPred,
2062 bool FromParent) const {
2063 // We look only in the enclosing region.
2064 size_t Skip = FromParent ? 2 : 1;
2065 for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
2066 I != E; ++I) {
2067 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2068 return true;
2069 }
2070 return false;
2071}
2072
2073void SemaOpenMP::InitDataSharingAttributesStack() {
2074 VarDataSharingAttributesStack = new DSAStackTy(SemaRef);
2075}
2076
2077#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2078
2079void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2080
2081void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2082 DSAStack->popFunction(OldFSI);
2083}
2084
2086 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2087 "Expected OpenMP device compilation.");
2089}
2090
2091namespace {
2092/// Status of the function emission on the host/device.
2093enum class FunctionEmissionStatus {
2094 Emitted,
2095 Discarded,
2096 Unknown,
2097};
2098} // anonymous namespace
2099
2100SemaBase::SemaDiagnosticBuilder
2102 const FunctionDecl *FD) {
2103 assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&
2104 "Expected OpenMP device compilation.");
2105
2106 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2107 if (FD) {
2108 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(FD);
2109 switch (FES) {
2111 Kind = SemaDiagnosticBuilder::K_Immediate;
2112 break;
2114 // TODO: We should always delay diagnostics here in case a target
2115 // region is in a function we do not emit. However, as the
2116 // current diagnostics are associated with the function containing
2117 // the target region and we do not emit that one, we would miss out
2118 // on diagnostics for the target region itself. We need to anchor
2119 // the diagnostics with the new generated function *or* ensure we
2120 // emit diagnostics associated with the surrounding function.
2122 ? SemaDiagnosticBuilder::K_Deferred
2123 : SemaDiagnosticBuilder::K_Immediate;
2124 break;
2127 Kind = SemaDiagnosticBuilder::K_Nop;
2128 break;
2130 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2131 break;
2132 }
2133 }
2134
2135 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2136}
2137
2140 const FunctionDecl *FD) {
2141 assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice &&
2142 "Expected OpenMP host compilation.");
2143
2144 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2145 if (FD) {
2146 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(FD);
2147 switch (FES) {
2149 Kind = SemaDiagnosticBuilder::K_Immediate;
2150 break;
2152 Kind = SemaDiagnosticBuilder::K_Deferred;
2153 break;
2157 Kind = SemaDiagnosticBuilder::K_Nop;
2158 break;
2159 }
2160 }
2161
2162 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2163}
2164
2167 if (LO.OpenMP <= 45) {
2169 return OMPC_DEFAULTMAP_scalar;
2170 return OMPC_DEFAULTMAP_aggregate;
2171 }
2173 return OMPC_DEFAULTMAP_pointer;
2175 return OMPC_DEFAULTMAP_scalar;
2176 return OMPC_DEFAULTMAP_aggregate;
2177}
2178
2179bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2180 unsigned OpenMPCaptureLevel) const {
2181 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2182
2183 ASTContext &Ctx = getASTContext();
2184 bool IsByRef = true;
2185
2186 // Find the directive that is associated with the provided scope.
2188 QualType Ty = D->getType();
2189
2190 bool IsVariableUsedInMapClause = false;
2191 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2192 // This table summarizes how a given variable should be passed to the device
2193 // given its type and the clauses where it appears. This table is based on
2194 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2195 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2196 //
2197 // =========================================================================
2198 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2199 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2200 // =========================================================================
2201 // | scl | | | | - | | bycopy|
2202 // | scl | | - | x | - | - | bycopy|
2203 // | scl | | x | - | - | - | null |
2204 // | scl | x | | | - | | byref |
2205 // | scl | x | - | x | - | - | bycopy|
2206 // | scl | x | x | - | - | - | null |
2207 // | scl | | - | - | - | x | byref |
2208 // | scl | x | - | - | - | x | byref |
2209 //
2210 // | agg | n.a. | | | - | | byref |
2211 // | agg | n.a. | - | x | - | - | byref |
2212 // | agg | n.a. | x | - | - | - | null |
2213 // | agg | n.a. | - | - | - | x | byref |
2214 // | agg | n.a. | - | - | - | x[] | byref |
2215 //
2216 // | ptr | n.a. | | | - | | bycopy|
2217 // | ptr | n.a. | - | x | - | - | bycopy|
2218 // | ptr | n.a. | x | - | - | - | null |
2219 // | ptr | n.a. | - | - | - | x | byref |
2220 // | ptr | n.a. | - | - | - | x[] | bycopy|
2221 // | ptr | n.a. | - | - | x | | bycopy|
2222 // | ptr | n.a. | - | - | x | x | bycopy|
2223 // | ptr | n.a. | - | - | x | x[] | bycopy|
2224 // =========================================================================
2225 // Legend:
2226 // scl - scalar
2227 // ptr - pointer
2228 // agg - aggregate
2229 // x - applies
2230 // - - invalid in this combination
2231 // [] - mapped with an array section
2232 // byref - should be mapped by reference
2233 // byval - should be mapped by value
2234 // null - initialize a local variable to null on the device
2235 //
2236 // Observations:
2237 // - All scalar declarations that show up in a map clause have to be passed
2238 // by reference, because they may have been mapped in the enclosing data
2239 // environment.
2240 // - If the scalar value does not fit the size of uintptr, it has to be
2241 // passed by reference, regardless the result in the table above.
2242 // - For pointers mapped by value that have either an implicit map or an
2243 // array section, the runtime library may pass the NULL value to the
2244 // device instead of the value passed to it by the compiler.
2245
2246 if (Ty->isReferenceType())
2247 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2248
2249 // Locate map clauses and see if the variable being captured is referred to
2250 // in any of those clauses. Here we only care about variables, not fields,
2251 // because fields are part of aggregates.
2252 bool IsVariableAssociatedWithSection = false;
2253
2254 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2255 D, Level,
2256 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2258 MapExprComponents,
2259 OpenMPClauseKind WhereFoundClauseKind) {
2260 // Both map and has_device_addr clauses information influences how a
2261 // variable is captured. E.g. is_device_ptr does not require changing
2262 // the default behavior.
2263 if (WhereFoundClauseKind != OMPC_map &&
2264 WhereFoundClauseKind != OMPC_has_device_addr)
2265 return false;
2266
2267 auto EI = MapExprComponents.rbegin();
2268 auto EE = MapExprComponents.rend();
2269
2270 assert(EI != EE && "Invalid map expression!");
2271
2272 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2273 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2274
2275 ++EI;
2276 if (EI == EE)
2277 return false;
2278 auto Last = std::prev(EE);
2279 const auto *UO =
2280 dyn_cast<UnaryOperator>(Last->getAssociatedExpression());
2281 if ((UO && UO->getOpcode() == UO_Deref) ||
2282 isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) ||
2283 isa<ArraySectionExpr>(Last->getAssociatedExpression()) ||
2284 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2285 isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) {
2286 IsVariableAssociatedWithSection = true;
2287 // There is nothing more we need to know about this variable.
2288 return true;
2289 }
2290
2291 // Keep looking for more map info.
2292 return false;
2293 });
2294
2295 if (IsVariableUsedInMapClause) {
2296 // If variable is identified in a map clause it is always captured by
2297 // reference except if it is a pointer that is dereferenced somehow.
2298 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2299 } else {
2300 // By default, all the data that has a scalar type is mapped by copy
2301 // (except for reduction variables).
2302 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2303 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2304 !Ty->isAnyPointerType()) ||
2305 !Ty->isScalarType() ||
2306 DSAStack->isDefaultmapCapturedByRef(
2308 DSAStack->hasExplicitDSA(
2309 D,
2310 [](OpenMPClauseKind K, bool AppliedToPointee) {
2311 return K == OMPC_reduction && !AppliedToPointee;
2312 },
2313 Level);
2314 }
2315 }
2316
2317 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2318 IsByRef =
2319 ((IsVariableUsedInMapClause &&
2320 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2321 OMPD_target) ||
2322 !(DSAStack->hasExplicitDSA(
2323 D,
2324 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2325 return K == OMPC_firstprivate ||
2326 (K == OMPC_reduction && AppliedToPointee);
2327 },
2328 Level, /*NotLastprivate=*/true) ||
2329 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2330 // If the variable is artificial and must be captured by value - try to
2331 // capture by value.
2332 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2333 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2334 // If the variable is implicitly firstprivate and scalar - capture by
2335 // copy
2336 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2337 DSAStack->getDefaultDSA() == DSA_private) &&
2338 !DSAStack->hasExplicitDSA(
2339 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2340 Level) &&
2341 !DSAStack->isLoopControlVariable(D, Level).first);
2342 }
2343
2344 // When passing data by copy, we need to make sure it fits the uintptr size
2345 // and alignment, because the runtime library only deals with uintptr types.
2346 // If it does not fit the uintptr size, we need to pass the data by reference
2347 // instead.
2348 if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) >
2350 Ctx.getAlignOfGlobalVarInChars(Ty, dyn_cast<VarDecl>(D)) >
2351 Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2352 IsByRef = true;
2353 }
2354
2355 return IsByRef;
2356}
2357
2358unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2359 assert(getLangOpts().OpenMP);
2360 return DSAStack->getNestingLevel();
2361}
2362
2364 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2365 DSAStack->isUntiedRegion();
2366}
2367
2369 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2370 !DSAStack->isClauseParsingMode()) ||
2371 DSAStack->hasDirective(
2373 SourceLocation) -> bool {
2375 },
2376 false);
2377}
2378
2380 // Only rebuild for Field.
2381 if (!isa<FieldDecl>(D))
2382 return false;
2383 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2384 D,
2385 [](OpenMPClauseKind C, bool AppliedToPointee,
2386 DefaultDataSharingAttributes DefaultAttr) {
2387 return isOpenMPPrivate(C) && !AppliedToPointee &&
2388 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2389 },
2390 [](OpenMPDirectiveKind) { return true; },
2391 DSAStack->isClauseParsingMode());
2392 if (DVarPrivate.CKind != OMPC_unknown)
2393 return true;
2394 return false;
2395}
2396
2398 Expr *CaptureExpr, bool WithInit,
2399 DeclContext *CurContext,
2400 bool AsExpression);
2401
2403 unsigned StopAt) {
2404 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2405 D = getCanonicalDecl(D);
2406
2407 auto *VD = dyn_cast<VarDecl>(D);
2408 // Do not capture constexpr variables.
2409 if (VD && VD->isConstexpr())
2410 return nullptr;
2411
2412 // If we want to determine whether the variable should be captured from the
2413 // perspective of the current capturing scope, and we've already left all the
2414 // capturing scopes of the top directive on the stack, check from the
2415 // perspective of its parent directive (if any) instead.
2416 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2417 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2418
2419 // If we are attempting to capture a global variable in a directive with
2420 // 'target' we return true so that this global is also mapped to the device.
2421 //
2422 if (VD && !VD->hasLocalStorage() &&
2423 (SemaRef.getCurCapturedRegion() || SemaRef.getCurBlock() ||
2424 SemaRef.getCurLambda())) {
2426 DSAStackTy::DSAVarData DVarTop =
2427 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2428 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2429 return VD;
2430 // If the declaration is enclosed in a 'declare target' directive,
2431 // then it should not be captured.
2432 //
2433 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2434 return nullptr;
2435 CapturedRegionScopeInfo *CSI = nullptr;
2436 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2437 llvm::reverse(SemaRef.FunctionScopes),
2438 CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2439 : 0)) {
2440 if (!isa<CapturingScopeInfo>(FSI))
2441 return nullptr;
2442 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2443 if (RSI->CapRegionKind == CR_OpenMP) {
2444 CSI = RSI;
2445 break;
2446 }
2447 }
2448 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2451 DSAStack->getDirective(CSI->OpenMPLevel));
2452 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2453 return VD;
2454 }
2456 // Try to mark variable as declare target if it is used in capturing
2457 // regions.
2458 if (getLangOpts().OpenMP <= 45 &&
2459 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2461 return nullptr;
2462 }
2463 }
2464
2465 if (CheckScopeInfo) {
2466 bool OpenMPFound = false;
2467 for (unsigned I = StopAt + 1; I > 0; --I) {
2468 FunctionScopeInfo *FSI = SemaRef.FunctionScopes[I - 1];
2469 if (!isa<CapturingScopeInfo>(FSI))
2470 return nullptr;
2471 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2472 if (RSI->CapRegionKind == CR_OpenMP) {
2473 OpenMPFound = true;
2474 break;
2475 }
2476 }
2477 if (!OpenMPFound)
2478 return nullptr;
2479 }
2480
2481 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2482 (!DSAStack->isClauseParsingMode() ||
2483 DSAStack->getParentDirective() != OMPD_unknown)) {
2484 auto &&Info = DSAStack->isLoopControlVariable(D);
2485 if (Info.first ||
2486 (VD && VD->hasLocalStorage() &&
2487 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2488 (VD && DSAStack->isForceVarCapturing()))
2489 return VD ? VD : Info.second;
2490 DSAStackTy::DSAVarData DVarTop =
2491 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2492 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2493 (!VD || VD->hasLocalStorage() ||
2494 !(DVarTop.AppliedToPointee && DVarTop.CKind != OMPC_reduction)))
2495 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2496 // Threadprivate variables must not be captured.
2497 if (isOpenMPThreadPrivate(DVarTop.CKind))
2498 return nullptr;
2499 // The variable is not private or it is the variable in the directive with
2500 // default(none) clause and not used in any clause.
2501 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2502 D,
2503 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2504 return isOpenMPPrivate(C) && !AppliedToPointee;
2505 },
2506 [](OpenMPDirectiveKind) { return true; },
2507 DSAStack->isClauseParsingMode());
2508 // Global shared must not be captured.
2509 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2510 ((DSAStack->getDefaultDSA() != DSA_none &&
2511 DSAStack->getDefaultDSA() != DSA_private &&
2512 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2513 DVarTop.CKind == OMPC_shared))
2514 return nullptr;
2515 auto *FD = dyn_cast<FieldDecl>(D);
2516 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2517 !DVarPrivate.PrivateCopy) {
2518 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2519 D,
2520 [](OpenMPClauseKind C, bool AppliedToPointee,
2521 DefaultDataSharingAttributes DefaultAttr) {
2522 return isOpenMPPrivate(C) && !AppliedToPointee &&
2523 (DefaultAttr == DSA_firstprivate ||
2524 DefaultAttr == DSA_private);
2525 },
2526 [](OpenMPDirectiveKind) { return true; },
2527 DSAStack->isClauseParsingMode());
2528 if (DVarPrivate.CKind == OMPC_unknown)
2529 return nullptr;
2530
2531 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2532 if (VD)
2533 return VD;
2534 if (SemaRef.getCurrentThisType().isNull())
2535 return nullptr;
2536 Expr *ThisExpr = SemaRef.BuildCXXThisExpr(SourceLocation(),
2537 SemaRef.getCurrentThisType(),
2538 /*IsImplicit=*/true);
2539 const CXXScopeSpec CS = CXXScopeSpec();
2540 Expr *ME = SemaRef.BuildMemberExpr(
2541 ThisExpr, /*IsArrow=*/true, SourceLocation(),
2544 /*HadMultipleCandidates=*/false, DeclarationNameInfo(), FD->getType(),
2547 SemaRef, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2548 SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2549 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2551 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2552 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2553 return VD;
2554 }
2555 if (DVarPrivate.CKind != OMPC_unknown ||
2556 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2557 DSAStack->getDefaultDSA() == DSA_private ||
2558 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2559 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2560 }
2561 return nullptr;
2562}
2563
2564void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2565 unsigned Level) const {
2566 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2567}
2568
2570 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2571 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2572 DSAStack->loopInit();
2573}
2574
2576 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2577 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2578 DSAStack->resetPossibleLoopCounter();
2579 DSAStack->loopStart();
2580 }
2581}
2582
2584 unsigned CapLevel) const {
2585 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2586 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2587 (!DSAStack->isClauseParsingMode() ||
2588 DSAStack->getParentDirective() != OMPD_unknown)) {
2589 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2590 D,
2591 [](OpenMPClauseKind C, bool AppliedToPointee,
2592 DefaultDataSharingAttributes DefaultAttr) {
2593 return isOpenMPPrivate(C) && !AppliedToPointee &&
2594 DefaultAttr == DSA_private;
2595 },
2596 [](OpenMPDirectiveKind) { return true; },
2597 DSAStack->isClauseParsingMode());
2598 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2599 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2600 !DSAStack->isLoopControlVariable(D).first)
2601 return OMPC_private;
2602 }
2603 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2604 bool IsTriviallyCopyable =
2606 getASTContext()) &&
2607 !D->getType()
2611 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2613 getOpenMPCaptureRegions(CaptureRegions, DKind);
2614 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2615 (IsTriviallyCopyable ||
2616 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2617 if (DSAStack->hasExplicitDSA(
2618 D,
2619 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2620 Level, /*NotLastprivate=*/true))
2621 return OMPC_firstprivate;
2622 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2623 if (DVar.CKind != OMPC_shared &&
2624 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2625 DSAStack->addImplicitTaskFirstprivate(Level, D);
2626 return OMPC_firstprivate;
2627 }
2628 }
2629 }
2630 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2631 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2632 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2633 DSAStack->resetPossibleLoopCounter(D);
2634 DSAStack->loopStart();
2635 return OMPC_private;
2636 }
2637 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2638 DSAStack->isLoopControlVariable(D).first) &&
2639 !DSAStack->hasExplicitDSA(
2640 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2641 Level) &&
2642 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2643 return OMPC_private;
2644 }
2645 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2646 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2647 DSAStack->isForceVarCapturing() &&
2648 !DSAStack->hasExplicitDSA(
2649 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2650 Level))
2651 return OMPC_private;
2652 }
2653 // User-defined allocators are private since they must be defined in the
2654 // context of target region.
2655 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2656 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2657 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2658 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2659 return OMPC_private;
2660 return (DSAStack->hasExplicitDSA(
2661 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2662 Level) ||
2663 (DSAStack->isClauseParsingMode() &&
2664 DSAStack->getClauseParsingMode() == OMPC_private) ||
2665 // Consider taskgroup reduction descriptor variable a private
2666 // to avoid possible capture in the region.
2667 (DSAStack->hasExplicitDirective(
2668 [](OpenMPDirectiveKind K) {
2669 return K == OMPD_taskgroup ||
2670 ((isOpenMPParallelDirective(K) ||
2671 isOpenMPWorksharingDirective(K)) &&
2672 !isOpenMPSimdDirective(K));
2673 },
2674 Level) &&
2675 DSAStack->isTaskgroupReductionRef(D, Level)))
2676 ? OMPC_private
2677 : OMPC_unknown;
2678}
2679
2681 unsigned Level) {
2682 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2683 D = getCanonicalDecl(D);
2684 OpenMPClauseKind OMPC = OMPC_unknown;
2685 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2686 const unsigned NewLevel = I - 1;
2687 if (DSAStack->hasExplicitDSA(
2688 D,
2689 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2690 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2691 OMPC = K;
2692 return true;
2693 }
2694 return false;
2695 },
2696 NewLevel))
2697 break;
2698 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2699 D, NewLevel,
2701 OpenMPClauseKind) { return true; })) {
2702 OMPC = OMPC_map;
2703 break;
2704 }
2705 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2706 NewLevel)) {
2707 OMPC = OMPC_map;
2708 if (DSAStack->mustBeFirstprivateAtLevel(
2710 OMPC = OMPC_firstprivate;
2711 break;
2712 }
2713 }
2714 if (OMPC != OMPC_unknown)
2715 FD->addAttr(
2716 OMPCaptureKindAttr::CreateImplicit(getASTContext(), unsigned(OMPC)));
2717}
2718
2720 unsigned CaptureLevel) const {
2721 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2722 // Return true if the current level is no longer enclosed in a target region.
2723
2725 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2726 const auto *VD = dyn_cast<VarDecl>(D);
2727 return VD && !VD->hasLocalStorage() &&
2728 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2729 Level) &&
2730 Regions[CaptureLevel] != OMPD_task;
2731}
2732
2734 unsigned CaptureLevel) const {
2735 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2736 // Return true if the current level is no longer enclosed in a target region.
2737
2738 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2739 if (!VD->hasLocalStorage()) {
2741 return true;
2742 DSAStackTy::DSAVarData TopDVar =
2743 DSAStack->getTopDSA(D, /*FromParent=*/false);
2744 unsigned NumLevels =
2745 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2746 if (Level == 0)
2747 // non-file scope static variable with default(firstprivate)
2748 // should be global captured.
2749 return (NumLevels == CaptureLevel + 1 &&
2750 (TopDVar.CKind != OMPC_shared ||
2751 DSAStack->getDefaultDSA() == DSA_firstprivate));
2752 do {
2753 --Level;
2754 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2755 if (DVar.CKind != OMPC_shared)
2756 return true;
2757 } while (Level > 0);
2758 }
2759 }
2760 return true;
2761}
2762
2763void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2764
2766 OMPTraitInfo &TI) {
2767 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2768}
2769
2772 "Not in OpenMP declare variant scope!");
2773
2774 OMPDeclareVariantScopes.pop_back();
2775}
2776
2778 const FunctionDecl *Callee,
2779 SourceLocation Loc) {
2780 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2781 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2782 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2783 // Ignore host functions during device analysis.
2784 if (getLangOpts().OpenMPIsTargetDevice &&
2785 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2786 return;
2787 // Ignore nohost functions during host analysis.
2788 if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2789 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2790 return;
2791 const FunctionDecl *FD = Callee->getMostRecentDecl();
2792 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2793 if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2794 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2795 // Diagnose host function called during device codegen.
2796 StringRef HostDevTy =
2797 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2798 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2799 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2800 diag::note_omp_marked_device_type_here)
2801 << HostDevTy;
2802 return;
2803 }
2804 if (!getLangOpts().OpenMPIsTargetDevice &&
2805 !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2806 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2807 // In OpenMP 5.2 or later, if the function has a host variant then allow
2808 // that to be called instead
2809 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2810 for (OMPDeclareVariantAttr *A :
2811 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2812 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2813 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2814 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2815 OMPDeclareTargetDeclAttr::getDeviceType(
2816 VariantFD->getMostRecentDecl());
2817 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2818 return true;
2819 }
2820 return false;
2821 };
2822 if (getLangOpts().OpenMP >= 52 &&
2823 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2824 return;
2825 // Diagnose nohost function called during host codegen.
2826 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2827 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2828 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2829 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2830 diag::note_omp_marked_device_type_here)
2831 << NoHostDevTy;
2832 }
2833}
2834
2836 const DeclarationNameInfo &DirName,
2837 Scope *CurScope, SourceLocation Loc) {
2838 DSAStack->push(DKind, DirName, CurScope, Loc);
2839 SemaRef.PushExpressionEvaluationContext(
2841}
2842
2844 DSAStack->setClauseParsingMode(K);
2845}
2846
2848 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2849 SemaRef.CleanupVarDeclMarking();
2850}
2851
2852static std::pair<ValueDecl *, bool>
2853getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2854 SourceRange &ERange, bool AllowArraySection = false,
2855 bool AllowAssumedSizeArray = false, StringRef DiagType = "");
2856
2857/// Check consistency of the reduction clauses.
2858static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2859 ArrayRef<OMPClause *> Clauses) {
2860 bool InscanFound = false;
2861 SourceLocation InscanLoc;
2862 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2863 // A reduction clause without the inscan reduction-modifier may not appear on
2864 // a construct on which a reduction clause with the inscan reduction-modifier
2865 // appears.
2866 for (OMPClause *C : Clauses) {
2867 if (C->getClauseKind() != OMPC_reduction)
2868 continue;
2869 auto *RC = cast<OMPReductionClause>(C);
2870 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2871 InscanFound = true;
2872 InscanLoc = RC->getModifierLoc();
2873 continue;
2874 }
2875 if (RC->getModifier() == OMPC_REDUCTION_task) {
2876 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2877 // A reduction clause with the task reduction-modifier may only appear on
2878 // a parallel construct, a worksharing construct or a combined or
2879 // composite construct for which any of the aforementioned constructs is a
2880 // constituent construct and simd or loop are not constituent constructs.
2881 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2882 if (!(isOpenMPParallelDirective(CurDir) ||
2884 isOpenMPSimdDirective(CurDir))
2885 S.Diag(RC->getModifierLoc(),
2886 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2887 continue;
2888 }
2889 }
2890 if (InscanFound) {
2891 for (OMPClause *C : Clauses) {
2892 if (C->getClauseKind() != OMPC_reduction)
2893 continue;
2894 auto *RC = cast<OMPReductionClause>(C);
2895 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2896 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2897 ? RC->getBeginLoc()
2898 : RC->getModifierLoc(),
2899 diag::err_omp_inscan_reduction_expected);
2900 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2901 continue;
2902 }
2903 for (Expr *Ref : RC->varlist()) {
2904 assert(Ref && "NULL expr in OpenMP reduction clause.");
2905 SourceLocation ELoc;
2906 SourceRange ERange;
2907 Expr *SimpleRefExpr = Ref;
2908 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2909 /*AllowArraySection=*/true);
2910 ValueDecl *D = Res.first;
2911 if (!D)
2912 continue;
2913 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2914 S.Diag(Ref->getExprLoc(),
2915 diag::err_omp_reduction_not_inclusive_exclusive)
2916 << Ref->getSourceRange();
2917 }
2918 }
2919 }
2920 }
2921}
2922
2923static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2924 ArrayRef<OMPClause *> Clauses);
2925static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2926 bool WithInit);
2927
2928static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2929 const ValueDecl *D,
2930 const DSAStackTy::DSAVarData &DVar,
2931 bool IsLoopIterVar = false);
2932
2934 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2935 // A variable of class type (or array thereof) that appears in a lastprivate
2936 // clause requires an accessible, unambiguous default constructor for the
2937 // class type, unless the list item is also specified in a firstprivate
2938 // clause.
2939
2940 auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) {
2941 SmallVector<Expr *, 8> PrivateCopies;
2942 for (Expr *DE : Clause->varlist()) {
2943 if (DE->isValueDependent() || DE->isTypeDependent()) {
2944 PrivateCopies.push_back(nullptr);
2945 continue;
2946 }
2947 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2948 auto *VD = cast<VarDecl>(DRE->getDecl());
2950 const DSAStackTy::DSAVarData DVar =
2951 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2952 if (DVar.CKind != OMPC_lastprivate) {
2953 // The variable is also a firstprivate, so initialization sequence
2954 // for private copy is generated already.
2955 PrivateCopies.push_back(nullptr);
2956 continue;
2957 }
2958 // Generate helper private variable and initialize it with the
2959 // default value. The address of the original variable is replaced
2960 // by the address of the new private variable in CodeGen. This new
2961 // variable is not added to IdResolver, so the code in the OpenMP
2962 // region uses original variable for proper diagnostics.
2963 VarDecl *VDPrivate = buildVarDecl(
2964 SemaRef, DE->getExprLoc(), Type.getUnqualifiedType(), VD->getName(),
2965 VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2966 SemaRef.ActOnUninitializedDecl(VDPrivate);
2967 if (VDPrivate->isInvalidDecl()) {
2968 PrivateCopies.push_back(nullptr);
2969 continue;
2970 }
2971 PrivateCopies.push_back(buildDeclRefExpr(
2972 SemaRef, VDPrivate, DE->getType(), DE->getExprLoc()));
2973 }
2974 Clause->setPrivateCopies(PrivateCopies);
2975 };
2976
2977 auto FinalizeNontemporal = [&](OMPNontemporalClause *Clause) {
2978 // Finalize nontemporal clause by handling private copies, if any.
2979 SmallVector<Expr *, 8> PrivateRefs;
2980 for (Expr *RefExpr : Clause->varlist()) {
2981 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2982 SourceLocation ELoc;
2983 SourceRange ERange;
2984 Expr *SimpleRefExpr = RefExpr;
2985 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
2986 if (Res.second)
2987 // It will be analyzed later.
2988 PrivateRefs.push_back(RefExpr);
2989 ValueDecl *D = Res.first;
2990 if (!D)
2991 continue;
2992
2993 const DSAStackTy::DSAVarData DVar =
2994 DSAStack->getTopDSA(D, /*FromParent=*/false);
2995 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2996 : SimpleRefExpr);
2997 }
2998 Clause->setPrivateRefs(PrivateRefs);
2999 };
3000
3001 auto FinalizeAllocators = [&](OMPUsesAllocatorsClause *Clause) {
3002 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
3003 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
3004 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
3005 if (!DRE)
3006 continue;
3007 ValueDecl *VD = DRE->getDecl();
3008 if (!VD || !isa<VarDecl>(VD))
3009 continue;
3010 DSAStackTy::DSAVarData DVar =
3011 DSAStack->getTopDSA(VD, /*FromParent=*/false);
3012 // OpenMP [2.12.5, target Construct]
3013 // Memory allocators that appear in a uses_allocators clause cannot
3014 // appear in other data-sharing attribute clauses or data-mapping
3015 // attribute clauses in the same construct.
3016 Expr *MapExpr = nullptr;
3017 if (DVar.RefExpr ||
3018 DSAStack->checkMappableExprComponentListsForDecl(
3019 VD, /*CurrentRegionOnly=*/true,
3020 [VD, &MapExpr](
3022 MapExprComponents,
3024 auto MI = MapExprComponents.rbegin();
3025 auto ME = MapExprComponents.rend();
3026 if (MI != ME &&
3027 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
3028 VD->getCanonicalDecl()) {
3029 MapExpr = MI->getAssociatedExpression();
3030 return true;
3031 }
3032 return false;
3033 })) {
3034 Diag(D.Allocator->getExprLoc(), diag::err_omp_allocator_used_in_clauses)
3035 << D.Allocator->getSourceRange();
3036 if (DVar.RefExpr)
3038 else
3039 Diag(MapExpr->getExprLoc(), diag::note_used_here)
3040 << MapExpr->getSourceRange();
3041 }
3042 }
3043 };
3044
3045 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
3046 for (OMPClause *C : D->clauses()) {
3047 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
3048 FinalizeLastprivate(Clause);
3049 } else if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
3050 FinalizeNontemporal(Clause);
3051 } else if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
3052 FinalizeAllocators(Clause);
3053 }
3054 }
3055 // Check allocate clauses.
3056 if (!SemaRef.CurContext->isDependentContext())
3057 checkAllocateClauses(SemaRef, DSAStack, D->clauses());
3058 checkReductionClauses(SemaRef, DSAStack, D->clauses());
3059 }
3060
3061 DSAStack->pop();
3064}
3065
3066static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
3067 Expr *NumIterations, Sema &SemaRef,
3068 Scope *S, DSAStackTy *Stack);
3069
3070static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
3071 OMPLoopBasedDirective::HelperExprs &B,
3072 DSAStackTy *Stack) {
3073 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
3074 "loop exprs were not built");
3075
3076 if (SemaRef.CurContext->isDependentContext())
3077 return false;
3078
3079 // Finalize the clauses that need pre-built expressions for CodeGen.
3080 for (OMPClause *C : Clauses) {
3081 auto *LC = dyn_cast<OMPLinearClause>(C);
3082 if (!LC)
3083 continue;
3084 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
3085 B.NumIterations, SemaRef,
3086 SemaRef.getCurScope(), Stack))
3087 return true;
3088 }
3089
3090 return false;
3091}
3092
3093namespace {
3094
3095class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3096private:
3097 Sema &SemaRef;
3098
3099public:
3100 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3101 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3102 NamedDecl *ND = Candidate.getCorrectionDecl();
3103 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3104 return VD->hasGlobalStorage() &&
3105 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3106 SemaRef.getCurScope());
3107 }
3108 return false;
3109 }
3110
3111 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3112 return std::make_unique<VarDeclFilterCCC>(*this);
3113 }
3114};
3115
3116class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3117private:
3118 Sema &SemaRef;
3119
3120public:
3121 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3122 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3123 NamedDecl *ND = Candidate.getCorrectionDecl();
3124 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3125 isa<FunctionDecl>(ND))) {
3126 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3127 SemaRef.getCurScope());
3128 }
3129 return false;
3130 }
3131
3132 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3133 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3134 }
3135};
3136
3137} // namespace
3138
3140 CXXScopeSpec &ScopeSpec,
3141 const DeclarationNameInfo &Id,
3142 OpenMPDirectiveKind Kind) {
3143 ASTContext &Context = getASTContext();
3144 unsigned OMPVersion = getLangOpts().OpenMP;
3146 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
3147 /*ObjectType=*/QualType(),
3148 /*AllowBuiltinCreation=*/true);
3149
3150 if (Lookup.isAmbiguous())
3151 return ExprError();
3152
3153 VarDecl *VD;
3154 if (!Lookup.isSingleResult()) {
3155 VarDeclFilterCCC CCC(SemaRef);
3156 if (TypoCorrection Corrected =
3157 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
3159 SemaRef.diagnoseTypo(
3160 Corrected,
3161 SemaRef.PDiag(Lookup.empty() ? diag::err_undeclared_var_use_suggest
3162 : diag::err_omp_expected_var_arg_suggest)
3163 << Id.getName());
3164 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3165 } else {
3166 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3167 : diag::err_omp_expected_var_arg)
3168 << Id.getName();
3169 return ExprError();
3170 }
3171 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3172 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3173 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3174 return ExprError();
3175 }
3176 Lookup.suppressDiagnostics();
3177
3178 // OpenMP [2.9.2, Syntax, C/C++]
3179 // Variables must be file-scope, namespace-scope, or static block-scope.
3180 if ((Kind == OMPD_threadprivate || Kind == OMPD_groupprivate) &&
3181 !VD->hasGlobalStorage()) {
3182 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3183 << getOpenMPDirectiveName(Kind, OMPVersion) << !VD->isStaticLocal();
3184 bool IsDecl =
3186 Diag(VD->getLocation(),
3187 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3188 << VD;
3189 return ExprError();
3190 }
3191
3192 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3193 NamedDecl *ND = CanonicalVD;
3194 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3195 // A threadprivate or groupprivate directive for file-scope variables must
3196 // appear outside any definition or declaration.
3197 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3198 !SemaRef.getCurLexicalContext()->isTranslationUnit()) {
3199 Diag(Id.getLoc(), diag::err_omp_var_scope)
3200 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3201 bool IsDecl =
3203 Diag(VD->getLocation(),
3204 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3205 << VD;
3206 return ExprError();
3207 }
3208 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3209 // A threadprivate or groupprivate directive for static class member
3210 // variables must appear in the class definition, in the same scope in which
3211 // the member variables are declared.
3212 if (CanonicalVD->isStaticDataMember() &&
3213 !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) {
3214 Diag(Id.getLoc(), diag::err_omp_var_scope)
3215 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3216 bool IsDecl =
3218 Diag(VD->getLocation(),
3219 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3220 << VD;
3221 return ExprError();
3222 }
3223 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3224 // A threadprivate or groupprivate directive for namespace-scope variables
3225 // must appear outside any definition or declaration other than the
3226 // namespace definition itself.
3227 if (CanonicalVD->getDeclContext()->isNamespace() &&
3228 (!SemaRef.getCurLexicalContext()->isFileContext() ||
3229 !SemaRef.getCurLexicalContext()->Encloses(
3230 CanonicalVD->getDeclContext()))) {
3231 Diag(Id.getLoc(), diag::err_omp_var_scope)
3232 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3233 bool IsDecl =
3235 Diag(VD->getLocation(),
3236 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3237 << VD;
3238 return ExprError();
3239 }
3240 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3241 // A threadprivate or groupprivate directive for static block-scope
3242 // variables must appear in the scope of the variable and not in a nested
3243 // scope.
3244 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3245 !SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(), CurScope)) {
3246 Diag(Id.getLoc(), diag::err_omp_var_scope)
3247 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3248 bool IsDecl =
3250 Diag(VD->getLocation(),
3251 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3252 << VD;
3253 return ExprError();
3254 }
3255
3256 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3257 // A threadprivate or groupprivate directive must lexically precede all
3258 // references to any of the variables in its list.
3259 if ((Kind == OMPD_threadprivate && VD->isUsed() &&
3260 !DSAStack->isThreadPrivate(VD)) ||
3261 (Kind == OMPD_groupprivate && VD->isUsed())) {
3262 Diag(Id.getLoc(), diag::err_omp_var_used)
3263 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3264 return ExprError();
3265 }
3266
3267 QualType ExprType = VD->getType().getNonReferenceType();
3269 SourceLocation(), VD,
3270 /*RefersToEnclosingVariableOrCapture=*/false,
3271 Id.getLoc(), ExprType, VK_LValue);
3272}
3273
3276 ArrayRef<Expr *> VarList) {
3277 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3278 SemaRef.CurContext->addDecl(D);
3280 }
3281 return nullptr;
3282}
3283
3286 ArrayRef<Expr *> VarList) {
3287 if (!getLangOpts().OpenMP || getLangOpts().OpenMP < 60) {
3288 Diag(Loc, diag::err_omp_unexpected_directive)
3289 << getOpenMPDirectiveName(OMPD_groupprivate, getLangOpts().OpenMP);
3290 return nullptr;
3291 }
3292 if (OMPGroupPrivateDecl *D = CheckOMPGroupPrivateDecl(Loc, VarList)) {
3293 SemaRef.CurContext->addDecl(D);
3295 }
3296 return nullptr;
3297}
3298
3299namespace {
3300class LocalVarRefChecker final
3301 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3302 Sema &SemaRef;
3303
3304public:
3305 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3306 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3307 if (VD->hasLocalStorage()) {
3308 SemaRef.Diag(E->getBeginLoc(),
3309 diag::err_omp_local_var_in_threadprivate_init)
3310 << E->getSourceRange();
3311 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3312 << VD << VD->getSourceRange();
3313 return true;
3314 }
3315 }
3316 return false;
3317 }
3318 bool VisitStmt(const Stmt *S) {
3319 for (const Stmt *Child : S->children()) {
3320 if (Child && Visit(Child))
3321 return true;
3322 }
3323 return false;
3324 }
3325 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3326};
3327} // namespace
3328
3329OMPThreadPrivateDecl *
3331 ArrayRef<Expr *> VarList) {
3332 ASTContext &Context = getASTContext();
3334 for (Expr *RefExpr : VarList) {
3335 auto *DE = cast<DeclRefExpr>(RefExpr);
3336 auto *VD = cast<VarDecl>(DE->getDecl());
3337 SourceLocation ILoc = DE->getExprLoc();
3338
3339 // Mark variable as used.
3340 VD->setReferenced();
3341 VD->markUsed(Context);
3342
3343 QualType QType = VD->getType();
3344 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3345 // It will be analyzed later.
3346 Vars.push_back(DE);
3347 continue;
3348 }
3349
3350 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3351 // A threadprivate variable must not have an incomplete type.
3352 if (SemaRef.RequireCompleteType(
3353 ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) {
3354 continue;
3355 }
3356
3357 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3358 // A threadprivate variable must not have a reference type.
3359 if (VD->getType()->isReferenceType()) {
3360 unsigned OMPVersion = getLangOpts().OpenMP;
3361 Diag(ILoc, diag::err_omp_ref_type_arg)
3362 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion)
3363 << VD->getType();
3364 bool IsDecl =
3366 Diag(VD->getLocation(),
3367 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3368 << VD;
3369 continue;
3370 }
3371
3372 // Check if this is a TLS variable. If TLS is not being supported, produce
3373 // the corresponding diagnostic.
3374 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3375 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3376 getLangOpts().OpenMPUseTLS &&
3377 getASTContext().getTargetInfo().isTLSSupported())) ||
3378 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3379 !VD->isLocalVarDecl())) {
3380 Diag(ILoc, diag::err_omp_var_thread_local)
3381 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3382 bool IsDecl =
3384 Diag(VD->getLocation(),
3385 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3386 << VD;
3387 continue;
3388 }
3389
3390 // Check if initial value of threadprivate variable reference variable with
3391 // local storage (it is not supported by runtime).
3392 if (const Expr *Init = VD->getAnyInitializer()) {
3393 LocalVarRefChecker Checker(SemaRef);
3394 if (Checker.Visit(Init))
3395 continue;
3396 }
3397
3398 Vars.push_back(RefExpr);
3399 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3400 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3401 Context, SourceRange(Loc, Loc)));
3402 if (ASTMutationListener *ML = Context.getASTMutationListener())
3403 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3404 }
3405 OMPThreadPrivateDecl *D = nullptr;
3406 if (!Vars.empty()) {
3407 D = OMPThreadPrivateDecl::Create(Context, SemaRef.getCurLexicalContext(),
3408 Loc, Vars);
3409 D->setAccess(AS_public);
3410 }
3411 return D;
3412}
3413
3416 ArrayRef<Expr *> VarList) {
3417 ASTContext &Context = getASTContext();
3419 for (Expr *RefExpr : VarList) {
3420 auto *DE = cast<DeclRefExpr>(RefExpr);
3421 auto *VD = cast<VarDecl>(DE->getDecl());
3422 SourceLocation ILoc = DE->getExprLoc();
3423
3424 // Mark variable as used.
3425 VD->setReferenced();
3426 VD->markUsed(Context);
3427
3428 QualType QType = VD->getType();
3429 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3430 // It will be analyzed later.
3431 Vars.push_back(DE);
3432 continue;
3433 }
3434
3435 // OpenMP groupprivate restrictions:
3436 // A groupprivate variable must not have an incomplete type.
3437 if (SemaRef.RequireCompleteType(
3438 ILoc, VD->getType(), diag::err_omp_groupprivate_incomplete_type)) {
3439 continue;
3440 }
3441
3442 // A groupprivate variable must not have a reference type.
3443 if (VD->getType()->isReferenceType()) {
3444 Diag(ILoc, diag::err_omp_ref_type_arg)
3445 << getOpenMPDirectiveName(OMPD_groupprivate) << VD->getType();
3446 bool IsDecl =
3448 Diag(VD->getLocation(),
3449 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3450 << VD;
3451 continue;
3452 }
3453
3454 // A variable that is declared with an initializer must not appear in a
3455 // groupprivate directive.
3456 if (VD->getAnyInitializer()) {
3457 Diag(ILoc, diag::err_omp_groupprivate_with_initializer)
3458 << VD->getDeclName();
3459 bool IsDecl =
3461 Diag(VD->getLocation(),
3462 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3463 << VD;
3464 continue;
3465 }
3466
3467 Vars.push_back(RefExpr);
3468 DSAStack->addDSA(VD, DE, OMPC_groupprivate);
3469 VD->addAttr(OMPGroupPrivateDeclAttr::CreateImplicit(Context,
3470 SourceRange(Loc, Loc)));
3471 if (ASTMutationListener *ML = Context.getASTMutationListener())
3472 ML->DeclarationMarkedOpenMPGroupPrivate(VD);
3473 }
3474 OMPGroupPrivateDecl *D = nullptr;
3475 if (!Vars.empty()) {
3476 D = OMPGroupPrivateDecl::Create(Context, SemaRef.getCurLexicalContext(),
3477 Loc, Vars);
3478 D->setAccess(AS_public);
3479 }
3480 return D;
3481}
3482
3483static OMPAllocateDeclAttr::AllocatorTypeTy
3484getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3485 if (!Allocator)
3486 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3487 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3488 Allocator->isInstantiationDependent() ||
3490 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3491 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3492 llvm::FoldingSetNodeID AEId;
3493 const Expr *AE = Allocator->IgnoreParenImpCasts();
3494 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3495 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3496 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3497 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3498 llvm::FoldingSetNodeID DAEId;
3499 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3500 /*Canonical=*/true);
3501 if (AEId == DAEId) {
3502 AllocatorKindRes = AllocatorKind;
3503 break;
3504 }
3505 }
3506 return AllocatorKindRes;
3507}
3508
3510 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3511 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3512 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3513 return false;
3514 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3515 Expr *PrevAllocator = A->getAllocator();
3516 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3517 getAllocatorKind(S, Stack, PrevAllocator);
3518 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3519 if (AllocatorsMatch &&
3520 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3521 Allocator && PrevAllocator) {
3522 const Expr *AE = Allocator->IgnoreParenImpCasts();
3523 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3524 llvm::FoldingSetNodeID AEId, PAEId;
3525 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3526 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3527 AllocatorsMatch = AEId == PAEId;
3528 }
3529 if (!AllocatorsMatch) {
3530 SmallString<256> AllocatorBuffer;
3531 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3532 if (Allocator)
3533 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3534 SmallString<256> PrevAllocatorBuffer;
3535 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3536 if (PrevAllocator)
3537 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3538 S.getPrintingPolicy());
3539
3540 SourceLocation AllocatorLoc =
3541 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3542 SourceRange AllocatorRange =
3543 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3544 SourceLocation PrevAllocatorLoc =
3545 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3546 SourceRange PrevAllocatorRange =
3547 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3548 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3549 << (Allocator ? 1 : 0) << AllocatorStream.str()
3550 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3551 << AllocatorRange;
3552 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3553 << PrevAllocatorRange;
3554 return true;
3555 }
3556 return false;
3557}
3558
3559static void
3561 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3562 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3563 if (VD->hasAttr<OMPAllocateDeclAttr>())
3564 return;
3565 if (Alignment &&
3566 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3567 Alignment->isInstantiationDependent() ||
3568 Alignment->containsUnexpandedParameterPack()))
3569 // Apply later when we have a usable value.
3570 return;
3571 if (Allocator &&
3572 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3573 Allocator->isInstantiationDependent() ||
3574 Allocator->containsUnexpandedParameterPack()))
3575 return;
3576 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3577 Allocator, Alignment, SR);
3578 VD->addAttr(A);
3580 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3581}
3582
3585 DeclContext *Owner) {
3586 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3587 Expr *Alignment = nullptr;
3588 Expr *Allocator = nullptr;
3589 if (Clauses.empty()) {
3590 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3591 // allocate directives that appear in a target region must specify an
3592 // allocator clause unless a requires directive with the dynamic_allocators
3593 // clause is present in the same compilation unit.
3594 if (getLangOpts().OpenMPIsTargetDevice &&
3595 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3596 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3597 } else {
3598 for (const OMPClause *C : Clauses)
3599 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3600 Allocator = AC->getAllocator();
3601 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3602 Alignment = AC->getAlignment();
3603 else
3604 llvm_unreachable("Unexpected clause on allocate directive");
3605 }
3606 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3607 getAllocatorKind(SemaRef, DSAStack, Allocator);
3609 for (Expr *RefExpr : VarList) {
3610 auto *DE = cast<DeclRefExpr>(RefExpr);
3611 auto *VD = cast<VarDecl>(DE->getDecl());
3612
3613 // Check if this is a TLS variable or global register.
3614 if (VD->getTLSKind() != VarDecl::TLS_None ||
3615 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3616 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3617 !VD->isLocalVarDecl()))
3618 continue;
3619
3620 // If the used several times in the allocate directive, the same allocator
3621 // must be used.
3623 AllocatorKind, Allocator))
3624 continue;
3625
3626 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3627 // If a list item has a static storage type, the allocator expression in the
3628 // allocator clause must be a constant expression that evaluates to one of
3629 // the predefined memory allocator values.
3630 if (Allocator && VD->hasGlobalStorage()) {
3631 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3632 Diag(Allocator->getExprLoc(),
3633 diag::err_omp_expected_predefined_allocator)
3634 << Allocator->getSourceRange();
3635 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3637 Diag(VD->getLocation(),
3638 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3639 << VD;
3640 continue;
3641 }
3642 }
3643
3644 Vars.push_back(RefExpr);
3645 applyOMPAllocateAttribute(SemaRef, VD, AllocatorKind, Allocator, Alignment,
3646 DE->getSourceRange());
3647 }
3648 if (Vars.empty())
3649 return nullptr;
3650 if (!Owner)
3651 Owner = SemaRef.getCurLexicalContext();
3652 auto *D = OMPAllocateDecl::Create(getASTContext(), Owner, Loc, Vars, Clauses);
3653 D->setAccess(AS_public);
3654 Owner->addDecl(D);
3656}
3657
3660 ArrayRef<OMPClause *> ClauseList) {
3661 OMPRequiresDecl *D = nullptr;
3662 if (!SemaRef.CurContext->isFileContext()) {
3663 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3664 } else {
3665 D = CheckOMPRequiresDecl(Loc, ClauseList);
3666 if (D) {
3667 SemaRef.CurContext->addDecl(D);
3668 DSAStack->addRequiresDecl(D);
3669 }
3670 }
3672}
3673
3675 OpenMPDirectiveKind DKind,
3676 ArrayRef<std::string> Assumptions,
3677 bool SkippedClauses) {
3678 if (!SkippedClauses && Assumptions.empty()) {
3679 unsigned OMPVersion = getLangOpts().OpenMP;
3680 Diag(Loc, diag::err_omp_no_clause_for_directive)
3681 << llvm::omp::getAllAssumeClauseOptions()
3682 << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion);
3683 }
3684
3685 auto *AA =
3686 OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc);
3687 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3688 OMPAssumeScoped.push_back(AA);
3689 return;
3690 }
3691
3692 // Global assumes without assumption clauses are ignored.
3693 if (Assumptions.empty())
3694 return;
3695
3696 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3697 "Unexpected omp assumption directive!");
3698 OMPAssumeGlobal.push_back(AA);
3699
3700 // The OMPAssumeGlobal scope above will take care of new declarations but
3701 // we also want to apply the assumption to existing ones, e.g., to
3702 // declarations in included headers. To this end, we traverse all existing
3703 // declaration contexts and annotate function declarations here.
3704 SmallVector<DeclContext *, 8> DeclContexts;
3705 auto *Ctx = SemaRef.CurContext;
3706 while (Ctx->getLexicalParent())
3707 Ctx = Ctx->getLexicalParent();
3708 DeclContexts.push_back(Ctx);
3709 while (!DeclContexts.empty()) {
3710 DeclContext *DC = DeclContexts.pop_back_val();
3711 for (auto *SubDC : DC->decls()) {
3712 if (SubDC->isInvalidDecl())
3713 continue;
3714 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3715 DeclContexts.push_back(CTD->getTemplatedDecl());
3716 llvm::append_range(DeclContexts, CTD->specializations());
3717 continue;
3718 }
3719 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3720 DeclContexts.push_back(DC);
3721 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3722 F->addAttr(AA);
3723 continue;
3724 }
3725 }
3726 }
3727}
3728
3730 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3731 OMPAssumeScoped.pop_back();
3732}
3733
3735 Stmt *AStmt,
3736 SourceLocation StartLoc,
3737 SourceLocation EndLoc) {
3738 if (!AStmt)
3739 return StmtError();
3740
3741 return OMPAssumeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
3742 AStmt);
3743}
3744
3747 ArrayRef<OMPClause *> ClauseList) {
3748 /// For target specific clauses, the requires directive cannot be
3749 /// specified after the handling of any of the target regions in the
3750 /// current compilation unit.
3751 ArrayRef<SourceLocation> TargetLocations =
3752 DSAStack->getEncounteredTargetLocs();
3753 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3754 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3755 for (const OMPClause *CNew : ClauseList) {
3756 // Check if any of the requires clauses affect target regions.
3761 Diag(Loc, diag::err_omp_directive_before_requires)
3762 << "target" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3763 for (SourceLocation TargetLoc : TargetLocations) {
3764 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3765 << "target";
3766 }
3767 } else if (!AtomicLoc.isInvalid() &&
3769 Diag(Loc, diag::err_omp_directive_before_requires)
3770 << "atomic" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3771 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3772 << "atomic";
3773 }
3774 }
3775 }
3776
3777 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3779 getASTContext(), SemaRef.getCurLexicalContext(), Loc, ClauseList);
3780 return nullptr;
3781}
3782
3783static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3784 const ValueDecl *D,
3785 const DSAStackTy::DSAVarData &DVar,
3786 bool IsLoopIterVar) {
3787 if (DVar.RefExpr) {
3788 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3789 << getOpenMPClauseNameForDiag(DVar.CKind);
3790 return;
3791 }
3792 enum {
3793 PDSA_StaticMemberShared,
3794 PDSA_StaticLocalVarShared,
3795 PDSA_LoopIterVarPrivate,
3796 PDSA_LoopIterVarLinear,
3797 PDSA_LoopIterVarLastprivate,
3798 PDSA_ConstVarShared,
3799 PDSA_GlobalVarShared,
3800 PDSA_TaskVarFirstprivate,
3801 PDSA_LocalVarPrivate,
3802 PDSA_Implicit
3803 } Reason = PDSA_Implicit;
3804 bool ReportHint = false;
3805 auto ReportLoc = D->getLocation();
3806 auto *VD = dyn_cast<VarDecl>(D);
3807 if (IsLoopIterVar) {
3808 if (DVar.CKind == OMPC_private)
3809 Reason = PDSA_LoopIterVarPrivate;
3810 else if (DVar.CKind == OMPC_lastprivate)
3811 Reason = PDSA_LoopIterVarLastprivate;
3812 else
3813 Reason = PDSA_LoopIterVarLinear;
3814 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3815 DVar.CKind == OMPC_firstprivate) {
3816 Reason = PDSA_TaskVarFirstprivate;
3817 ReportLoc = DVar.ImplicitDSALoc;
3818 } else if (VD && VD->isStaticLocal())
3819 Reason = PDSA_StaticLocalVarShared;
3820 else if (VD && VD->isStaticDataMember())
3821 Reason = PDSA_StaticMemberShared;
3822 else if (VD && VD->isFileVarDecl())
3823 Reason = PDSA_GlobalVarShared;
3824 else if (D->getType().isConstant(SemaRef.getASTContext()))
3825 Reason = PDSA_ConstVarShared;
3826 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3827 ReportHint = true;
3828 Reason = PDSA_LocalVarPrivate;
3829 }
3830 if (Reason != PDSA_Implicit) {
3831 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
3832 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3833 << Reason << ReportHint
3834 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
3835 } else if (DVar.ImplicitDSALoc.isValid()) {
3836 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3837 << getOpenMPClauseNameForDiag(DVar.CKind);
3838 }
3839}
3840
3843 bool IsAggregateOrDeclareTarget) {
3845 switch (M) {
3846 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3847 case OMPC_DEFAULTMAP_MODIFIER_storage:
3848 Kind = OMPC_MAP_alloc;
3849 break;
3850 case OMPC_DEFAULTMAP_MODIFIER_to:
3851 Kind = OMPC_MAP_to;
3852 break;
3853 case OMPC_DEFAULTMAP_MODIFIER_from:
3854 Kind = OMPC_MAP_from;
3855 break;
3856 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3857 Kind = OMPC_MAP_tofrom;
3858 break;
3859 case OMPC_DEFAULTMAP_MODIFIER_present:
3860 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3861 // If implicit-behavior is present, each variable referenced in the
3862 // construct in the category specified by variable-category is treated as if
3863 // it had been listed in a map clause with the map-type of alloc and
3864 // map-type-modifier of present.
3865 Kind = OMPC_MAP_alloc;
3866 break;
3867 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3868 case OMPC_DEFAULTMAP_MODIFIER_private:
3870 llvm_unreachable("Unexpected defaultmap implicit behavior");
3871 case OMPC_DEFAULTMAP_MODIFIER_none:
3872 case OMPC_DEFAULTMAP_MODIFIER_default:
3874 // IsAggregateOrDeclareTarget could be true if:
3875 // 1. the implicit behavior for aggregate is tofrom
3876 // 2. it's a declare target link
3877 if (IsAggregateOrDeclareTarget) {
3878 Kind = OMPC_MAP_tofrom;
3879 break;
3880 }
3881 llvm_unreachable("Unexpected defaultmap implicit behavior");
3882 }
3883 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3884 return Kind;
3885}
3886
3887namespace {
3888struct VariableImplicitInfo {
3889 static const unsigned MapKindNum = OMPC_MAP_unknown;
3890 static const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3891
3892 llvm::SetVector<Expr *> Privates;
3893 llvm::SetVector<Expr *> Firstprivates;
3894 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3895 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3896 MapModifiers[DefaultmapKindNum];
3897};
3898
3899class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3900 DSAStackTy *Stack;
3901 Sema &SemaRef;
3902 OpenMPDirectiveKind DKind = OMPD_unknown;
3903 bool ErrorFound = false;
3904 bool TryCaptureCXXThisMembers = false;
3905 CapturedStmt *CS = nullptr;
3906
3907 VariableImplicitInfo ImpInfo;
3908 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3909 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3910
3911 void VisitSubCaptures(OMPExecutableDirective *S) {
3912 // Check implicitly captured variables.
3913 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3914 return;
3915 if (S->getDirectiveKind() == OMPD_atomic ||
3916 S->getDirectiveKind() == OMPD_critical ||
3917 S->getDirectiveKind() == OMPD_section ||
3918 S->getDirectiveKind() == OMPD_master ||
3919 S->getDirectiveKind() == OMPD_masked ||
3920 S->getDirectiveKind() == OMPD_scope ||
3921 S->getDirectiveKind() == OMPD_assume ||
3922 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3923 Visit(S->getAssociatedStmt());
3924 return;
3925 }
3926 visitSubCaptures(S->getInnermostCapturedStmt());
3927 // Try to capture inner this->member references to generate correct mappings
3928 // and diagnostics.
3929 if (TryCaptureCXXThisMembers ||
3931 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3932 [](const CapturedStmt::Capture &C) {
3933 return C.capturesThis();
3934 }))) {
3935 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3936 TryCaptureCXXThisMembers = true;
3937 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3938 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3939 }
3940 // In tasks firstprivates are not captured anymore, need to analyze them
3941 // explicitly.
3942 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3943 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3944 for (OMPClause *C : S->clauses())
3945 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3946 for (Expr *Ref : FC->varlist())
3947 Visit(Ref);
3948 }
3949 }
3950 }
3951
3952public:
3953 void VisitDeclRefExpr(DeclRefExpr *E) {
3954 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3958 return;
3959 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3960 // Check the datasharing rules for the expressions in the clauses.
3961 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3962 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3963 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3964 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3965 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3966 Visit(CED->getInit());
3967 return;
3968 }
3969 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3970 // Do not analyze internal variables and do not enclose them into
3971 // implicit clauses.
3972 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3973 return;
3974 VD = VD->getCanonicalDecl();
3975 // Skip internally declared variables.
3976 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3977 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3978 !Stack->isImplicitTaskFirstprivate(VD))
3979 return;
3980 // Skip allocators in uses_allocators clauses.
3981 if (Stack->isUsesAllocatorsDecl(VD))
3982 return;
3983
3984 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3985 // Check if the variable has explicit DSA set and stop analysis if it so.
3986 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3987 return;
3988
3989 // Skip internally declared static variables.
3990 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3991 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3992 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3993 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3994 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3995 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3996 !Stack->isImplicitTaskFirstprivate(VD))
3997 return;
3998
3999 SourceLocation ELoc = E->getExprLoc();
4000 // The default(none) clause requires that each variable that is referenced
4001 // in the construct, and does not have a predetermined data-sharing
4002 // attribute, must have its data-sharing attribute explicitly determined
4003 // by being listed in a data-sharing attribute clause.
4004 if (DVar.CKind == OMPC_unknown &&
4005 (Stack->getDefaultDSA() == DSA_none ||
4006 Stack->getDefaultDSA() == DSA_private ||
4007 Stack->getDefaultDSA() == DSA_firstprivate) &&
4008 isImplicitOrExplicitTaskingRegion(DKind) &&
4009 VarsWithInheritedDSA.count(VD) == 0) {
4010 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
4011 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
4012 Stack->getDefaultDSA() == DSA_private)) {
4013 DSAStackTy::DSAVarData DVar =
4014 Stack->getImplicitDSA(VD, /*FromParent=*/false);
4015 InheritedDSA = DVar.CKind == OMPC_unknown;
4016 }
4017 if (InheritedDSA)
4018 VarsWithInheritedDSA[VD] = E;
4019 if (Stack->getDefaultDSA() == DSA_none)
4020 return;
4021 }
4022
4023 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
4024 // If implicit-behavior is none, each variable referenced in the
4025 // construct that does not have a predetermined data-sharing attribute
4026 // and does not appear in a to or link clause on a declare target
4027 // directive must be listed in a data-mapping attribute clause, a
4028 // data-sharing attribute clause (including a data-sharing attribute
4029 // clause on a combined construct where target. is one of the
4030 // constituent constructs), or an is_device_ptr clause.
4031 OpenMPDefaultmapClauseKind ClauseKind =
4033 if (SemaRef.getLangOpts().OpenMP >= 50) {
4034 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
4035 OMPC_DEFAULTMAP_MODIFIER_none;
4036 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
4037 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
4038 // Only check for data-mapping attribute and is_device_ptr here
4039 // since we have already make sure that the declaration does not
4040 // have a data-sharing attribute above
4041 if (!Stack->checkMappableExprComponentListsForDecl(
4042 VD, /*CurrentRegionOnly=*/true,
4044 MapExprComponents,
4046 auto MI = MapExprComponents.rbegin();
4047 auto ME = MapExprComponents.rend();
4048 return MI != ME && MI->getAssociatedDeclaration() == VD;
4049 })) {
4050 VarsWithInheritedDSA[VD] = E;
4051 return;
4052 }
4053 }
4054 }
4055 if (SemaRef.getLangOpts().OpenMP > 50) {
4056 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
4057 OMPC_DEFAULTMAP_MODIFIER_present;
4058 if (IsModifierPresent) {
4059 if (!llvm::is_contained(ImpInfo.MapModifiers[ClauseKind],
4060 OMPC_MAP_MODIFIER_present)) {
4061 ImpInfo.MapModifiers[ClauseKind].push_back(
4062 OMPC_MAP_MODIFIER_present);
4063 }
4064 }
4065 }
4066
4068 !Stack->isLoopControlVariable(VD).first) {
4069 if (!Stack->checkMappableExprComponentListsForDecl(
4070 VD, /*CurrentRegionOnly=*/true,
4072 StackComponents,
4074 if (SemaRef.LangOpts.OpenMP >= 50)
4075 return !StackComponents.empty();
4076 // Variable is used if it has been marked as an array, array
4077 // section, array shaping or the variable itself.
4078 return StackComponents.size() == 1 ||
4079 llvm::all_of(
4080 llvm::drop_begin(llvm::reverse(StackComponents)),
4081 [](const OMPClauseMappableExprCommon::
4082 MappableComponent &MC) {
4083 return MC.getAssociatedDeclaration() ==
4084 nullptr &&
4085 (isa<ArraySectionExpr>(
4086 MC.getAssociatedExpression()) ||
4087 isa<OMPArrayShapingExpr>(
4088 MC.getAssociatedExpression()) ||
4089 isa<ArraySubscriptExpr>(
4090 MC.getAssociatedExpression()));
4091 });
4092 })) {
4093 bool IsFirstprivate = false;
4094 // By default lambdas are captured as firstprivates.
4095 if (const auto *RD =
4097 IsFirstprivate = RD->isLambda();
4098 IsFirstprivate =
4099 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
4100 if (IsFirstprivate) {
4101 ImpInfo.Firstprivates.insert(E);
4102 } else {
4104 Stack->getDefaultmapModifier(ClauseKind);
4105 if (M == OMPC_DEFAULTMAP_MODIFIER_private) {
4106 ImpInfo.Privates.insert(E);
4107 } else {
4109 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
4110 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
4111 }
4112 }
4113 return;
4114 }
4115 }
4116
4117 // OpenMP [2.9.3.6, Restrictions, p.2]
4118 // A list item that appears in a reduction clause of the innermost
4119 // enclosing worksharing or parallel construct may not be accessed in an
4120 // explicit task.
4121 DVar = Stack->hasInnermostDSA(
4122 VD,
4123 [](OpenMPClauseKind C, bool AppliedToPointee) {
4124 return C == OMPC_reduction && !AppliedToPointee;
4125 },
4126 [](OpenMPDirectiveKind K) {
4127 return isOpenMPParallelDirective(K) ||
4129 },
4130 /*FromParent=*/true);
4131 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4132 ErrorFound = true;
4133 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4134 reportOriginalDsa(SemaRef, Stack, VD, DVar);
4135 return;
4136 }
4137
4138 // Define implicit data-sharing attributes for task.
4139 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
4140 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
4141 (((Stack->getDefaultDSA() == DSA_firstprivate &&
4142 DVar.CKind == OMPC_firstprivate) ||
4143 (Stack->getDefaultDSA() == DSA_private &&
4144 DVar.CKind == OMPC_private)) &&
4145 !DVar.RefExpr)) &&
4146 !Stack->isLoopControlVariable(VD).first) {
4147 if (Stack->getDefaultDSA() == DSA_private)
4148 ImpInfo.Privates.insert(E);
4149 else
4150 ImpInfo.Firstprivates.insert(E);
4151 return;
4152 }
4153
4154 // Store implicitly used globals with declare target link for parent
4155 // target.
4156 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
4157 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
4158 Stack->addToParentTargetRegionLinkGlobals(E);
4159 return;
4160 }
4161 }
4162 }
4163 void VisitMemberExpr(MemberExpr *E) {
4164 if (E->isTypeDependent() || E->isValueDependent() ||
4166 return;
4167 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
4168 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
4169 if (!FD)
4170 return;
4171 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
4172 // Check if the variable has explicit DSA set and stop analysis if it
4173 // so.
4174 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
4175 return;
4176
4178 !Stack->isLoopControlVariable(FD).first &&
4179 !Stack->checkMappableExprComponentListsForDecl(
4180 FD, /*CurrentRegionOnly=*/true,
4182 StackComponents,
4184 return isa<CXXThisExpr>(
4185 cast<MemberExpr>(
4186 StackComponents.back().getAssociatedExpression())
4187 ->getBase()
4188 ->IgnoreParens());
4189 })) {
4190 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
4191 // A bit-field cannot appear in a map clause.
4192 //
4193 if (FD->isBitField())
4194 return;
4195
4196 // Check to see if the member expression is referencing a class that
4197 // has already been explicitly mapped
4198 if (Stack->isClassPreviouslyMapped(TE->getType()))
4199 return;
4200
4202 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4203 OpenMPDefaultmapClauseKind ClauseKind =
4206 Modifier, /*IsAggregateOrDeclareTarget=*/true);
4207 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
4208 return;
4209 }
4210
4211 SourceLocation ELoc = E->getExprLoc();
4212 // OpenMP [2.9.3.6, Restrictions, p.2]
4213 // A list item that appears in a reduction clause of the innermost
4214 // enclosing worksharing or parallel construct may not be accessed in
4215 // an explicit task.
4216 DVar = Stack->hasInnermostDSA(
4217 FD,
4218 [](OpenMPClauseKind C, bool AppliedToPointee) {
4219 return C == OMPC_reduction && !AppliedToPointee;
4220 },
4221 [](OpenMPDirectiveKind K) {
4222 return isOpenMPParallelDirective(K) ||
4224 },
4225 /*FromParent=*/true);
4226 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4227 ErrorFound = true;
4228 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4229 reportOriginalDsa(SemaRef, Stack, FD, DVar);
4230 return;
4231 }
4232
4233 // Define implicit data-sharing attributes for task.
4234 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4235 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4236 !Stack->isLoopControlVariable(FD).first) {
4237 // Check if there is a captured expression for the current field in the
4238 // region. Do not mark it as firstprivate unless there is no captured
4239 // expression.
4240 // TODO: try to make it firstprivate.
4241 if (DVar.CKind != OMPC_unknown)
4242 ImpInfo.Firstprivates.insert(E);
4243 }
4244 return;
4245 }
4248 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4249 DKind, /*NoDiagnose=*/true))
4250 return;
4251 const auto *VD = cast<ValueDecl>(
4252 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4253 if (!Stack->checkMappableExprComponentListsForDecl(
4254 VD, /*CurrentRegionOnly=*/true,
4255 [&CurComponents](
4257 StackComponents,
4259 auto CCI = CurComponents.rbegin();
4260 auto CCE = CurComponents.rend();
4261 for (const auto &SC : llvm::reverse(StackComponents)) {
4262 // Do both expressions have the same kind?
4263 if (CCI->getAssociatedExpression()->getStmtClass() !=
4264 SC.getAssociatedExpression()->getStmtClass())
4265 if (!((isa<ArraySectionExpr>(
4266 SC.getAssociatedExpression()) ||
4267 isa<OMPArrayShapingExpr>(
4268 SC.getAssociatedExpression())) &&
4269 isa<ArraySubscriptExpr>(
4270 CCI->getAssociatedExpression())))
4271 return false;
4272
4273 const Decl *CCD = CCI->getAssociatedDeclaration();
4274 const Decl *SCD = SC.getAssociatedDeclaration();
4275 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4276 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4277 if (SCD != CCD)
4278 return false;
4279 std::advance(CCI, 1);
4280 if (CCI == CCE)
4281 break;
4282 }
4283 return true;
4284 })) {
4285 Visit(E->getBase());
4286 }
4287 } else if (!TryCaptureCXXThisMembers) {
4288 Visit(E->getBase());
4289 }
4290 }
4291 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4292 for (OMPClause *C : S->clauses()) {
4293 // Skip analysis of arguments of private clauses for task|target
4294 // directives.
4295 if (isa_and_nonnull<OMPPrivateClause>(C))
4296 continue;
4297 // Skip analysis of arguments of implicitly defined firstprivate clause
4298 // for task|target directives.
4299 // Skip analysis of arguments of implicitly defined map clause for target
4300 // directives.
4302 C->isImplicit() && !isOpenMPTaskingDirective(DKind))) {
4303 for (Stmt *CC : C->children()) {
4304 if (CC)
4305 Visit(CC);
4306 }
4307 }
4308 }
4309 // Check implicitly captured variables.
4310 VisitSubCaptures(S);
4311 }
4312
4313 void VisitOMPCanonicalLoopNestTransformationDirective(
4314 OMPCanonicalLoopNestTransformationDirective *S) {
4315 // Loop transformation directives do not introduce data sharing
4316 VisitStmt(S);
4317 }
4318
4319 void VisitCallExpr(CallExpr *S) {
4320 for (Stmt *C : S->arguments()) {
4321 if (C) {
4322 // Check implicitly captured variables in the task-based directives to
4323 // check if they must be firstprivatized.
4324 Visit(C);
4325 }
4326 }
4327 if (Expr *Callee = S->getCallee()) {
4328 auto *CI = Callee->IgnoreParenImpCasts();
4329 if (auto *CE = dyn_cast<MemberExpr>(CI))
4330 Visit(CE->getBase());
4331 else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4332 Visit(CE);
4333 }
4334 }
4335 void VisitStmt(Stmt *S) {
4336 for (Stmt *C : S->children()) {
4337 if (C) {
4338 // Check implicitly captured variables in the task-based directives to
4339 // check if they must be firstprivatized.
4340 Visit(C);
4341 }
4342 }
4343 }
4344
4345 void visitSubCaptures(CapturedStmt *S) {
4346 for (const CapturedStmt::Capture &Cap : S->captures()) {
4347 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4348 continue;
4349 VarDecl *VD = Cap.getCapturedVar();
4350 // Do not try to map the variable if it or its sub-component was mapped
4351 // already.
4353 Stack->checkMappableExprComponentListsForDecl(
4354 VD, /*CurrentRegionOnly=*/true,
4356 OpenMPClauseKind) { return true; }))
4357 continue;
4358 DeclRefExpr *DRE = buildDeclRefExpr(
4359 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4360 Cap.getLocation(), /*RefersToCapture=*/true);
4361 Visit(DRE);
4362 }
4363 }
4364 bool isErrorFound() const { return ErrorFound; }
4365 const VariableImplicitInfo &getImplicitInfo() const { return ImpInfo; }
4366 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4367 return VarsWithInheritedDSA;
4368 }
4369
4370 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4371 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4372 DKind = S->getCurrentDirective();
4373 // Process declare target link variables for the target directives.
4375 for (DeclRefExpr *E : Stack->getLinkGlobals())
4376 Visit(E);
4377 }
4378 }
4379};
4380} // namespace
4381
4382static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4383 OpenMPDirectiveKind DKind,
4384 bool ScopeEntry) {
4387 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4388 if (isOpenMPTeamsDirective(DKind))
4389 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4390 if (isOpenMPParallelDirective(DKind))
4391 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4393 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4394 if (isOpenMPSimdDirective(DKind))
4395 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4396 Stack->handleConstructTrait(Traits, ScopeEntry);
4397}
4398
4399static SmallVector<SemaOpenMP::CapturedParamNameType>
4400getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4401 ASTContext &Context = SemaRef.getASTContext();
4402 QualType KmpInt32Ty =
4403 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4404 QualType KmpInt32PtrTy =
4405 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4407 std::make_pair(".global_tid.", KmpInt32PtrTy),
4408 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4409 };
4410 if (LoopBoundSharing) {
4411 QualType KmpSizeTy = Context.getSizeType().withConst();
4412 Params.push_back(std::make_pair(".previous.lb.", KmpSizeTy));
4413 Params.push_back(std::make_pair(".previous.ub.", KmpSizeTy));
4414 }
4415
4416 // __context with shared vars
4417 Params.push_back(std::make_pair(StringRef(), QualType()));
4418 return Params;
4419}
4420
4421static SmallVector<SemaOpenMP::CapturedParamNameType>
4423 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4424}
4425
4426static SmallVector<SemaOpenMP::CapturedParamNameType>
4428 ASTContext &Context = SemaRef.getASTContext();
4429 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4430 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4431 QualType KmpInt32PtrTy =
4432 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4433 QualType Args[] = {VoidPtrTy};
4435 EPI.Variadic = true;
4436 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4438 std::make_pair(".global_tid.", KmpInt32Ty),
4439 std::make_pair(".part_id.", KmpInt32PtrTy),
4440 std::make_pair(".privates.", VoidPtrTy),
4441 std::make_pair(
4442 ".copy_fn.",
4443 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4444 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4445 std::make_pair(StringRef(), QualType()) // __context with shared vars
4446 };
4447 return Params;
4448}
4449
4450static SmallVector<SemaOpenMP::CapturedParamNameType>
4452 ASTContext &Context = SemaRef.getASTContext();
4454 if (SemaRef.getLangOpts().OpenMPIsTargetDevice) {
4455 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4456 Params.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4457 }
4458 // __context with shared vars
4459 Params.push_back(std::make_pair(StringRef(), QualType()));
4460 return Params;
4461}
4462
4463static SmallVector<SemaOpenMP::CapturedParamNameType>
4466 std::make_pair(StringRef(), QualType()) // __context with shared vars
4467 };
4468 return Params;
4469}
4470
4471static SmallVector<SemaOpenMP::CapturedParamNameType>
4473 ASTContext &Context = SemaRef.getASTContext();
4474 QualType KmpInt32Ty =
4475 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4476 QualType KmpUInt64Ty =
4477 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4478 QualType KmpInt64Ty =
4479 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4480 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4481 QualType KmpInt32PtrTy =
4482 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4483 QualType Args[] = {VoidPtrTy};
4485 EPI.Variadic = true;
4486 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4488 std::make_pair(".global_tid.", KmpInt32Ty),
4489 std::make_pair(".part_id.", KmpInt32PtrTy),
4490 std::make_pair(".privates.", VoidPtrTy),
4491 std::make_pair(
4492 ".copy_fn.",
4493 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4494 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4495 std::make_pair(".lb.", KmpUInt64Ty),
4496 std::make_pair(".ub.", KmpUInt64Ty),
4497 std::make_pair(".st.", KmpInt64Ty),
4498 std::make_pair(".liter.", KmpInt32Ty),
4499 std::make_pair(".reductions.", VoidPtrTy),
4500 std::make_pair(StringRef(), QualType()) // __context with shared vars
4501 };
4502 return Params;
4503}
4504
4506 Scope *CurScope, SourceLocation Loc) {
4508 getOpenMPCaptureRegions(Regions, DKind);
4509
4510 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(DKind);
4511
4512 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4513 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4514 SemaRef.getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4515 };
4516
4517 for (auto [Level, RKind] : llvm::enumerate(Regions)) {
4518 switch (RKind) {
4519 // All region kinds that can be returned from `getOpenMPCaptureRegions`
4520 // are listed here.
4521 case OMPD_parallel:
4523 Loc, CurScope, CR_OpenMP,
4524 getParallelRegionParams(SemaRef, LoopBoundSharing), Level);
4525 break;
4526 case OMPD_teams:
4527 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4528 getTeamsRegionParams(SemaRef), Level);
4529 break;
4530 case OMPD_task:
4531 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4532 getTaskRegionParams(SemaRef), Level);
4533 // Mark this captured region as inlined, because we don't use outlined
4534 // function directly.
4535 MarkAsInlined(SemaRef.getCurCapturedRegion());
4536 break;
4537 case OMPD_taskloop:
4538 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4539 getTaskloopRegionParams(SemaRef), Level);
4540 // Mark this captured region as inlined, because we don't use outlined
4541 // function directly.
4542 MarkAsInlined(SemaRef.getCurCapturedRegion());
4543 break;
4544 case OMPD_target:
4545 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4546 getTargetRegionParams(SemaRef), Level);
4547 break;
4548 case OMPD_unknown:
4549 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4550 getUnknownRegionParams(SemaRef));
4551 break;
4552 case OMPD_metadirective:
4553 case OMPD_nothing:
4554 default:
4555 llvm_unreachable("Unexpected capture region");
4556 }
4557 }
4558}
4559
4561 Scope *CurScope) {
4562 switch (DKind) {
4563 case OMPD_atomic:
4564 case OMPD_critical:
4565 case OMPD_masked:
4566 case OMPD_master:
4567 case OMPD_section:
4568 case OMPD_tile:
4569 case OMPD_stripe:
4570 case OMPD_unroll:
4571 case OMPD_reverse:
4572 case OMPD_interchange:
4573 case OMPD_fuse:
4574 case OMPD_assume:
4575 break;
4576 default:
4577 processCapturedRegions(SemaRef, DKind, CurScope,
4578 DSAStack->getConstructLoc());
4579 break;
4580 }
4581
4582 DSAStack->setContext(SemaRef.CurContext);
4583 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
4584}
4585
4586int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4587 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4588}
4589
4592 getOpenMPCaptureRegions(CaptureRegions, DKind);
4593 return CaptureRegions.size();
4594}
4595
4597 Expr *CaptureExpr, bool WithInit,
4598 DeclContext *CurContext,
4599 bool AsExpression) {
4600 assert(CaptureExpr);
4601 ASTContext &C = S.getASTContext();
4602 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4603 QualType Ty = Init->getType();
4604 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4605 if (S.getLangOpts().CPlusPlus) {
4606 Ty = C.getLValueReferenceType(Ty);
4607 } else {
4608 Ty = C.getPointerType(Ty);
4609 ExprResult Res =
4610 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4611 if (!Res.isUsable())
4612 return nullptr;
4613 Init = Res.get();
4614 }
4615 WithInit = true;
4616 }
4617 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4618 CaptureExpr->getBeginLoc());
4619 if (!WithInit)
4620 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4621 CurContext->addHiddenDecl(CED);
4623 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4624 return CED;
4625}
4626
4627static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4628 bool WithInit) {
4630 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4632 else
4633 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4634 S.CurContext,
4635 /*AsExpression=*/false);
4636 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4637 CaptureExpr->getExprLoc());
4638}
4639
4640static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4641 StringRef Name) {
4642 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4643 if (!Ref) {
4645 S, &S.getASTContext().Idents.get(Name), CaptureExpr,
4646 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4647 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4648 CaptureExpr->getExprLoc());
4649 }
4650 ExprResult Res = Ref;
4651 if (!S.getLangOpts().CPlusPlus &&
4652 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4653 Ref->getType()->isPointerType()) {
4654 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4655 if (!Res.isUsable())
4656 return ExprError();
4657 }
4658 return S.DefaultLvalueConversion(Res.get());
4659}
4660
4661namespace {
4662// OpenMP directives parsed in this section are represented as a
4663// CapturedStatement with an associated statement. If a syntax error
4664// is detected during the parsing of the associated statement, the
4665// compiler must abort processing and close the CapturedStatement.
4666//
4667// Combined directives such as 'target parallel' have more than one
4668// nested CapturedStatements. This RAII ensures that we unwind out
4669// of all the nested CapturedStatements when an error is found.
4670class CaptureRegionUnwinderRAII {
4671private:
4672 Sema &S;
4673 bool &ErrorFound;
4674 OpenMPDirectiveKind DKind = OMPD_unknown;
4675
4676public:
4677 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4678 OpenMPDirectiveKind DKind)
4679 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4680 ~CaptureRegionUnwinderRAII() {
4681 if (ErrorFound) {
4682 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4683 while (--ThisCaptureLevel >= 0)
4685 }
4686 }
4687};
4688} // namespace
4689
4691 // Capture variables captured by reference in lambdas for target-based
4692 // directives.
4693 if (!SemaRef.CurContext->isDependentContext() &&
4694 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4696 DSAStack->getCurrentDirective()))) {
4697 QualType Type = V->getType();
4698 if (const auto *RD = Type.getCanonicalType()
4699 .getNonReferenceType()
4700 ->getAsCXXRecordDecl()) {
4701 bool SavedForceCaptureByReferenceInTargetExecutable =
4702 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4703 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4704 /*V=*/true);
4705 if (RD->isLambda()) {
4706 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4707 FieldDecl *ThisCapture;
4708 RD->getCaptureFields(Captures, ThisCapture);
4709 for (const LambdaCapture &LC : RD->captures()) {
4710 if (LC.getCaptureKind() == LCK_ByRef) {
4711 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4712 DeclContext *VDC = VD->getDeclContext();
4713 if (!VDC->Encloses(SemaRef.CurContext))
4714 continue;
4715 SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
4716 } else if (LC.getCaptureKind() == LCK_This) {
4717 QualType ThisTy = SemaRef.getCurrentThisType();
4718 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4719 ThisTy, ThisCapture->getType()))
4720 SemaRef.CheckCXXThisCapture(LC.getLocation());
4721 }
4722 }
4723 }
4724 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4725 SavedForceCaptureByReferenceInTargetExecutable);
4726 }
4727 }
4728}
4729
4731 const ArrayRef<OMPClause *> Clauses) {
4732 const OMPOrderedClause *Ordered = nullptr;
4733 const OMPOrderClause *Order = nullptr;
4734
4735 for (const OMPClause *Clause : Clauses) {
4736 if (Clause->getClauseKind() == OMPC_ordered)
4737 Ordered = cast<OMPOrderedClause>(Clause);
4738 else if (Clause->getClauseKind() == OMPC_order) {
4739 Order = cast<OMPOrderClause>(Clause);
4740 if (Order->getKind() != OMPC_ORDER_concurrent)
4741 Order = nullptr;
4742 }
4743 if (Ordered && Order)
4744 break;
4745 }
4746
4747 if (Ordered && Order) {
4748 S.Diag(Order->getKindKwLoc(),
4749 diag::err_omp_simple_clause_incompatible_with_ordered)
4750 << getOpenMPClauseNameForDiag(OMPC_order)
4751 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4752 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4753 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4754 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4755 return true;
4756 }
4757 return false;
4758}
4759
4761 ArrayRef<OMPClause *> Clauses) {
4763 /*ScopeEntry=*/false);
4764 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
4765 return S;
4766
4767 bool ErrorFound = false;
4768 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4769 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4770 if (!S.isUsable()) {
4771 ErrorFound = true;
4772 return StmtError();
4773 }
4774
4776 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4777 OMPOrderedClause *OC = nullptr;
4778 OMPScheduleClause *SC = nullptr;
4781 // This is required for proper codegen.
4782 for (OMPClause *Clause : Clauses) {
4783 if (!getLangOpts().OpenMPSimd &&
4784 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4785 DSAStack->getCurrentDirective() == OMPD_target) &&
4786 Clause->getClauseKind() == OMPC_in_reduction) {
4787 // Capture taskgroup task_reduction descriptors inside the tasking regions
4788 // with the corresponding in_reduction items.
4789 auto *IRC = cast<OMPInReductionClause>(Clause);
4790 for (Expr *E : IRC->taskgroup_descriptors())
4791 if (E)
4792 SemaRef.MarkDeclarationsReferencedInExpr(E);
4793 }
4794 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4795 Clause->getClauseKind() == OMPC_copyprivate ||
4796 (getLangOpts().OpenMPUseTLS &&
4797 getASTContext().getTargetInfo().isTLSSupported() &&
4798 Clause->getClauseKind() == OMPC_copyin)) {
4799 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4800 // Mark all variables in private list clauses as used in inner region.
4801 for (Stmt *VarRef : Clause->children()) {
4802 if (auto *E = cast_or_null<Expr>(VarRef)) {
4803 SemaRef.MarkDeclarationsReferencedInExpr(E);
4804 }
4805 }
4806 DSAStack->setForceVarCapturing(/*V=*/false);
4807 } else if (CaptureRegions.size() > 1 ||
4808 CaptureRegions.back() != OMPD_unknown) {
4809 if (auto *C = OMPClauseWithPreInit::get(Clause))
4810 PICs.push_back(C);
4811 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4812 if (Expr *E = C->getPostUpdateExpr())
4813 SemaRef.MarkDeclarationsReferencedInExpr(E);
4814 }
4815 }
4816 if (Clause->getClauseKind() == OMPC_schedule)
4817 SC = cast<OMPScheduleClause>(Clause);
4818 else if (Clause->getClauseKind() == OMPC_ordered)
4819 OC = cast<OMPOrderedClause>(Clause);
4820 else if (Clause->getClauseKind() == OMPC_linear)
4821 LCs.push_back(cast<OMPLinearClause>(Clause));
4822 }
4823 // Capture allocator expressions if used.
4824 for (Expr *E : DSAStack->getInnerAllocators())
4825 SemaRef.MarkDeclarationsReferencedInExpr(E);
4826 // OpenMP, 2.7.1 Loop Construct, Restrictions
4827 // The nonmonotonic modifier cannot be specified if an ordered clause is
4828 // specified.
4829 if (SC &&
4830 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4832 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4833 OC) {
4834 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4837 diag::err_omp_simple_clause_incompatible_with_ordered)
4838 << getOpenMPClauseNameForDiag(OMPC_schedule)
4839 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4840 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4841 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4842 ErrorFound = true;
4843 }
4844 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4845 // If an order(concurrent) clause is present, an ordered clause may not appear
4846 // on the same directive.
4847 if (checkOrderedOrderSpecified(SemaRef, Clauses))
4848 ErrorFound = true;
4849 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4850 for (const OMPLinearClause *C : LCs) {
4851 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4852 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4853 }
4854 ErrorFound = true;
4855 }
4856 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4857 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4858 OC->getNumForLoops()) {
4859 unsigned OMPVersion = getLangOpts().OpenMP;
4860 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4861 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(), OMPVersion);
4862 ErrorFound = true;
4863 }
4864 if (ErrorFound) {
4865 return StmtError();
4866 }
4867 StmtResult SR = S;
4868 unsigned CompletedRegions = 0;
4869 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4870 // Mark all variables in private list clauses as used in inner region.
4871 // Required for proper codegen of combined directives.
4872 // TODO: add processing for other clauses.
4873 if (ThisCaptureRegion != OMPD_unknown) {
4874 for (const clang::OMPClauseWithPreInit *C : PICs) {
4875 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4876 // Find the particular capture region for the clause if the
4877 // directive is a combined one with multiple capture regions.
4878 // If the directive is not a combined one, the capture region
4879 // associated with the clause is OMPD_unknown and is generated
4880 // only once.
4881 if (CaptureRegion == ThisCaptureRegion ||
4882 CaptureRegion == OMPD_unknown) {
4883 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4884 for (Decl *D : DS->decls())
4885 SemaRef.MarkVariableReferenced(D->getLocation(),
4886 cast<VarDecl>(D));
4887 }
4888 }
4889 }
4890 }
4891 if (ThisCaptureRegion == OMPD_target) {
4892 // Capture allocator traits in the target region. They are used implicitly
4893 // and, thus, are not captured by default.
4894 for (OMPClause *C : Clauses) {
4895 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4896 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4897 ++I) {
4898 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4899 if (Expr *E = D.AllocatorTraits)
4900 SemaRef.MarkDeclarationsReferencedInExpr(E);
4901 }
4902 continue;
4903 }
4904 }
4905 }
4906 if (ThisCaptureRegion == OMPD_parallel) {
4907 // Capture temp arrays for inscan reductions and locals in aligned
4908 // clauses.
4909 for (OMPClause *C : Clauses) {
4910 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4911 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4912 continue;
4913 for (Expr *E : RC->copy_array_temps())
4914 if (E)
4915 SemaRef.MarkDeclarationsReferencedInExpr(E);
4916 }
4917 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4918 for (Expr *E : AC->varlist())
4919 SemaRef.MarkDeclarationsReferencedInExpr(E);
4920 }
4921 }
4922 }
4923 if (++CompletedRegions == CaptureRegions.size())
4924 DSAStack->setBodyComplete();
4925 SR = SemaRef.ActOnCapturedRegionEnd(SR.get());
4926 }
4927 return SR;
4928}
4929
4930static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4931 OpenMPDirectiveKind CancelRegion,
4932 SourceLocation StartLoc) {
4933 // CancelRegion is only needed for cancel and cancellation_point.
4934 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4935 return false;
4936
4937 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4938 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4939 return false;
4940
4941 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
4942 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4943 << getOpenMPDirectiveName(CancelRegion, OMPVersion);
4944 return true;
4945}
4946
4947static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4948 OpenMPDirectiveKind CurrentRegion,
4949 const DeclarationNameInfo &CurrentName,
4950 OpenMPDirectiveKind CancelRegion,
4951 OpenMPBindClauseKind BindKind,
4952 SourceLocation StartLoc) {
4953 if (!Stack->getCurScope())
4954 return false;
4955
4956 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4957 OpenMPDirectiveKind OffendingRegion = ParentRegion;
4958 bool NestingProhibited = false;
4959 bool CloseNesting = true;
4960 bool OrphanSeen = false;
4961 enum {
4962 NoRecommend,
4963 ShouldBeInParallelRegion,
4964 ShouldBeInOrderedRegion,
4965 ShouldBeInTargetRegion,
4966 ShouldBeInTeamsRegion,
4967 ShouldBeInLoopSimdRegion,
4968 } Recommend = NoRecommend;
4969
4972 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4973 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
4974 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
4975
4976 if (OMPVersion >= 50 && Stack->isParentOrderConcurrent() &&
4978 SemaRef.LangOpts)) {
4979 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
4980 << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
4981 return true;
4982 }
4983 if (isOpenMPSimdDirective(ParentRegion) &&
4984 ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered) ||
4985 (OMPVersion >= 50 && CurrentRegion != OMPD_ordered &&
4986 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4987 CurrentRegion != OMPD_scan))) {
4988 // OpenMP [2.16, Nesting of Regions]
4989 // OpenMP constructs may not be nested inside a simd region.
4990 // OpenMP [2.8.1,simd Construct, Restrictions]
4991 // An ordered construct with the simd clause is the only OpenMP
4992 // construct that can appear in the simd region.
4993 // Allowing a SIMD construct nested in another SIMD construct is an
4994 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
4995 // message.
4996 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
4997 // The only OpenMP constructs that can be encountered during execution of
4998 // a simd region are the atomic construct, the loop construct, the simd
4999 // construct and the ordered construct with the simd clause.
5000 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
5001 ? diag::err_omp_prohibited_region_simd
5002 : diag::warn_omp_nesting_simd)
5003 << (OMPVersion >= 50 ? 1 : 0);
5004 return CurrentRegion != OMPD_simd;
5005 }
5006 if (EnclosingConstruct == OMPD_atomic) {
5007 // OpenMP [2.16, Nesting of Regions]
5008 // OpenMP constructs may not be nested inside an atomic region.
5009 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
5010 return true;
5011 }
5012 if (CurrentRegion == OMPD_section) {
5013 // OpenMP [2.7.2, sections Construct, Restrictions]
5014 // Orphaned section directives are prohibited. That is, the section
5015 // directives must appear within the sections construct and must not be
5016 // encountered elsewhere in the sections region.
5017 if (EnclosingConstruct != OMPD_sections) {
5018 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
5019 << (ParentRegion != OMPD_unknown)
5020 << getOpenMPDirectiveName(ParentRegion, OMPVersion);
5021 return true;
5022 }
5023 return false;
5024 }
5025 // Allow some constructs (except teams and cancellation constructs) to be
5026 // orphaned (they could be used in functions, called from OpenMP regions
5027 // with the required preconditions).
5028 if (ParentRegion == OMPD_unknown &&
5029 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
5030 CurrentRegion != OMPD_cancellation_point &&
5031 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5032 return false;
5033 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
5034 // for a detailed explanation
5035 if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
5036 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
5037 (isOpenMPWorksharingDirective(ParentRegion) ||
5038 EnclosingConstruct == OMPD_loop)) {
5039 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
5040 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5041 << true << getOpenMPDirectiveName(ParentRegion, OMPVersion)
5042 << ErrorMsgNumber << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5043 return true;
5044 }
5045 if (CurrentRegion == OMPD_cancellation_point ||
5046 CurrentRegion == OMPD_cancel) {
5047 // OpenMP [2.16, Nesting of Regions]
5048 // A cancellation point construct for which construct-type-clause is
5049 // taskgroup must be nested inside a task construct. A cancellation
5050 // point construct for which construct-type-clause is not taskgroup must
5051 // be closely nested inside an OpenMP construct that matches the type
5052 // specified in construct-type-clause.
5053 // A cancel construct for which construct-type-clause is taskgroup must be
5054 // nested inside a task construct. A cancel construct for which
5055 // construct-type-clause is not taskgroup must be closely nested inside an
5056 // OpenMP construct that matches the type specified in
5057 // construct-type-clause.
5058 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(ParentRegion);
5059 if (CancelRegion == OMPD_taskgroup) {
5060 NestingProhibited =
5061 EnclosingConstruct != OMPD_task &&
5062 (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
5063 } else if (CancelRegion == OMPD_sections) {
5064 NestingProhibited = EnclosingConstruct != OMPD_section &&
5065 EnclosingConstruct != OMPD_sections;
5066 } else {
5067 NestingProhibited = CancelRegion != Leafs.back();
5068 }
5069 OrphanSeen = ParentRegion == OMPD_unknown;
5070 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5071 // OpenMP 5.1 [2.22, Nesting of Regions]
5072 // A masked region may not be closely nested inside a worksharing, loop,
5073 // atomic, task, or taskloop region.
5074 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5075 isOpenMPGenericLoopDirective(ParentRegion) ||
5076 isOpenMPTaskingDirective(ParentRegion);
5077 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5078 // OpenMP [2.16, Nesting of Regions]
5079 // A critical region may not be nested (closely or otherwise) inside a
5080 // critical region with the same name. Note that this restriction is not
5081 // sufficient to prevent deadlock.
5082 SourceLocation PreviousCriticalLoc;
5083 bool DeadLock = Stack->hasDirective(
5084 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5085 const DeclarationNameInfo &DNI,
5086 SourceLocation Loc) {
5087 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5088 PreviousCriticalLoc = Loc;
5089 return true;
5090 }
5091 return false;
5092 },
5093 false /* skip top directive */);
5094 if (DeadLock) {
5095 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
5096 << CurrentName.getName();
5097 if (PreviousCriticalLoc.isValid())
5098 SemaRef.Diag(PreviousCriticalLoc,
5099 diag::note_omp_previous_critical_region);
5100 return true;
5101 }
5102 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5103 // OpenMP 5.1 [2.22, Nesting of Regions]
5104 // A scope region may not be closely nested inside a worksharing, loop,
5105 // task, taskloop, critical, ordered, atomic, or masked region.
5106 // OpenMP 5.1 [2.22, Nesting of Regions]
5107 // A barrier region may not be closely nested inside a worksharing, loop,
5108 // task, taskloop, critical, ordered, atomic, or masked region.
5109 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5110 isOpenMPGenericLoopDirective(ParentRegion) ||
5111 isOpenMPTaskingDirective(ParentRegion) ||
5112 llvm::is_contained({OMPD_masked, OMPD_master,
5113 OMPD_critical, OMPD_ordered},
5114 EnclosingConstruct);
5115 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
5116 !isOpenMPParallelDirective(CurrentRegion) &&
5117 !isOpenMPTeamsDirective(CurrentRegion)) {
5118 // OpenMP 5.1 [2.22, Nesting of Regions]
5119 // A loop region that binds to a parallel region or a worksharing region
5120 // may not be closely nested inside a worksharing, loop, task, taskloop,
5121 // critical, ordered, atomic, or masked region.
5122 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5123 isOpenMPGenericLoopDirective(ParentRegion) ||
5124 isOpenMPTaskingDirective(ParentRegion) ||
5125 llvm::is_contained({OMPD_masked, OMPD_master,
5126 OMPD_critical, OMPD_ordered},
5127 EnclosingConstruct);
5128 Recommend = ShouldBeInParallelRegion;
5129 } else if (CurrentRegion == OMPD_ordered) {
5130 // OpenMP [2.16, Nesting of Regions]
5131 // An ordered region may not be closely nested inside a critical,
5132 // atomic, or explicit task region.
5133 // An ordered region must be closely nested inside a loop region (or
5134 // parallel loop region) with an ordered clause.
5135 // OpenMP [2.8.1,simd Construct, Restrictions]
5136 // An ordered construct with the simd clause is the only OpenMP construct
5137 // that can appear in the simd region.
5138 NestingProhibited = EnclosingConstruct == OMPD_critical ||
5139 isOpenMPTaskingDirective(ParentRegion) ||
5140 !(isOpenMPSimdDirective(ParentRegion) ||
5141 Stack->isParentOrderedRegion());
5142 Recommend = ShouldBeInOrderedRegion;
5143 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
5144 // OpenMP [2.16, Nesting of Regions]
5145 // If specified, a teams construct must be contained within a target
5146 // construct.
5147 NestingProhibited =
5148 (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
5149 (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
5150 EnclosingConstruct != OMPD_target);
5151 OrphanSeen = ParentRegion == OMPD_unknown;
5152 Recommend = ShouldBeInTargetRegion;
5153 } else if (CurrentRegion == OMPD_scan) {
5154 if (OMPVersion >= 50) {
5155 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
5156 // simd, or for simd. This has to take into account combined directives.
5157 // In 5.2 this seems to be implied by the fact that the specified
5158 // separated constructs are do, for, and simd.
5159 NestingProhibited = !llvm::is_contained(
5160 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
5161 } else {
5162 NestingProhibited = true;
5163 }
5164 OrphanSeen = ParentRegion == OMPD_unknown;
5165 Recommend = ShouldBeInLoopSimdRegion;
5166 }
5167 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5168 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5169 EnclosingConstruct == OMPD_teams) {
5170 // OpenMP [5.1, 2.22, Nesting of Regions]
5171 // distribute, distribute simd, distribute parallel worksharing-loop,
5172 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5173 // including any parallel regions arising from combined constructs,
5174 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5175 // only OpenMP regions that may be strictly nested inside the teams
5176 // region.
5177 //
5178 // As an extension, we permit atomic within teams as well.
5179 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5180 !isOpenMPDistributeDirective(CurrentRegion) &&
5181 CurrentRegion != OMPD_loop &&
5182 !(SemaRef.getLangOpts().OpenMPExtensions &&
5183 CurrentRegion == OMPD_atomic);
5184 Recommend = ShouldBeInParallelRegion;
5185 }
5186 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5187 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5188 // If the bind clause is present on the loop construct and binding is
5189 // teams then the corresponding loop region must be strictly nested inside
5190 // a teams region.
5191 NestingProhibited =
5192 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5193 Recommend = ShouldBeInTeamsRegion;
5194 }
5195 if (!NestingProhibited && isOpenMPNestingDistributeDirective(CurrentRegion)) {
5196 // OpenMP 4.5 [2.17 Nesting of Regions]
5197 // The region associated with the distribute construct must be strictly
5198 // nested inside a teams region
5199 NestingProhibited = EnclosingConstruct != OMPD_teams;
5200 Recommend = ShouldBeInTeamsRegion;
5201 }
5202 if (!NestingProhibited &&
5203 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5204 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5205 // OpenMP 4.5 [2.17 Nesting of Regions]
5206 // If a target, target update, target data, target enter data, or
5207 // target exit data construct is encountered during execution of a
5208 // target region, the behavior is unspecified.
5209 NestingProhibited = Stack->hasDirective(
5210 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5213 OffendingRegion = K;
5214 return true;
5215 }
5216 return false;
5217 },
5218 false /* don't skip top directive */);
5219 CloseNesting = false;
5220 }
5221 if (NestingProhibited) {
5222 if (OrphanSeen) {
5223 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5224 << getOpenMPDirectiveName(CurrentRegion, OMPVersion) << Recommend;
5225 } else {
5226 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5227 << CloseNesting << getOpenMPDirectiveName(OffendingRegion, OMPVersion)
5228 << Recommend << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5229 }
5230 return true;
5231 }
5232 return false;
5233}
5234
5240 ArrayRef<OMPClause *> Clauses,
5241 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5242 bool ErrorFound = false;
5243 unsigned NamedModifiersNumber = 0;
5244 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5245 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5246 SmallVector<SourceLocation, 4> NameModifierLoc;
5247 unsigned OMPVersion = S.getLangOpts().OpenMP;
5248 for (const OMPClause *C : Clauses) {
5249 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5250 // At most one if clause without a directive-name-modifier can appear on
5251 // the directive.
5252 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5253 auto &FNM = FoundNameModifiers[CurNM];
5254 if (FNM) {
5255 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5256 << getOpenMPDirectiveName(Kind, OMPVersion)
5257 << getOpenMPClauseNameForDiag(OMPC_if) << (CurNM != OMPD_unknown)
5258 << getOpenMPDirectiveName(CurNM, OMPVersion);
5259 ErrorFound = true;
5260 } else if (CurNM != OMPD_unknown) {
5261 NameModifierLoc.push_back(IC->getNameModifierLoc());
5262 ++NamedModifiersNumber;
5263 }
5264 FNM = IC;
5265 if (CurNM == OMPD_unknown)
5266 continue;
5267 // Check if the specified name modifier is allowed for the current
5268 // directive.
5269 // At most one if clause with the particular directive-name-modifier can
5270 // appear on the directive.
5271 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5272 S.Diag(IC->getNameModifierLoc(),
5273 diag::err_omp_wrong_if_directive_name_modifier)
5274 << getOpenMPDirectiveName(CurNM, OMPVersion)
5275 << getOpenMPDirectiveName(Kind, OMPVersion);
5276 ErrorFound = true;
5277 }
5278 }
5279 }
5280 // If any if clause on the directive includes a directive-name-modifier then
5281 // all if clauses on the directive must include a directive-name-modifier.
5282 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5283 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5284 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5285 diag::err_omp_no_more_if_clause);
5286 } else {
5287 std::string Values;
5288 std::string Sep(", ");
5289 unsigned AllowedCnt = 0;
5290 unsigned TotalAllowedNum =
5291 AllowedNameModifiers.size() - NamedModifiersNumber;
5292 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5293 ++Cnt) {
5294 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5295 if (!FoundNameModifiers[NM]) {
5296 Values += "'";
5297 Values += getOpenMPDirectiveName(NM, OMPVersion);
5298 Values += "'";
5299 if (AllowedCnt + 2 == TotalAllowedNum)
5300 Values += " or ";
5301 else if (AllowedCnt + 1 != TotalAllowedNum)
5302 Values += Sep;
5303 ++AllowedCnt;
5304 }
5305 }
5306 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5307 diag::err_omp_unnamed_if_clause)
5308 << (TotalAllowedNum > 1) << Values;
5309 }
5310 for (SourceLocation Loc : NameModifierLoc) {
5311 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5312 }
5313 ErrorFound = true;
5314 }
5315 return ErrorFound;
5316}
5317
5318static std::pair<ValueDecl *, bool>
5320 SourceRange &ERange, bool AllowArraySection,
5321 bool AllowAssumedSizeArray, StringRef DiagType) {
5322 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5324 return std::make_pair(nullptr, true);
5325
5326 // OpenMP [3.1, C/C++]
5327 // A list item is a variable name.
5328 // OpenMP [2.9.3.3, Restrictions, p.1]
5329 // A variable that is part of another variable (as an array or
5330 // structure element) cannot appear in a private clause.
5331 //
5332 // OpenMP [6.0]
5333 // 5.2.5 Array Sections, p. 166, L28-29
5334 // When the length is absent and the size of the dimension is not known,
5335 // the array section is an assumed-size array.
5336 // 2 Glossary, p. 23, L4-6
5337 // assumed-size array
5338 // For C/C++, an array section for which the length is absent and the
5339 // size of the dimensions is not known.
5340 // 5.2.5 Array Sections, p. 168, L11
5341 // An assumed-size array can appear only in clauses for which it is
5342 // explicitly allowed.
5343 // 7.4 List Item Privatization, Restrictions, p. 222, L15
5344 // Assumed-size arrays must not be privatized.
5345 RefExpr = RefExpr->IgnoreParens();
5346 enum {
5347 NoArrayExpr = -1,
5348 ArraySubscript = 0,
5349 OMPArraySection = 1
5350 } IsArrayExpr = NoArrayExpr;
5351 if (AllowArraySection) {
5352 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5353 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5354 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5355 Base = TempASE->getBase()->IgnoreParenImpCasts();
5356 RefExpr = Base;
5357 IsArrayExpr = ArraySubscript;
5358 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5359 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5360 if (S.getLangOpts().OpenMP >= 60 && !AllowAssumedSizeArray &&
5361 OASE->getColonLocFirst().isValid() && !OASE->getLength()) {
5363 if (BaseType.isNull() || (!BaseType->isConstantArrayType() &&
5364 !BaseType->isVariableArrayType())) {
5365 S.Diag(OASE->getColonLocFirst(),
5366 diag::err_omp_section_length_undefined)
5367 << (!BaseType.isNull() && BaseType->isArrayType());
5368 return std::make_pair(nullptr, false);
5369 }
5370 }
5371 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Base))
5372 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5373 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5374 Base = TempASE->getBase()->IgnoreParenImpCasts();
5375 RefExpr = Base;
5376 IsArrayExpr = OMPArraySection;
5377 }
5378 }
5379 ELoc = RefExpr->getExprLoc();
5380 ERange = RefExpr->getSourceRange();
5381 RefExpr = RefExpr->IgnoreParenImpCasts();
5382 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5383 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5384 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5385 (S.getCurrentThisType().isNull() || !ME ||
5386 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5387 !isa<FieldDecl>(ME->getMemberDecl()))) {
5388 if (IsArrayExpr != NoArrayExpr) {
5389 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5390 << IsArrayExpr << ERange;
5391 } else if (!DiagType.empty()) {
5392 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5393 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5394 : 0;
5395 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5396 << DiagSelect << DiagType << ERange;
5397 } else {
5398 S.Diag(ELoc,
5399 AllowArraySection
5400 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5401 : diag::err_omp_expected_var_name_member_expr)
5402 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5403 }
5404 return std::make_pair(nullptr, false);
5405 }
5406 return std::make_pair(
5407 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5408}
5409
5410namespace {
5411/// Checks if the allocator is used in uses_allocators clause to be allowed in
5412/// target regions.
5413class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5414 DSAStackTy *S = nullptr;
5415
5416public:
5417 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5418 return S->isUsesAllocatorsDecl(E->getDecl())
5419 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5420 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5421 }
5422 bool VisitStmt(const Stmt *S) {
5423 for (const Stmt *Child : S->children()) {
5424 if (Child && Visit(Child))
5425 return true;
5426 }
5427 return false;
5428 }
5429 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5430};
5431} // namespace
5432
5433static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5434 ArrayRef<OMPClause *> Clauses) {
5435 assert(!S.CurContext->isDependentContext() &&
5436 "Expected non-dependent context.");
5437 auto AllocateRange =
5438 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5439 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5440 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5441 return isOpenMPPrivate(C->getClauseKind());
5442 });
5443 for (OMPClause *Cl : PrivateRange) {
5445 if (Cl->getClauseKind() == OMPC_private) {
5446 auto *PC = cast<OMPPrivateClause>(Cl);
5447 I = PC->private_copies().begin();
5448 It = PC->varlist_begin();
5449 Et = PC->varlist_end();
5450 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5451 auto *PC = cast<OMPFirstprivateClause>(Cl);
5452 I = PC->private_copies().begin();
5453 It = PC->varlist_begin();
5454 Et = PC->varlist_end();
5455 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5456 auto *PC = cast<OMPLastprivateClause>(Cl);
5457 I = PC->private_copies().begin();
5458 It = PC->varlist_begin();
5459 Et = PC->varlist_end();
5460 } else if (Cl->getClauseKind() == OMPC_linear) {
5461 auto *PC = cast<OMPLinearClause>(Cl);
5462 I = PC->privates().begin();
5463 It = PC->varlist_begin();
5464 Et = PC->varlist_end();
5465 } else if (Cl->getClauseKind() == OMPC_reduction) {
5466 auto *PC = cast<OMPReductionClause>(Cl);
5467 I = PC->privates().begin();
5468 It = PC->varlist_begin();
5469 Et = PC->varlist_end();
5470 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5471 auto *PC = cast<OMPTaskReductionClause>(Cl);
5472 I = PC->privates().begin();
5473 It = PC->varlist_begin();
5474 Et = PC->varlist_end();
5475 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5476 auto *PC = cast<OMPInReductionClause>(Cl);
5477 I = PC->privates().begin();
5478 It = PC->varlist_begin();
5479 Et = PC->varlist_end();
5480 } else {
5481 llvm_unreachable("Expected private clause.");
5482 }
5483 for (Expr *E : llvm::make_range(It, Et)) {
5484 if (!*I) {
5485 ++I;
5486 continue;
5487 }
5488 SourceLocation ELoc;
5489 SourceRange ERange;
5490 Expr *SimpleRefExpr = E;
5491 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5492 /*AllowArraySection=*/true);
5493 DeclToCopy.try_emplace(Res.first,
5494 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5495 ++I;
5496 }
5497 }
5498 for (OMPClause *C : AllocateRange) {
5499 auto *AC = cast<OMPAllocateClause>(C);
5500 if (S.getLangOpts().OpenMP >= 50 &&
5501 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5502 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5503 AC->getAllocator()) {
5504 Expr *Allocator = AC->getAllocator();
5505 // OpenMP, 2.12.5 target Construct
5506 // Memory allocators that do not appear in a uses_allocators clause cannot
5507 // appear as an allocator in an allocate clause or be used in the target
5508 // region unless a requires directive with the dynamic_allocators clause
5509 // is present in the same compilation unit.
5510 AllocatorChecker Checker(Stack);
5511 if (Checker.Visit(Allocator))
5512 S.Diag(Allocator->getExprLoc(),
5513 diag::err_omp_allocator_not_in_uses_allocators)
5514 << Allocator->getSourceRange();
5515 }
5516 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5517 getAllocatorKind(S, Stack, AC->getAllocator());
5518 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5519 // For task, taskloop or target directives, allocation requests to memory
5520 // allocators with the trait access set to thread result in unspecified
5521 // behavior.
5522 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5523 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5524 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5525 unsigned OMPVersion = S.getLangOpts().OpenMP;
5526 S.Diag(AC->getAllocator()->getExprLoc(),
5527 diag::warn_omp_allocate_thread_on_task_target_directive)
5528 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
5529 }
5530 for (Expr *E : AC->varlist()) {
5531 SourceLocation ELoc;
5532 SourceRange ERange;
5533 Expr *SimpleRefExpr = E;
5534 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5535 ValueDecl *VD = Res.first;
5536 if (!VD)
5537 continue;
5538 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5539 if (!isOpenMPPrivate(Data.CKind)) {
5540 S.Diag(E->getExprLoc(),
5541 diag::err_omp_expected_private_copy_for_allocate);
5542 continue;
5543 }
5544 VarDecl *PrivateVD = DeclToCopy[VD];
5545 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5546 AllocatorKind, AC->getAllocator()))
5547 continue;
5548 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5549 AC->getAlignment(), E->getSourceRange());
5550 }
5551 }
5552}
5553
5554namespace {
5555/// Rewrite statements and expressions for Sema \p Actions CurContext.
5556///
5557/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5558/// context. DeclRefExpr used inside the new context are changed to refer to the
5559/// captured variable instead.
5560class CaptureVars : public TreeTransform<CaptureVars> {
5561 using BaseTransform = TreeTransform<CaptureVars>;
5562
5563public:
5564 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5565
5566 bool AlwaysRebuild() { return true; }
5567};
5568} // namespace
5569
5570static VarDecl *precomputeExpr(Sema &Actions,
5571 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5572 StringRef Name) {
5573 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5574 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5575 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5576 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5577 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5578 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5579 BodyStmts.push_back(NewDeclStmt);
5580 return NewVar;
5581}
5582
5583/// Create a closure that computes the number of iterations of a loop.
5584///
5585/// \param Actions The Sema object.
5586/// \param LogicalTy Type for the logical iteration number.
5587/// \param Rel Comparison operator of the loop condition.
5588/// \param StartExpr Value of the loop counter at the first iteration.
5589/// \param StopExpr Expression the loop counter is compared against in the loop
5590/// condition. \param StepExpr Amount of increment after each iteration.
5591///
5592/// \return Closure (CapturedStmt) of the distance calculation.
5593static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5595 Expr *StartExpr, Expr *StopExpr,
5596 Expr *StepExpr) {
5597 ASTContext &Ctx = Actions.getASTContext();
5598 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5599
5600 // Captured regions currently don't support return values, we use an
5601 // out-parameter instead. All inputs are implicit captures.
5602 // TODO: Instead of capturing each DeclRefExpr occurring in
5603 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5604 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5605 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5606 {StringRef(), QualType()}};
5607 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5608
5609 Stmt *Body;
5610 {
5611 Sema::CompoundScopeRAII CompoundScope(Actions);
5613
5614 // Get the LValue expression for the result.
5615 ImplicitParamDecl *DistParam = CS->getParam(0);
5616 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5617 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5618
5619 SmallVector<Stmt *, 4> BodyStmts;
5620
5621 // Capture all referenced variable references.
5622 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5623 // CapturedStmt, we could compute them before and capture the result, to be
5624 // used jointly with the LoopVar function.
5625 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5626 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5627 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5628 auto BuildVarRef = [&](VarDecl *VD) {
5629 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5630 };
5631
5633 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5635 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5636 Expr *Dist;
5637 if (Rel == BO_NE) {
5638 // When using a != comparison, the increment can be +1 or -1. This can be
5639 // dynamic at runtime, so we need to check for the direction.
5640 Expr *IsNegStep = AssertSuccess(
5641 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5642
5643 // Positive increment.
5644 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5645 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5646 ForwardRange = AssertSuccess(
5647 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5648 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5649 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5650
5651 // Negative increment.
5652 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5653 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5654 BackwardRange = AssertSuccess(
5655 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5656 Expr *NegIncAmount = AssertSuccess(
5657 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5658 Expr *BackwardDist = AssertSuccess(
5659 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5660
5661 // Use the appropriate case.
5662 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5663 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5664 } else {
5665 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5666 "Expected one of these relational operators");
5667
5668 // We can derive the direction from any other comparison operator. It is
5669 // non well-formed OpenMP if Step increments/decrements in the other
5670 // directions. Whether at least the first iteration passes the loop
5671 // condition.
5672 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5673 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5674
5675 // Compute the range between first and last counter value.
5676 Expr *Range;
5677 if (Rel == BO_GE || Rel == BO_GT)
5678 Range = AssertSuccess(Actions.BuildBinOp(
5679 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5680 else
5681 Range = AssertSuccess(Actions.BuildBinOp(
5682 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5683
5684 // Ensure unsigned range space.
5685 Range =
5686 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5687
5688 if (Rel == BO_LE || Rel == BO_GE) {
5689 // Add one to the range if the relational operator is inclusive.
5690 Range =
5691 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5692 }
5693
5694 // Divide by the absolute step amount. If the range is not a multiple of
5695 // the step size, rounding-up the effective upper bound ensures that the
5696 // last iteration is included.
5697 // Note that the rounding-up may cause an overflow in a temporary that
5698 // could be avoided, but would have occurred in a C-style for-loop as
5699 // well.
5700 Expr *Divisor = BuildVarRef(NewStep);
5701 if (Rel == BO_GE || Rel == BO_GT)
5702 Divisor =
5703 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5704 Expr *DivisorMinusOne =
5705 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5706 Expr *RangeRoundUp = AssertSuccess(
5707 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5708 Dist = AssertSuccess(
5709 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5710
5711 // If there is not at least one iteration, the range contains garbage. Fix
5712 // to zero in this case.
5713 Dist = AssertSuccess(
5714 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5715 }
5716
5717 // Assign the result to the out-parameter.
5718 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5719 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5720 BodyStmts.push_back(ResultAssign);
5721
5722 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5723 }
5724
5725 return cast<CapturedStmt>(
5726 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5727}
5728
5729/// Create a closure that computes the loop variable from the logical iteration
5730/// number.
5731///
5732/// \param Actions The Sema object.
5733/// \param LoopVarTy Type for the loop variable used for result value.
5734/// \param LogicalTy Type for the logical iteration number.
5735/// \param StartExpr Value of the loop counter at the first iteration.
5736/// \param Step Amount of increment after each iteration.
5737/// \param Deref Whether the loop variable is a dereference of the loop
5738/// counter variable.
5739///
5740/// \return Closure (CapturedStmt) of the loop value calculation.
5741static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5742 QualType LogicalTy,
5743 DeclRefExpr *StartExpr, Expr *Step,
5744 bool Deref) {
5745 ASTContext &Ctx = Actions.getASTContext();
5746
5747 // Pass the result as an out-parameter. Passing as return value would require
5748 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5749 // invoke a copy constructor.
5750 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5751 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5752 {"Logical", LogicalTy},
5753 {StringRef(), QualType()}};
5754 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5755
5756 // Capture the initial iterator which represents the LoopVar value at the
5757 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5758 // it in every iteration, capture it by value before it is modified.
5759 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5760 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5762 (void)Invalid;
5763 assert(!Invalid && "Expecting capture-by-value to work.");
5764
5765 Expr *Body;
5766 {
5767 Sema::CompoundScopeRAII CompoundScope(Actions);
5768 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5769
5770 ImplicitParamDecl *TargetParam = CS->getParam(0);
5771 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5772 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5773 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5774 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5775 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5776
5777 // Capture the Start expression.
5778 CaptureVars Recap(Actions);
5779 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5780 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5781
5783 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5784 // TODO: Explicitly cast to the iterator's difference_type instead of
5785 // relying on implicit conversion.
5786 Expr *Advanced =
5787 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5788
5789 if (Deref) {
5790 // For range-based for-loops convert the loop counter value to a concrete
5791 // loop variable value by dereferencing the iterator.
5792 Advanced =
5793 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5794 }
5795
5796 // Assign the result to the output parameter.
5797 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5798 BO_Assign, TargetRef, Advanced));
5799 }
5800 return cast<CapturedStmt>(
5801 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5802}
5803
5805 ASTContext &Ctx = getASTContext();
5806
5807 // Extract the common elements of ForStmt and CXXForRangeStmt:
5808 // Loop variable, repeat condition, increment
5809 Expr *Cond, *Inc;
5810 VarDecl *LIVDecl, *LUVDecl;
5811 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5812 Stmt *Init = For->getInit();
5813 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5814 // For statement declares loop variable.
5815 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5816 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5817 // For statement reuses variable.
5818 assert(LCAssign->getOpcode() == BO_Assign &&
5819 "init part must be a loop variable assignment");
5820 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5821 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5822 } else
5823 llvm_unreachable("Cannot determine loop variable");
5824 LUVDecl = LIVDecl;
5825
5826 Cond = For->getCond();
5827 Inc = For->getInc();
5828 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5829 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5830 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5831 LUVDecl = RangeFor->getLoopVariable();
5832
5833 Cond = RangeFor->getCond();
5834 Inc = RangeFor->getInc();
5835 } else
5836 llvm_unreachable("unhandled kind of loop");
5837
5838 QualType CounterTy = LIVDecl->getType();
5839 QualType LVTy = LUVDecl->getType();
5840
5841 // Analyze the loop condition.
5842 Expr *LHS, *RHS;
5843 BinaryOperator::Opcode CondRel;
5844 Cond = Cond->IgnoreImplicit();
5845 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5846 LHS = CondBinExpr->getLHS();
5847 RHS = CondBinExpr->getRHS();
5848 CondRel = CondBinExpr->getOpcode();
5849 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5850 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5851 LHS = CondCXXOp->getArg(0);
5852 RHS = CondCXXOp->getArg(1);
5853 switch (CondCXXOp->getOperator()) {
5854 case OO_ExclaimEqual:
5855 CondRel = BO_NE;
5856 break;
5857 case OO_Less:
5858 CondRel = BO_LT;
5859 break;
5860 case OO_LessEqual:
5861 CondRel = BO_LE;
5862 break;
5863 case OO_Greater:
5864 CondRel = BO_GT;
5865 break;
5866 case OO_GreaterEqual:
5867 CondRel = BO_GE;
5868 break;
5869 default:
5870 llvm_unreachable("unexpected iterator operator");
5871 }
5872 } else
5873 llvm_unreachable("unexpected loop condition");
5874
5875 // Normalize such that the loop counter is on the LHS.
5876 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5877 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5878 std::swap(LHS, RHS);
5879 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5880 }
5881 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5882
5883 // Decide the bit width for the logical iteration counter. By default use the
5884 // unsigned ptrdiff_t integer size (for iterators and pointers).
5885 // TODO: For iterators, use iterator::difference_type,
5886 // std::iterator_traits<>::difference_type or decltype(it - end).
5887 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5888 if (CounterTy->isIntegerType()) {
5889 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5890 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5891 }
5892
5893 // Analyze the loop increment.
5894 Expr *Step;
5895 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5896 int Direction;
5897 switch (IncUn->getOpcode()) {
5898 case UO_PreInc:
5899 case UO_PostInc:
5900 Direction = 1;
5901 break;
5902 case UO_PreDec:
5903 case UO_PostDec:
5904 Direction = -1;
5905 break;
5906 default:
5907 llvm_unreachable("unhandled unary increment operator");
5908 }
5910 Ctx,
5911 llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction, /*isSigned=*/true),
5912 LogicalTy, {});
5913 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5914 if (IncBin->getOpcode() == BO_AddAssign) {
5915 Step = IncBin->getRHS();
5916 } else if (IncBin->getOpcode() == BO_SubAssign) {
5917 Step = AssertSuccess(
5918 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5919 } else
5920 llvm_unreachable("unhandled binary increment operator");
5921 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5922 switch (CondCXXOp->getOperator()) {
5923 case OO_PlusPlus:
5925 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5926 break;
5927 case OO_MinusMinus:
5929 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5930 break;
5931 case OO_PlusEqual:
5932 Step = CondCXXOp->getArg(1);
5933 break;
5934 case OO_MinusEqual:
5935 Step = AssertSuccess(
5936 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5937 break;
5938 default:
5939 llvm_unreachable("unhandled overloaded increment operator");
5940 }
5941 } else
5942 llvm_unreachable("unknown increment expression");
5943
5944 CapturedStmt *DistanceFunc =
5945 buildDistanceFunc(SemaRef, LogicalTy, CondRel, LHS, RHS, Step);
5946 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5947 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5948 DeclRefExpr *LVRef =
5949 SemaRef.BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue, {},
5950 nullptr, nullptr, {}, nullptr);
5951 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
5952 LoopVarFunc, LVRef);
5953}
5954
5956 // Handle a literal loop.
5957 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5958 return ActOnOpenMPCanonicalLoop(AStmt);
5959
5960 // If not a literal loop, it must be the result of a loop transformation.
5962 assert(
5963 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
5964 "Loop transformation directive expected");
5965 return LoopTransform;
5966}
5967
5969 CXXScopeSpec &MapperIdScopeSpec,
5970 const DeclarationNameInfo &MapperId,
5971 QualType Type,
5972 Expr *UnresolvedMapper);
5973
5974/// Perform DFS through the structure/class data members trying to find
5975/// member(s) with user-defined 'default' mapper and generate implicit map
5976/// clauses for such members with the found 'default' mapper.
5977static void
5980 // Check for the default mapper for data members.
5981 if (S.getLangOpts().OpenMP < 50)
5982 return;
5983 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5984 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5985 if (!C)
5986 continue;
5987 SmallVector<Expr *, 4> SubExprs;
5988 auto *MI = C->mapperlist_begin();
5989 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
5990 ++I, ++MI) {
5991 // Expression is mapped using mapper - skip it.
5992 if (*MI)
5993 continue;
5994 Expr *E = *I;
5995 // Expression is dependent - skip it, build the mapper when it gets
5996 // instantiated.
5997 if (E->isTypeDependent() || E->isValueDependent() ||
5999 continue;
6000 // Array section - need to check for the mapping of the array section
6001 // element.
6002 QualType CanonType = E->getType().getCanonicalType();
6003 if (CanonType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
6004 const auto *OASE = cast<ArraySectionExpr>(E->IgnoreParenImpCasts());
6005 QualType BaseType =
6007 QualType ElemType;
6008 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6009 ElemType = ATy->getElementType();
6010 else
6011 ElemType = BaseType->getPointeeType();
6012 CanonType = ElemType;
6013 }
6014
6015 // DFS over data members in structures/classes.
6017 1, {CanonType, nullptr});
6018 llvm::DenseMap<const Type *, Expr *> Visited;
6020 1, {nullptr, 1});
6021 while (!Types.empty()) {
6022 QualType BaseType;
6023 FieldDecl *CurFD;
6024 std::tie(BaseType, CurFD) = Types.pop_back_val();
6025 while (ParentChain.back().second == 0)
6026 ParentChain.pop_back();
6027 --ParentChain.back().second;
6028 if (BaseType.isNull())
6029 continue;
6030 // Only structs/classes are allowed to have mappers.
6031 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6032 if (!RD)
6033 continue;
6034 auto It = Visited.find(BaseType.getTypePtr());
6035 if (It == Visited.end()) {
6036 // Try to find the associated user-defined mapper.
6037 CXXScopeSpec MapperIdScopeSpec;
6038 DeclarationNameInfo DefaultMapperId;
6040 &S.Context.Idents.get("default")));
6041 DefaultMapperId.setLoc(E->getExprLoc());
6043 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
6044 BaseType, /*UnresolvedMapper=*/nullptr);
6045 if (ER.isInvalid())
6046 continue;
6047 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
6048 }
6049 // Found default mapper.
6050 if (It->second) {
6051 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
6053 OE->setIsUnique(/*V=*/true);
6054 Expr *BaseExpr = OE;
6055 for (const auto &P : ParentChain) {
6056 if (P.first) {
6057 BaseExpr = S.BuildMemberExpr(
6058 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6060 DeclAccessPair::make(P.first, P.first->getAccess()),
6061 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6062 P.first->getType(), VK_LValue, OK_Ordinary);
6063 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
6064 }
6065 }
6066 if (CurFD)
6067 BaseExpr = S.BuildMemberExpr(
6068 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6070 DeclAccessPair::make(CurFD, CurFD->getAccess()),
6071 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6072 CurFD->getType(), VK_LValue, OK_Ordinary);
6073 SubExprs.push_back(BaseExpr);
6074 continue;
6075 }
6076 // Check for the "default" mapper for data members.
6077 bool FirstIter = true;
6078 for (FieldDecl *FD : RD->fields()) {
6079 if (!FD)
6080 continue;
6081 QualType FieldTy = FD->getType();
6082 if (FieldTy.isNull() ||
6083 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6084 continue;
6085 if (FirstIter) {
6086 FirstIter = false;
6087 ParentChain.emplace_back(CurFD, 1);
6088 } else {
6089 ++ParentChain.back().second;
6090 }
6091 Types.emplace_back(FieldTy, FD);
6092 }
6093 }
6094 }
6095 if (SubExprs.empty())
6096 continue;
6097 CXXScopeSpec MapperIdScopeSpec;
6098 DeclarationNameInfo MapperId;
6099 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
6100 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
6101 MapperIdScopeSpec, MapperId, C->getMapType(),
6102 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6103 SubExprs, OMPVarListLocTy()))
6104 Clauses.push_back(NewClause);
6105 }
6106}
6107
6108namespace {
6109/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
6110/// call in the associated loop-nest cannot be a 'parallel for'.
6111class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
6112 Sema &SemaRef;
6113
6114public:
6115 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
6116
6117 // Is there a nested OpenMP loop bind(parallel)
6118 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
6119 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
6120 if (const auto *C = D->getSingleClause<OMPBindClause>())
6121 if (C->getBindKind() == OMPC_BIND_parallel) {
6122 TeamsLoopCanBeParallelFor = false;
6123 // No need to continue visiting any more
6124 return;
6125 }
6126 }
6127 for (const Stmt *Child : D->children())
6128 if (Child)
6129 Visit(Child);
6130 }
6131
6132 void VisitCallExpr(const CallExpr *C) {
6133 // Function calls inhibit parallel loop translation of 'target teams loop'
6134 // unless the assume-no-nested-parallelism flag has been specified.
6135 // OpenMP API runtime library calls do not inhibit parallel loop
6136 // translation, regardless of the assume-no-nested-parallelism.
6137 bool IsOpenMPAPI = false;
6138 auto *FD = dyn_cast_or_null<FunctionDecl>(C->getCalleeDecl());
6139 if (FD) {
6140 std::string Name = FD->getNameInfo().getAsString();
6141 IsOpenMPAPI = Name.find("omp_") == 0;
6142 }
6143 TeamsLoopCanBeParallelFor =
6144 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
6145 if (!TeamsLoopCanBeParallelFor)
6146 return;
6147
6148 for (const Stmt *Child : C->children())
6149 if (Child)
6150 Visit(Child);
6151 }
6152
6153 void VisitCapturedStmt(const CapturedStmt *S) {
6154 if (!S)
6155 return;
6156 Visit(S->getCapturedDecl()->getBody());
6157 }
6158
6159 void VisitStmt(const Stmt *S) {
6160 if (!S)
6161 return;
6162 for (const Stmt *Child : S->children())
6163 if (Child)
6164 Visit(Child);
6165 }
6166 explicit TeamsLoopChecker(Sema &SemaRef)
6167 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
6168
6169private:
6170 bool TeamsLoopCanBeParallelFor;
6171};
6172} // namespace
6173
6174static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
6175 TeamsLoopChecker Checker(SemaRef);
6176 Checker.Visit(AStmt);
6177 return Checker.teamsLoopCanBeParallelFor();
6178}
6179
6181 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6182 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6183 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
6184 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
6185
6186 StmtResult Res = StmtError();
6188 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6189
6190 if (const OMPBindClause *BC =
6191 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6192 BindKind = BC->getBindKind();
6193
6194 if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
6195 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
6196
6197 // Setting the enclosing teams or parallel construct for the loop
6198 // directive without bind clause.
6199 // [5.0:129:25-28] If the bind clause is not present on the construct and
6200 // the loop construct is closely nested inside a teams or parallel
6201 // construct, the binding region is the corresponding teams or parallel
6202 // region. If none of those conditions hold, the binding region is not
6203 // defined.
6204 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6205 ArrayRef<OpenMPDirectiveKind> ParentLeafs =
6206 getLeafConstructsOrSelf(ParentDirective);
6207
6208 if (ParentDirective == OMPD_unknown) {
6209 Diag(DSAStack->getDefaultDSALocation(),
6210 diag::err_omp_bind_required_on_loop);
6211 } else if (ParentLeafs.back() == OMPD_parallel) {
6212 BindKind = OMPC_BIND_parallel;
6213 } else if (ParentLeafs.back() == OMPD_teams) {
6214 BindKind = OMPC_BIND_teams;
6215 }
6216
6217 assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind");
6218
6219 OMPClause *C =
6222 ClausesWithImplicit.push_back(C);
6223 }
6224
6225 // Diagnose "loop bind(teams)" with "reduction".
6226 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6227 for (OMPClause *C : Clauses) {
6228 if (C->getClauseKind() == OMPC_reduction)
6229 Diag(DSAStack->getDefaultDSALocation(),
6230 diag::err_omp_loop_reduction_clause);
6231 }
6232 }
6233
6234 // First check CancelRegion which is then used in checkNestingOfRegions.
6235 if (checkCancelRegion(SemaRef, Kind, CancelRegion, StartLoc) ||
6236 checkNestingOfRegions(SemaRef, DSAStack, Kind, DirName, CancelRegion,
6237 BindKind, StartLoc)) {
6238 return StmtError();
6239 }
6240
6241 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6244 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6245
6246 VarsWithInheritedDSAType VarsWithInheritedDSA;
6247 bool ErrorFound = false;
6248 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6249
6250 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6252 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6253
6254 // Check default data sharing attributes for referenced variables.
6255 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(AStmt));
6256 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6257 Stmt *S = AStmt;
6258 while (--ThisCaptureLevel >= 0)
6259 S = cast<CapturedStmt>(S)->getCapturedStmt();
6260 DSAChecker.Visit(S);
6262 !isOpenMPTaskingDirective(Kind)) {
6263 // Visit subcaptures to generate implicit clauses for captured vars.
6264 auto *CS = cast<CapturedStmt>(AStmt);
6266 getOpenMPCaptureRegions(CaptureRegions, Kind);
6267 // Ignore outer tasking regions for target directives.
6268 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6270 DSAChecker.visitSubCaptures(CS);
6271 }
6272 if (DSAChecker.isErrorFound())
6273 return StmtError();
6274 // Generate list of implicitly defined firstprivate variables.
6275 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6276 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6277
6279 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6280 // Get the original location of present modifier from Defaultmap clause.
6281 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6282 for (OMPClause *C : Clauses) {
6283 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6284 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6285 PresentModifierLocs[DMC->getDefaultmapKind()] =
6286 DMC->getDefaultmapModifierLoc();
6287 }
6288
6290 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6292 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[K]),
6293 ImpInfo.MapModifiers[K].size(), PresentModifierLocs[K]);
6294 }
6295 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6296 for (OMPClause *C : Clauses) {
6297 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6298 for (Expr *E : IRC->taskgroup_descriptors())
6299 if (E)
6300 ImpInfo.Firstprivates.insert(E);
6301 }
6302 // OpenMP 5.0, 2.10.1 task Construct
6303 // [detach clause]... The event-handle will be considered as if it was
6304 // specified on a firstprivate clause.
6305 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6306 ImpInfo.Firstprivates.insert(DC->getEventHandler());
6307 }
6308 if (!ImpInfo.Firstprivates.empty()) {
6310 ImpInfo.Firstprivates.getArrayRef(), SourceLocation(),
6312 ClausesWithImplicit.push_back(Implicit);
6313 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6314 ImpInfo.Firstprivates.size();
6315 } else {
6316 ErrorFound = true;
6317 }
6318 }
6319 if (!ImpInfo.Privates.empty()) {
6321 ImpInfo.Privates.getArrayRef(), SourceLocation(),
6323 ClausesWithImplicit.push_back(Implicit);
6324 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6325 ImpInfo.Privates.size();
6326 } else {
6327 ErrorFound = true;
6328 }
6329 }
6330 // OpenMP 5.0 [2.19.7]
6331 // If a list item appears in a reduction, lastprivate or linear
6332 // clause on a combined target construct then it is treated as
6333 // if it also appears in a map clause with a map-type of tofrom
6334 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6336 SmallVector<Expr *, 4> ImplicitExprs;
6337 for (OMPClause *C : Clauses) {
6338 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6339 for (Expr *E : RC->varlist())
6341 ImplicitExprs.emplace_back(E);
6342 }
6343 if (!ImplicitExprs.empty()) {
6344 ArrayRef<Expr *> Exprs = ImplicitExprs;
6345 CXXScopeSpec MapperIdScopeSpec;
6346 DeclarationNameInfo MapperId;
6349 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6350 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6351 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6352 ClausesWithImplicit.emplace_back(Implicit);
6353 }
6354 }
6355 for (unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6356 int ClauseKindCnt = -1;
6357 for (unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6358 ArrayRef<Expr *> ImplicitMap = ImpInfo.Mappings[I][J].getArrayRef();
6359 ++ClauseKindCnt;
6360 if (ImplicitMap.empty())
6361 continue;
6362 CXXScopeSpec MapperIdScopeSpec;
6363 DeclarationNameInfo MapperId;
6364 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6366 nullptr, ImpInfo.MapModifiers[I], ImplicitMapModifiersLoc[I],
6367 MapperIdScopeSpec, MapperId, K, /*IsMapTypeImplicit=*/true,
6368 SourceLocation(), SourceLocation(), ImplicitMap,
6369 OMPVarListLocTy())) {
6370 ClausesWithImplicit.emplace_back(Implicit);
6371 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6372 ImplicitMap.size();
6373 } else {
6374 ErrorFound = true;
6375 }
6376 }
6377 }
6378 // Build expressions for implicit maps of data members with 'default'
6379 // mappers.
6380 if (getLangOpts().OpenMP >= 50)
6382 ClausesWithImplicit);
6383 }
6384
6385 switch (Kind) {
6386 case OMPD_parallel:
6387 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6388 EndLoc);
6389 break;
6390 case OMPD_simd:
6391 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6392 VarsWithInheritedDSA);
6393 break;
6394 case OMPD_tile:
6395 Res =
6396 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6397 break;
6398 case OMPD_stripe:
6399 Res = ActOnOpenMPStripeDirective(ClausesWithImplicit, AStmt, StartLoc,
6400 EndLoc);
6401 break;
6402 case OMPD_unroll:
6403 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6404 EndLoc);
6405 break;
6406 case OMPD_reverse:
6407 assert(ClausesWithImplicit.empty() &&
6408 "reverse directive does not support any clauses");
6409 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6410 break;
6411 case OMPD_interchange:
6412 Res = ActOnOpenMPInterchangeDirective(ClausesWithImplicit, AStmt, StartLoc,
6413 EndLoc);
6414 break;
6415 case OMPD_fuse:
6416 Res =
6417 ActOnOpenMPFuseDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6418 break;
6419 case OMPD_for:
6420 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6421 VarsWithInheritedDSA);
6422 break;
6423 case OMPD_for_simd:
6424 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6425 EndLoc, VarsWithInheritedDSA);
6426 break;
6427 case OMPD_sections:
6428 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6429 EndLoc);
6430 break;
6431 case OMPD_section:
6432 assert(ClausesWithImplicit.empty() &&
6433 "No clauses are allowed for 'omp section' directive");
6434 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6435 break;
6436 case OMPD_single:
6437 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6438 EndLoc);
6439 break;
6440 case OMPD_master:
6441 assert(ClausesWithImplicit.empty() &&
6442 "No clauses are allowed for 'omp master' directive");
6443 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6444 break;
6445 case OMPD_masked:
6446 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6447 EndLoc);
6448 break;
6449 case OMPD_critical:
6450 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6451 StartLoc, EndLoc);
6452 break;
6453 case OMPD_parallel_for:
6454 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6455 EndLoc, VarsWithInheritedDSA);
6456 break;
6457 case OMPD_parallel_for_simd:
6459 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6460 break;
6461 case OMPD_scope:
6462 Res =
6463 ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6464 break;
6465 case OMPD_parallel_master:
6466 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6467 StartLoc, EndLoc);
6468 break;
6469 case OMPD_parallel_masked:
6470 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6471 StartLoc, EndLoc);
6472 break;
6473 case OMPD_parallel_sections:
6474 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6475 StartLoc, EndLoc);
6476 break;
6477 case OMPD_task:
6478 Res =
6479 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6480 break;
6481 case OMPD_taskyield:
6482 assert(ClausesWithImplicit.empty() &&
6483 "No clauses are allowed for 'omp taskyield' directive");
6484 assert(AStmt == nullptr &&
6485 "No associated statement allowed for 'omp taskyield' directive");
6486 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6487 break;
6488 case OMPD_error:
6489 assert(AStmt == nullptr &&
6490 "No associated statement allowed for 'omp error' directive");
6491 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6492 break;
6493 case OMPD_barrier:
6494 assert(ClausesWithImplicit.empty() &&
6495 "No clauses are allowed for 'omp barrier' directive");
6496 assert(AStmt == nullptr &&
6497 "No associated statement allowed for 'omp barrier' directive");
6498 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6499 break;
6500 case OMPD_taskwait:
6501 assert(AStmt == nullptr &&
6502 "No associated statement allowed for 'omp taskwait' directive");
6503 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6504 break;
6505 case OMPD_taskgroup:
6506 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6507 EndLoc);
6508 break;
6509 case OMPD_flush:
6510 assert(AStmt == nullptr &&
6511 "No associated statement allowed for 'omp flush' directive");
6512 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6513 break;
6514 case OMPD_depobj:
6515 assert(AStmt == nullptr &&
6516 "No associated statement allowed for 'omp depobj' directive");
6517 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6518 break;
6519 case OMPD_scan:
6520 assert(AStmt == nullptr &&
6521 "No associated statement allowed for 'omp scan' directive");
6522 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6523 break;
6524 case OMPD_ordered:
6525 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6526 EndLoc);
6527 break;
6528 case OMPD_atomic:
6529 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6530 EndLoc);
6531 break;
6532 case OMPD_teams:
6533 Res =
6534 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6535 break;
6536 case OMPD_target:
6537 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6538 EndLoc);
6539 break;
6540 case OMPD_target_parallel:
6541 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6542 StartLoc, EndLoc);
6543 break;
6544 case OMPD_target_parallel_for:
6546 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6547 break;
6548 case OMPD_cancellation_point:
6549 assert(ClausesWithImplicit.empty() &&
6550 "No clauses are allowed for 'omp cancellation point' directive");
6551 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6552 "cancellation point' directive");
6553 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6554 break;
6555 case OMPD_cancel:
6556 assert(AStmt == nullptr &&
6557 "No associated statement allowed for 'omp cancel' directive");
6558 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6559 CancelRegion);
6560 break;
6561 case OMPD_target_data:
6562 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6563 EndLoc);
6564 break;
6565 case OMPD_target_enter_data:
6566 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6567 EndLoc, AStmt);
6568 break;
6569 case OMPD_target_exit_data:
6570 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6571 EndLoc, AStmt);
6572 break;
6573 case OMPD_taskloop:
6574 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6575 EndLoc, VarsWithInheritedDSA);
6576 break;
6577 case OMPD_taskloop_simd:
6578 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6579 EndLoc, VarsWithInheritedDSA);
6580 break;
6581 case OMPD_master_taskloop:
6583 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6584 break;
6585 case OMPD_masked_taskloop:
6587 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6588 break;
6589 case OMPD_master_taskloop_simd:
6591 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6592 break;
6593 case OMPD_masked_taskloop_simd:
6595 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6596 break;
6597 case OMPD_parallel_master_taskloop:
6599 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6600 break;
6601 case OMPD_parallel_masked_taskloop:
6603 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6604 break;
6605 case OMPD_parallel_master_taskloop_simd:
6607 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6608 break;
6609 case OMPD_parallel_masked_taskloop_simd:
6611 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6612 break;
6613 case OMPD_distribute:
6614 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6615 EndLoc, VarsWithInheritedDSA);
6616 break;
6617 case OMPD_target_update:
6618 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6619 EndLoc, AStmt);
6620 break;
6621 case OMPD_distribute_parallel_for:
6623 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6624 break;
6625 case OMPD_distribute_parallel_for_simd:
6627 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6628 break;
6629 case OMPD_distribute_simd:
6631 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6632 break;
6633 case OMPD_target_parallel_for_simd:
6635 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6636 break;
6637 case OMPD_target_simd:
6638 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6639 EndLoc, VarsWithInheritedDSA);
6640 break;
6641 case OMPD_teams_distribute:
6643 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6644 break;
6645 case OMPD_teams_distribute_simd:
6647 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6648 break;
6649 case OMPD_teams_distribute_parallel_for_simd:
6651 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6652 break;
6653 case OMPD_teams_distribute_parallel_for:
6655 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6656 break;
6657 case OMPD_target_teams:
6658 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6659 EndLoc);
6660 break;
6661 case OMPD_target_teams_distribute:
6663 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6664 break;
6665 case OMPD_target_teams_distribute_parallel_for:
6667 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6668 break;
6669 case OMPD_target_teams_distribute_parallel_for_simd:
6671 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6672 break;
6673 case OMPD_target_teams_distribute_simd:
6675 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6676 break;
6677 case OMPD_interop:
6678 assert(AStmt == nullptr &&
6679 "No associated statement allowed for 'omp interop' directive");
6680 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6681 break;
6682 case OMPD_dispatch:
6683 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6684 EndLoc);
6685 break;
6686 case OMPD_loop:
6687 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6688 EndLoc, VarsWithInheritedDSA);
6689 break;
6690 case OMPD_teams_loop:
6692 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6693 break;
6694 case OMPD_target_teams_loop:
6696 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6697 break;
6698 case OMPD_parallel_loop:
6700 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6701 break;
6702 case OMPD_target_parallel_loop:
6704 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6705 break;
6706 case OMPD_declare_target:
6707 case OMPD_end_declare_target:
6708 case OMPD_threadprivate:
6709 case OMPD_allocate:
6710 case OMPD_declare_reduction:
6711 case OMPD_declare_mapper:
6712 case OMPD_declare_simd:
6713 case OMPD_requires:
6714 case OMPD_declare_variant:
6715 case OMPD_begin_declare_variant:
6716 case OMPD_end_declare_variant:
6717 llvm_unreachable("OpenMP Directive is not allowed");
6718 case OMPD_unknown:
6719 default:
6720 llvm_unreachable("Unknown OpenMP directive");
6721 }
6722
6723 ErrorFound = Res.isInvalid() || ErrorFound;
6724
6725 // Check variables in the clauses if default(none) or
6726 // default(firstprivate) was specified.
6727 if (DSAStack->getDefaultDSA() == DSA_none ||
6728 DSAStack->getDefaultDSA() == DSA_private ||
6729 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6730 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6731 for (OMPClause *C : Clauses) {
6732 switch (C->getClauseKind()) {
6733 case OMPC_num_threads:
6734 case OMPC_dist_schedule:
6735 // Do not analyze if no parent teams directive.
6736 if (isOpenMPTeamsDirective(Kind))
6737 break;
6738 continue;
6739 case OMPC_if:
6740 if (isOpenMPTeamsDirective(Kind) &&
6741 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6742 break;
6743 if (isOpenMPParallelDirective(Kind) &&
6745 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6746 break;
6747 continue;
6748 case OMPC_schedule:
6749 case OMPC_detach:
6750 break;
6751 case OMPC_grainsize:
6752 case OMPC_num_tasks:
6753 case OMPC_final:
6754 case OMPC_priority:
6755 case OMPC_novariants:
6756 case OMPC_nocontext:
6757 // Do not analyze if no parent parallel directive.
6758 if (isOpenMPParallelDirective(Kind))
6759 break;
6760 continue;
6761 case OMPC_ordered:
6762 case OMPC_device:
6763 case OMPC_num_teams:
6764 case OMPC_thread_limit:
6765 case OMPC_hint:
6766 case OMPC_collapse:
6767 case OMPC_safelen:
6768 case OMPC_simdlen:
6769 case OMPC_sizes:
6770 case OMPC_default:
6771 case OMPC_proc_bind:
6772 case OMPC_private:
6773 case OMPC_firstprivate:
6774 case OMPC_lastprivate:
6775 case OMPC_shared:
6776 case OMPC_reduction:
6777 case OMPC_task_reduction:
6778 case OMPC_in_reduction:
6779 case OMPC_linear:
6780 case OMPC_aligned:
6781 case OMPC_copyin:
6782 case OMPC_copyprivate:
6783 case OMPC_nowait:
6784 case OMPC_untied:
6785 case OMPC_mergeable:
6786 case OMPC_allocate:
6787 case OMPC_read:
6788 case OMPC_write:
6789 case OMPC_update:
6790 case OMPC_capture:
6791 case OMPC_compare:
6792 case OMPC_seq_cst:
6793 case OMPC_acq_rel:
6794 case OMPC_acquire:
6795 case OMPC_release:
6796 case OMPC_relaxed:
6797 case OMPC_depend:
6798 case OMPC_threads:
6799 case OMPC_simd:
6800 case OMPC_map:
6801 case OMPC_nogroup:
6802 case OMPC_defaultmap:
6803 case OMPC_to:
6804 case OMPC_from:
6805 case OMPC_use_device_ptr:
6806 case OMPC_use_device_addr:
6807 case OMPC_is_device_ptr:
6808 case OMPC_has_device_addr:
6809 case OMPC_nontemporal:
6810 case OMPC_order:
6811 case OMPC_destroy:
6812 case OMPC_inclusive:
6813 case OMPC_exclusive:
6814 case OMPC_uses_allocators:
6815 case OMPC_affinity:
6816 case OMPC_bind:
6817 case OMPC_filter:
6818 case OMPC_severity:
6819 case OMPC_message:
6820 continue;
6821 case OMPC_allocator:
6822 case OMPC_flush:
6823 case OMPC_depobj:
6824 case OMPC_threadprivate:
6825 case OMPC_groupprivate:
6826 case OMPC_uniform:
6827 case OMPC_unknown:
6828 case OMPC_unified_address:
6829 case OMPC_unified_shared_memory:
6830 case OMPC_reverse_offload:
6831 case OMPC_dynamic_allocators:
6832 case OMPC_atomic_default_mem_order:
6833 case OMPC_self_maps:
6834 case OMPC_device_type:
6835 case OMPC_match:
6836 case OMPC_when:
6837 case OMPC_at:
6838 default:
6839 llvm_unreachable("Unexpected clause");
6840 }
6841 for (Stmt *CC : C->children()) {
6842 if (CC)
6843 DSAChecker.Visit(CC);
6844 }
6845 }
6846 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6847 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6848 }
6849 for (const auto &P : VarsWithInheritedDSA) {
6850 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6851 continue;
6852 ErrorFound = true;
6853 if (DSAStack->getDefaultDSA() == DSA_none ||
6854 DSAStack->getDefaultDSA() == DSA_private ||
6855 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6856 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6857 << P.first << P.second->getSourceRange();
6858 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6859 } else if (getLangOpts().OpenMP >= 50) {
6860 Diag(P.second->getExprLoc(),
6861 diag::err_omp_defaultmap_no_attr_for_variable)
6862 << P.first << P.second->getSourceRange();
6863 Diag(DSAStack->getDefaultDSALocation(),
6864 diag::note_omp_defaultmap_attr_none);
6865 }
6866 }
6867
6868 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6869 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(Kind)) {
6870 if (isAllowedClauseForDirective(D, OMPC_if, getLangOpts().OpenMP))
6871 AllowedNameModifiers.push_back(D);
6872 }
6873 if (!AllowedNameModifiers.empty())
6874 ErrorFound = checkIfClauses(SemaRef, Kind, Clauses, AllowedNameModifiers) ||
6875 ErrorFound;
6876
6877 if (ErrorFound)
6878 return StmtError();
6879
6880 if (!SemaRef.CurContext->isDependentContext() &&
6882 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6883 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6884 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6885 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6886 // Register target to DSA Stack.
6887 DSAStack->addTargetDirLocation(StartLoc);
6888 }
6889
6890 return Res;
6891}
6892
6894 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6895 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6896 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6897 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6898 assert(Aligneds.size() == Alignments.size());
6899 assert(Linears.size() == LinModifiers.size());
6900 assert(Linears.size() == Steps.size());
6901 if (!DG || DG.get().isNull())
6902 return DeclGroupPtrTy();
6903
6904 const int SimdId = 0;
6905 if (!DG.get().isSingleDecl()) {
6906 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6907 << SimdId;
6908 return DG;
6909 }
6910 Decl *ADecl = DG.get().getSingleDecl();
6911 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6912 ADecl = FTD->getTemplatedDecl();
6913
6914 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6915 if (!FD) {
6916 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6917 return DeclGroupPtrTy();
6918 }
6919
6920 // OpenMP [2.8.2, declare simd construct, Description]
6921 // The parameter of the simdlen clause must be a constant positive integer
6922 // expression.
6923 ExprResult SL;
6924 if (Simdlen)
6925 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6926 // OpenMP [2.8.2, declare simd construct, Description]
6927 // The special this pointer can be used as if was one of the arguments to the
6928 // function in any of the linear, aligned, or uniform clauses.
6929 // The uniform clause declares one or more arguments to have an invariant
6930 // value for all concurrent invocations of the function in the execution of a
6931 // single SIMD loop.
6932 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6933 const Expr *UniformedLinearThis = nullptr;
6934 for (const Expr *E : Uniforms) {
6935 E = E->IgnoreParenImpCasts();
6936 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6937 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6938 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6939 FD->getParamDecl(PVD->getFunctionScopeIndex())
6940 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
6941 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6942 continue;
6943 }
6944 if (isa<CXXThisExpr>(E)) {
6945 UniformedLinearThis = E;
6946 continue;
6947 }
6948 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6949 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6950 }
6951 // OpenMP [2.8.2, declare simd construct, Description]
6952 // The aligned clause declares that the object to which each list item points
6953 // is aligned to the number of bytes expressed in the optional parameter of
6954 // the aligned clause.
6955 // The special this pointer can be used as if was one of the arguments to the
6956 // function in any of the linear, aligned, or uniform clauses.
6957 // The type of list items appearing in the aligned clause must be array,
6958 // pointer, reference to array, or reference to pointer.
6959 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6960 const Expr *AlignedThis = nullptr;
6961 for (const Expr *E : Aligneds) {
6962 E = E->IgnoreParenImpCasts();
6963 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6964 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6965 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6966 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6967 FD->getParamDecl(PVD->getFunctionScopeIndex())
6968 ->getCanonicalDecl() == CanonPVD) {
6969 // OpenMP [2.8.1, simd construct, Restrictions]
6970 // A list-item cannot appear in more than one aligned clause.
6971 auto [It, Inserted] = AlignedArgs.try_emplace(CanonPVD, E);
6972 if (!Inserted) {
6973 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6974 << 1 << getOpenMPClauseNameForDiag(OMPC_aligned)
6975 << E->getSourceRange();
6976 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
6977 << getOpenMPClauseNameForDiag(OMPC_aligned);
6978 continue;
6979 }
6980 QualType QTy = PVD->getType()
6981 .getNonReferenceType()
6982 .getUnqualifiedType()
6983 .getCanonicalType();
6984 const Type *Ty = QTy.getTypePtrOrNull();
6985 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
6986 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
6987 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
6988 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6989 }
6990 continue;
6991 }
6992 }
6993 if (isa<CXXThisExpr>(E)) {
6994 if (AlignedThis) {
6995 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6996 << 2 << getOpenMPClauseNameForDiag(OMPC_aligned)
6997 << E->getSourceRange();
6998 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
6999 << getOpenMPClauseNameForDiag(OMPC_aligned);
7000 }
7001 AlignedThis = E;
7002 continue;
7003 }
7004 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7005 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7006 }
7007 // The optional parameter of the aligned clause, alignment, must be a constant
7008 // positive integer expression. If no optional parameter is specified,
7009 // implementation-defined default alignments for SIMD instructions on the
7010 // target platforms are assumed.
7012 for (Expr *E : Alignments) {
7013 ExprResult Align;
7014 if (E)
7015 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
7016 NewAligns.push_back(Align.get());
7017 }
7018 // OpenMP [2.8.2, declare simd construct, Description]
7019 // The linear clause declares one or more list items to be private to a SIMD
7020 // lane and to have a linear relationship with respect to the iteration space
7021 // of a loop.
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 // When a linear-step expression is specified in a linear clause it must be
7025 // either a constant integer expression or an integer-typed parameter that is
7026 // specified in a uniform clause on the directive.
7027 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7028 const bool IsUniformedThis = UniformedLinearThis != nullptr;
7029 auto MI = LinModifiers.begin();
7030 for (const Expr *E : Linears) {
7031 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
7032 ++MI;
7033 E = E->IgnoreParenImpCasts();
7034 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7035 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7036 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7037 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7038 FD->getParamDecl(PVD->getFunctionScopeIndex())
7039 ->getCanonicalDecl() == CanonPVD) {
7040 // OpenMP [2.15.3.7, linear Clause, Restrictions]
7041 // A list-item cannot appear in more than one linear clause.
7042 if (auto It = LinearArgs.find(CanonPVD); It != LinearArgs.end()) {
7043 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7044 << getOpenMPClauseNameForDiag(OMPC_linear)
7045 << getOpenMPClauseNameForDiag(OMPC_linear)
7046 << E->getSourceRange();
7047 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7048 << getOpenMPClauseNameForDiag(OMPC_linear);
7049 continue;
7050 }
7051 // Each argument can appear in at most one uniform or linear clause.
7052 if (auto It = UniformedArgs.find(CanonPVD);
7053 It != UniformedArgs.end()) {
7054 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7055 << getOpenMPClauseNameForDiag(OMPC_linear)
7056 << getOpenMPClauseNameForDiag(OMPC_uniform)
7057 << E->getSourceRange();
7058 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7059 << getOpenMPClauseNameForDiag(OMPC_uniform);
7060 continue;
7061 }
7062 LinearArgs[CanonPVD] = E;
7063 if (E->isValueDependent() || E->isTypeDependent() ||
7066 continue;
7067 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
7068 PVD->getOriginalType(),
7069 /*IsDeclareSimd=*/true);
7070 continue;
7071 }
7072 }
7073 if (isa<CXXThisExpr>(E)) {
7074 if (UniformedLinearThis) {
7075 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7076 << getOpenMPClauseNameForDiag(OMPC_linear)
7077 << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
7078 : OMPC_linear)
7079 << E->getSourceRange();
7080 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
7081 << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
7082 : OMPC_linear);
7083 continue;
7084 }
7085 UniformedLinearThis = E;
7086 if (E->isValueDependent() || E->isTypeDependent() ||
7088 continue;
7089 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
7090 E->getType(), /*IsDeclareSimd=*/true);
7091 continue;
7092 }
7093 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7094 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7095 }
7096 Expr *Step = nullptr;
7097 Expr *NewStep = nullptr;
7098 SmallVector<Expr *, 4> NewSteps;
7099 for (Expr *E : Steps) {
7100 // Skip the same step expression, it was checked already.
7101 if (Step == E || !E) {
7102 NewSteps.push_back(E ? NewStep : nullptr);
7103 continue;
7104 }
7105 Step = E;
7106 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
7107 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7108 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7109 if (UniformedArgs.count(CanonPVD) == 0) {
7110 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
7111 << Step->getSourceRange();
7112 } else if (E->isValueDependent() || E->isTypeDependent() ||
7115 CanonPVD->getType()->hasIntegerRepresentation()) {
7116 NewSteps.push_back(Step);
7117 } else {
7118 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
7119 << Step->getSourceRange();
7120 }
7121 continue;
7122 }
7123 NewStep = Step;
7124 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
7125 !Step->isInstantiationDependent() &&
7127 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
7128 .get();
7129 if (NewStep)
7130 NewStep = SemaRef
7131 .VerifyIntegerConstantExpression(
7132 NewStep, /*FIXME*/ AllowFoldKind::Allow)
7133 .get();
7134 }
7135 NewSteps.push_back(NewStep);
7136 }
7137 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7138 getASTContext(), BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
7139 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
7140 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
7141 const_cast<Expr **>(Linears.data()), Linears.size(),
7142 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
7143 NewSteps.data(), NewSteps.size(), SR);
7144 ADecl->addAttr(NewAttr);
7145 return DG;
7146}
7147
7149 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
7150 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
7151 SourceLocation EndLoc) {
7152 assert(isOpenMPInformationalDirective(Kind) &&
7153 "Unexpected directive category");
7154
7155 StmtResult Res = StmtError();
7156
7157 switch (Kind) {
7158 case OMPD_assume:
7159 Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc);
7160 break;
7161 default:
7162 llvm_unreachable("Unknown OpenMP directive");
7163 }
7164
7165 return Res;
7166}
7167
7168static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7169 QualType NewType) {
7170 assert(NewType->isFunctionProtoType() &&
7171 "Expected function type with prototype.");
7172 assert(FD->getType()->isFunctionNoProtoType() &&
7173 "Expected function with type with no prototype.");
7174 assert(FDWithProto->getType()->isFunctionProtoType() &&
7175 "Expected function with prototype.");
7176 // Synthesize parameters with the same types.
7177 FD->setType(NewType);
7179 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7180 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
7181 SourceLocation(), nullptr, P->getType(),
7182 /*TInfo=*/nullptr, SC_None, nullptr);
7183 Param->setScopeInfo(0, Params.size());
7184 Param->setImplicit();
7185 Params.push_back(Param);
7186 }
7187
7188 FD->setParams(Params);
7189}
7190
7192 if (D->isInvalidDecl())
7193 return;
7194 FunctionDecl *FD = nullptr;
7195 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7196 FD = UTemplDecl->getTemplatedDecl();
7197 else
7198 FD = cast<FunctionDecl>(D);
7199 assert(FD && "Expected a function declaration!");
7200
7201 // If we are instantiating templates we do *not* apply scoped assumptions but
7202 // only global ones. We apply scoped assumption to the template definition
7203 // though.
7204 if (!SemaRef.inTemplateInstantiation()) {
7205 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7206 FD->addAttr(AA);
7207 }
7208 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7209 FD->addAttr(AA);
7210}
7211
7212SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7213 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7214
7216 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7218 if (!D.getIdentifier())
7219 return;
7220
7221 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7222
7223 // Template specialization is an extension, check if we do it.
7224 bool IsTemplated = !TemplateParamLists.empty();
7225 if (IsTemplated &&
7226 !DVScope.TI->isExtensionActive(
7227 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7228 return;
7229
7230 const IdentifierInfo *BaseII = D.getIdentifier();
7233 SemaRef.LookupParsedName(Lookup, S, &D.getCXXScopeSpec(),
7234 /*ObjectType=*/QualType());
7235
7236 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
7237 QualType FType = TInfo->getType();
7238
7239 bool IsConstexpr =
7241 bool IsConsteval =
7243
7244 for (auto *Candidate : Lookup) {
7245 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7246 FunctionDecl *UDecl = nullptr;
7247 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7248 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7249 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7250 UDecl = FTD->getTemplatedDecl();
7251 } else if (!IsTemplated)
7252 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7253 if (!UDecl)
7254 continue;
7255
7256 // Don't specialize constexpr/consteval functions with
7257 // non-constexpr/consteval functions.
7258 if (UDecl->isConstexpr() && !IsConstexpr)
7259 continue;
7260 if (UDecl->isConsteval() && !IsConsteval)
7261 continue;
7262
7263 QualType UDeclTy = UDecl->getType();
7264 if (!UDeclTy->isDependentType()) {
7266 FType, UDeclTy, /*OfBlockPointer=*/false,
7267 /*Unqualified=*/false, /*AllowCXX=*/true);
7268 if (NewType.isNull())
7269 continue;
7270 }
7271
7272 // Found a base!
7273 Bases.push_back(UDecl);
7274 }
7275
7276 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7277 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7278 // If no base was found we create a declaration that we use as base.
7279 if (Bases.empty() && UseImplicitBase) {
7281 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7282 BaseD->setImplicit(true);
7283 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7284 Bases.push_back(BaseTemplD->getTemplatedDecl());
7285 else
7286 Bases.push_back(cast<FunctionDecl>(BaseD));
7287 }
7288
7289 std::string MangledName;
7290 MangledName += D.getIdentifier()->getName();
7291 MangledName += getOpenMPVariantManglingSeparatorStr();
7292 MangledName += DVScope.NameSuffix;
7293 IdentifierInfo &VariantII = getASTContext().Idents.get(MangledName);
7294
7295 VariantII.setMangledOpenMPVariantName(true);
7296 D.SetIdentifier(&VariantII, D.getBeginLoc());
7297}
7298
7301 // Do not mark function as is used to prevent its emission if this is the
7302 // only place where it is used.
7305
7306 FunctionDecl *FD = nullptr;
7307 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7308 FD = UTemplDecl->getTemplatedDecl();
7309 else
7310 FD = cast<FunctionDecl>(D);
7311 auto *VariantFuncRef = DeclRefExpr::Create(
7313 /*RefersToEnclosingVariableOrCapture=*/false,
7314 /*NameLoc=*/FD->getLocation(), FD->getType(), ExprValueKind::VK_PRValue);
7315
7316 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7317 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7318 getASTContext(), VariantFuncRef, DVScope.TI,
7319 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7320 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7321 /*NeedDeviceAddrArgs=*/nullptr, /*NeedDeviceAddrArgsSize=*/0,
7322 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7323 for (FunctionDecl *BaseFD : Bases)
7324 BaseFD->addAttr(OMPDeclareVariantA);
7325}
7326
7328 SourceLocation LParenLoc,
7329 MultiExprArg ArgExprs,
7330 SourceLocation RParenLoc,
7331 Expr *ExecConfig) {
7332 // The common case is a regular call we do not want to specialize at all. Try
7333 // to make that case fast by bailing early.
7334 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7335 if (!CE)
7336 return Call;
7337
7338 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7339 if (!CalleeFnDecl)
7340 return Call;
7341
7342 if (getLangOpts().OpenMP >= 50 && getLangOpts().OpenMP <= 60 &&
7343 CalleeFnDecl->getIdentifier() &&
7344 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7345 // checking for any calls inside an Order region
7347 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7348 }
7349
7350 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7351 return Call;
7352
7353 ASTContext &Context = getASTContext();
7354 std::function<void(StringRef)> DiagUnknownTrait = [this,
7355 CE](StringRef ISATrait) {
7356 // TODO Track the selector locations in a way that is accessible here to
7357 // improve the diagnostic location.
7358 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7359 << ISATrait;
7360 };
7361 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7362 SemaRef.getCurFunctionDecl(),
7363 DSAStack->getConstructTraits(), getOpenMPDeviceNum());
7364
7365 QualType CalleeFnType = CalleeFnDecl->getType();
7366
7369 while (CalleeFnDecl) {
7370 for (OMPDeclareVariantAttr *A :
7371 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7372 Expr *VariantRef = A->getVariantFuncRef();
7373
7374 VariantMatchInfo VMI;
7375 OMPTraitInfo &TI = A->getTraitInfo();
7376 TI.getAsVariantMatchInfo(Context, VMI);
7377 if (!isVariantApplicableInContext(VMI, OMPCtx,
7378 /*DeviceSetOnly=*/false))
7379 continue;
7380
7381 VMIs.push_back(VMI);
7382 Exprs.push_back(VariantRef);
7383 }
7384
7385 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7386 }
7387
7388 ExprResult NewCall;
7389 do {
7390 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7391 if (BestIdx < 0)
7392 return Call;
7393 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7394 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7395
7396 {
7397 // Try to build a (member) call expression for the current best applicable
7398 // variant expression. We allow this to fail in which case we continue
7399 // with the next best variant expression. The fail case is part of the
7400 // implementation defined behavior in the OpenMP standard when it talks
7401 // about what differences in the function prototypes: "Any differences
7402 // that the specific OpenMP context requires in the prototype of the
7403 // variant from the base function prototype are implementation defined."
7404 // This wording is there to allow the specialized variant to have a
7405 // different type than the base function. This is intended and OK but if
7406 // we cannot create a call the difference is not in the "implementation
7407 // defined range" we allow.
7409
7410 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7411 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7412 BestExpr = MemberExpr::CreateImplicit(
7413 Context, MemberCall->getImplicitObjectArgument(),
7414 /*IsArrow=*/false, SpecializedMethod, Context.BoundMemberTy,
7415 MemberCall->getValueKind(), MemberCall->getObjectKind());
7416 }
7417 NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs,
7418 RParenLoc, ExecConfig);
7419 if (NewCall.isUsable()) {
7420 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7421 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7423 CalleeFnType, NewCalleeFnDecl->getType(),
7424 /*OfBlockPointer=*/false,
7425 /*Unqualified=*/false, /*AllowCXX=*/true);
7426 if (!NewType.isNull())
7427 break;
7428 // Don't use the call if the function type was not compatible.
7429 NewCall = nullptr;
7430 }
7431 }
7432 }
7433
7434 VMIs.erase(VMIs.begin() + BestIdx);
7435 Exprs.erase(Exprs.begin() + BestIdx);
7436 } while (!VMIs.empty());
7437
7438 if (!NewCall.isUsable())
7439 return Call;
7440 return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
7441}
7442
7443std::optional<std::pair<FunctionDecl *, Expr *>>
7445 Expr *VariantRef,
7446 OMPTraitInfo &TI,
7447 unsigned NumAppendArgs,
7448 SourceRange SR) {
7449 ASTContext &Context = getASTContext();
7450 if (!DG || DG.get().isNull())
7451 return std::nullopt;
7452
7453 const int VariantId = 1;
7454 // Must be applied only to single decl.
7455 if (!DG.get().isSingleDecl()) {
7456 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7457 << VariantId << SR;
7458 return std::nullopt;
7459 }
7460 Decl *ADecl = DG.get().getSingleDecl();
7461 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7462 ADecl = FTD->getTemplatedDecl();
7463
7464 // Decl must be a function.
7465 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7466 if (!FD) {
7467 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7468 << VariantId << SR;
7469 return std::nullopt;
7470 }
7471
7472 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7473 // The 'target' attribute needs to be separately checked because it does
7474 // not always signify a multiversion function declaration.
7475 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7476 };
7477 // OpenMP is not compatible with multiversion function attributes.
7478 if (HasMultiVersionAttributes(FD)) {
7479 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7480 << SR;
7481 return std::nullopt;
7482 }
7483
7484 // Allow #pragma omp declare variant only if the function is not used.
7485 if (FD->isUsed(false))
7486 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7487 << FD->getLocation();
7488
7489 // Check if the function was emitted already.
7490 const FunctionDecl *Definition;
7491 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7492 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7493 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7494 << FD->getLocation();
7495
7496 // The VariantRef must point to function.
7497 if (!VariantRef) {
7498 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7499 return std::nullopt;
7500 }
7501
7502 auto ShouldDelayChecks = [](Expr *&E, bool) {
7503 return E && (E->isTypeDependent() || E->isValueDependent() ||
7506 };
7507 // Do not check templates, wait until instantiation.
7508 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7509 TI.anyScoreOrCondition(ShouldDelayChecks))
7510 return std::make_pair(FD, VariantRef);
7511
7512 // Deal with non-constant score and user condition expressions.
7513 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7514 bool IsScore) -> bool {
7515 if (!E || E->isIntegerConstantExpr(getASTContext()))
7516 return false;
7517
7518 if (IsScore) {
7519 // We warn on non-constant scores and pretend they were not present.
7520 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7521 << E;
7522 E = nullptr;
7523 } else {
7524 // We could replace a non-constant user condition with "false" but we
7525 // will soon need to handle these anyway for the dynamic version of
7526 // OpenMP context selectors.
7527 Diag(E->getExprLoc(),
7528 diag::err_omp_declare_variant_user_condition_not_constant)
7529 << E;
7530 }
7531 return true;
7532 };
7533 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7534 return std::nullopt;
7535
7536 QualType AdjustedFnType = FD->getType();
7537 if (NumAppendArgs) {
7538 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7539 if (!PTy) {
7540 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7541 << SR;
7542 return std::nullopt;
7543 }
7544 // Adjust the function type to account for an extra omp_interop_t for each
7545 // specified in the append_args clause.
7546 const TypeDecl *TD = nullptr;
7547 LookupResult Result(SemaRef, &Context.Idents.get("omp_interop_t"),
7549 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
7550 NamedDecl *ND = Result.getFoundDecl();
7551 TD = dyn_cast_or_null<TypeDecl>(ND);
7552 }
7553 if (!TD) {
7554 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7555 return std::nullopt;
7556 }
7557 QualType InteropType =
7558 Context.getTypeDeclType(ElaboratedTypeKeyword::None,
7559 /*Qualifier=*/std::nullopt, TD);
7560 if (PTy->isVariadic()) {
7561 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7562 return std::nullopt;
7563 }
7565 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7566 Params.insert(Params.end(), NumAppendArgs, InteropType);
7567 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7568 PTy->getExtProtoInfo());
7569 }
7570
7571 // Convert VariantRef expression to the type of the original function to
7572 // resolve possible conflicts.
7573 ExprResult VariantRefCast = VariantRef;
7574 if (getLangOpts().CPlusPlus) {
7575 QualType FnPtrType;
7576 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7577 if (Method && !Method->isStatic()) {
7578 FnPtrType = Context.getMemberPointerType(
7579 AdjustedFnType, /*Qualifier=*/std::nullopt, Method->getParent());
7580 ExprResult ER;
7581 {
7582 // Build addr_of unary op to correctly handle type checks for member
7583 // functions.
7585 ER = SemaRef.CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7586 VariantRef);
7587 }
7588 if (!ER.isUsable()) {
7589 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7590 << VariantId << VariantRef->getSourceRange();
7591 return std::nullopt;
7592 }
7593 VariantRef = ER.get();
7594 } else {
7595 FnPtrType = Context.getPointerType(AdjustedFnType);
7596 }
7597 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7598 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7599 ImplicitConversionSequence ICS = SemaRef.TryImplicitConversion(
7600 VariantRef, FnPtrType.getUnqualifiedType(),
7601 /*SuppressUserConversions=*/false, Sema::AllowedExplicit::None,
7602 /*InOverloadResolution=*/false,
7603 /*CStyle=*/false,
7604 /*AllowObjCWritebackConversion=*/false);
7605 if (ICS.isFailure()) {
7606 Diag(VariantRef->getExprLoc(),
7607 diag::err_omp_declare_variant_incompat_types)
7608 << VariantRef->getType()
7609 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7610 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7611 return std::nullopt;
7612 }
7613 VariantRefCast = SemaRef.PerformImplicitConversion(
7614 VariantRef, FnPtrType.getUnqualifiedType(),
7616 if (!VariantRefCast.isUsable())
7617 return std::nullopt;
7618 }
7619 // Drop previously built artificial addr_of unary op for member functions.
7620 if (Method && !Method->isStatic()) {
7621 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7622 if (auto *UO = dyn_cast<UnaryOperator>(
7623 PossibleAddrOfVariantRef->IgnoreImplicit()))
7624 VariantRefCast = UO->getSubExpr();
7625 }
7626 }
7627
7628 ExprResult ER = SemaRef.CheckPlaceholderExpr(VariantRefCast.get());
7629 if (!ER.isUsable() ||
7631 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7632 << VariantId << VariantRef->getSourceRange();
7633 return std::nullopt;
7634 }
7635
7636 // The VariantRef must point to function.
7637 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7638 if (!DRE) {
7639 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7640 << VariantId << VariantRef->getSourceRange();
7641 return std::nullopt;
7642 }
7643 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7644 if (!NewFD) {
7645 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7646 << VariantId << VariantRef->getSourceRange();
7647 return std::nullopt;
7648 }
7649
7650 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7651 Diag(VariantRef->getExprLoc(),
7652 diag::err_omp_declare_variant_same_base_function)
7653 << VariantRef->getSourceRange();
7654 return std::nullopt;
7655 }
7656
7657 // Check if function types are compatible in C.
7658 if (!getLangOpts().CPlusPlus) {
7659 QualType NewType =
7660 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7661 if (NewType.isNull()) {
7662 Diag(VariantRef->getExprLoc(),
7663 diag::err_omp_declare_variant_incompat_types)
7664 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7665 << VariantRef->getSourceRange();
7666 return std::nullopt;
7667 }
7668 if (NewType->isFunctionProtoType()) {
7669 if (FD->getType()->isFunctionNoProtoType())
7670 setPrototype(SemaRef, FD, NewFD, NewType);
7671 else if (NewFD->getType()->isFunctionNoProtoType())
7672 setPrototype(SemaRef, NewFD, FD, NewType);
7673 }
7674 }
7675
7676 // Check if variant function is not marked with declare variant directive.
7677 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7678 Diag(VariantRef->getExprLoc(),
7679 diag::warn_omp_declare_variant_marked_as_declare_variant)
7680 << VariantRef->getSourceRange();
7681 SourceRange SR =
7682 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7683 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7684 return std::nullopt;
7685 }
7686
7687 enum DoesntSupport {
7688 VirtFuncs = 1,
7689 Constructors = 3,
7690 Destructors = 4,
7691 DeletedFuncs = 5,
7692 DefaultedFuncs = 6,
7693 ConstexprFuncs = 7,
7694 ConstevalFuncs = 8,
7695 };
7696 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7697 if (CXXFD->isVirtual()) {
7698 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7699 << VirtFuncs;
7700 return std::nullopt;
7701 }
7702
7703 if (isa<CXXConstructorDecl>(FD)) {
7704 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7705 << Constructors;
7706 return std::nullopt;
7707 }
7708
7709 if (isa<CXXDestructorDecl>(FD)) {
7710 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7711 << Destructors;
7712 return std::nullopt;
7713 }
7714 }
7715
7716 if (FD->isDeleted()) {
7717 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7718 << DeletedFuncs;
7719 return std::nullopt;
7720 }
7721
7722 if (FD->isDefaulted()) {
7723 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7724 << DefaultedFuncs;
7725 return std::nullopt;
7726 }
7727
7728 if (FD->isConstexpr()) {
7729 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7730 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7731 return std::nullopt;
7732 }
7733
7734 // Check general compatibility.
7735 if (SemaRef.areMultiversionVariantFunctionsCompatible(
7740 VariantRef->getExprLoc(),
7741 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7742 PartialDiagnosticAt(VariantRef->getExprLoc(),
7743 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7744 << FD->getLocation()),
7745 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7746 /*CLinkageMayDiffer=*/true))
7747 return std::nullopt;
7748 return std::make_pair(FD, cast<Expr>(DRE));
7749}
7750
7752 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7753 ArrayRef<Expr *> AdjustArgsNothing,
7754 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7755 ArrayRef<Expr *> AdjustArgsNeedDeviceAddr,
7756 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7757 SourceLocation AppendArgsLoc, SourceRange SR) {
7758
7759 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7760 // An adjust_args clause or append_args clause can only be specified if the
7761 // dispatch selector of the construct selector set appears in the match
7762 // clause.
7763
7764 SmallVector<Expr *, 8> AllAdjustArgs;
7765 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7766 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7767 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDeviceAddr);
7768
7769 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7770 VariantMatchInfo VMI;
7772 if (!llvm::is_contained(
7773 VMI.ConstructTraits,
7774 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7775 if (!AllAdjustArgs.empty())
7776 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7777 << getOpenMPClauseNameForDiag(OMPC_adjust_args);
7778 if (!AppendArgs.empty())
7779 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7780 << getOpenMPClauseNameForDiag(OMPC_append_args);
7781 return;
7782 }
7783 }
7784
7785 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7786 // Each argument can only appear in a single adjust_args clause for each
7787 // declare variant directive.
7789
7790 for (Expr *E : AllAdjustArgs) {
7791 E = E->IgnoreParenImpCasts();
7792 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7793 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7794 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7795 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7796 FD->getParamDecl(PVD->getFunctionScopeIndex())
7797 ->getCanonicalDecl() == CanonPVD) {
7798 // It's a parameter of the function, check duplicates.
7799 if (!AdjustVars.insert(CanonPVD).second) {
7800 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7801 << PVD;
7802 return;
7803 }
7804 continue;
7805 }
7806 }
7807 }
7808 // Anything that is not a function parameter is an error.
7809 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7810 return;
7811 }
7812
7813 // OpenMP 6.0 [9.6.2 (page 332, line 31-33, adjust_args clause, Restrictions]
7814 // If the `need_device_addr` adjust-op modifier is present, each list item
7815 // that appears in the clause must refer to an argument in the declaration of
7816 // the function variant that has a reference type
7817 if (getLangOpts().OpenMP >= 60) {
7818 for (Expr *E : AdjustArgsNeedDeviceAddr) {
7819 E = E->IgnoreParenImpCasts();
7820 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7821 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
7822 if (!VD->getType()->isReferenceType())
7823 Diag(E->getExprLoc(),
7824 diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
7825 }
7826 }
7827 }
7828 }
7829
7830 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7831 getASTContext(), VariantRef, &TI,
7832 const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7833 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7834 AdjustArgsNeedDevicePtr.size(),
7835 const_cast<Expr **>(AdjustArgsNeedDeviceAddr.data()),
7836 AdjustArgsNeedDeviceAddr.size(),
7837 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7838 FD->addAttr(NewAttr);
7839}
7840
7841static CapturedStmt *
7843 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7844 assert(CS && "Captured statement expected");
7845 // 1.2.2 OpenMP Language Terminology
7846 // Structured block - An executable statement with a single entry at the
7847 // top and a single exit at the bottom.
7848 // The point of exit cannot be a branch out of the structured block.
7849 // longjmp() and throw() must not violate the entry/exit criteria.
7850 CS->getCapturedDecl()->setNothrow();
7851
7852 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
7853 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7855 // 1.2.2 OpenMP Language Terminology
7856 // Structured block - An executable statement with a single entry at the
7857 // top and a single exit at the bottom.
7858 // The point of exit cannot be a branch out of the structured block.
7859 // longjmp() and throw() must not violate the entry/exit criteria.
7860 CS->getCapturedDecl()->setNothrow();
7861 }
7863 return CS;
7864}
7865
7868 Stmt *AStmt, SourceLocation StartLoc,
7869 SourceLocation EndLoc) {
7870 if (!AStmt)
7871 return StmtError();
7872
7873 setBranchProtectedScope(SemaRef, OMPD_parallel, AStmt);
7874
7875 return OMPParallelDirective::Create(
7876 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
7877 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
7878}
7879
7880namespace {
7881/// Iteration space of a single for loop.
7882struct LoopIterationSpace final {
7883 /// True if the condition operator is the strict compare operator (<, > or
7884 /// !=).
7885 bool IsStrictCompare = false;
7886 /// Condition of the loop.
7887 Expr *PreCond = nullptr;
7888 /// This expression calculates the number of iterations in the loop.
7889 /// It is always possible to calculate it before starting the loop.
7890 Expr *NumIterations = nullptr;
7891 /// The loop counter variable.
7892 Expr *CounterVar = nullptr;
7893 /// Private loop counter variable.
7894 Expr *PrivateCounterVar = nullptr;
7895 /// This is initializer for the initial value of #CounterVar.
7896 Expr *CounterInit = nullptr;
7897 /// This is step for the #CounterVar used to generate its update:
7898 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7899 Expr *CounterStep = nullptr;
7900 /// Should step be subtracted?
7901 bool Subtract = false;
7902 /// Source range of the loop init.
7903 SourceRange InitSrcRange;
7904 /// Source range of the loop condition.
7905 SourceRange CondSrcRange;
7906 /// Source range of the loop increment.
7907 SourceRange IncSrcRange;
7908 /// Minimum value that can have the loop control variable. Used to support
7909 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7910 /// since only such variables can be used in non-loop invariant expressions.
7911 Expr *MinValue = nullptr;
7912 /// Maximum value that can have the loop control variable. Used to support
7913 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7914 /// since only such variables can be used in non-loop invariant expressions.
7915 Expr *MaxValue = nullptr;
7916 /// true, if the lower bound depends on the outer loop control var.
7917 bool IsNonRectangularLB = false;
7918 /// true, if the upper bound depends on the outer loop control var.
7919 bool IsNonRectangularUB = false;
7920 /// Index of the loop this loop depends on and forms non-rectangular loop
7921 /// nest.
7922 unsigned LoopDependentIdx = 0;
7923 /// Final condition for the non-rectangular loop nest support. It is used to
7924 /// check that the number of iterations for this particular counter must be
7925 /// finished.
7926 Expr *FinalCondition = nullptr;
7927};
7928
7929/// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls
7930/// set are referenced. Used for verifying loop nest structure before
7931/// performing a loop collapse operation.
7932class ForSubExprChecker : public DynamicRecursiveASTVisitor {
7933 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7934 VarDecl *ForbiddenVar = nullptr;
7935 SourceRange ErrLoc;
7936
7937public:
7938 explicit ForSubExprChecker(
7939 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7940 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
7941 // We want to visit implicit code, i.e. synthetic initialisation statements
7942 // created during range-for lowering.
7943 ShouldVisitImplicitCode = true;
7944 }
7945
7946 bool VisitDeclRefExpr(DeclRefExpr *E) override {
7947 ValueDecl *VD = E->getDecl();
7949 return true;
7950 VarDecl *V = VD->getPotentiallyDecomposedVarDecl();
7951 if (V->getType()->isReferenceType()) {
7952 VarDecl *VD = V->getDefinition();
7953 if (VD->hasInit()) {
7954 Expr *I = VD->getInit();
7955 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
7956 if (!DRE)
7957 return true;
7959 }
7960 }
7961 Decl *Canon = V->getCanonicalDecl();
7962 if (CollapsedLoopVarDecls.contains(Canon)) {
7963 ForbiddenVar = V;
7964 ErrLoc = E->getSourceRange();
7965 return false;
7966 }
7967
7968 return true;
7969 }
7970
7971 VarDecl *getForbiddenVar() const { return ForbiddenVar; }
7972 SourceRange getErrRange() const { return ErrLoc; }
7973};
7974
7975/// Helper class for checking canonical form of the OpenMP loops and
7976/// extracting iteration space of each loop in the loop nest, that will be used
7977/// for IR generation.
7978class OpenMPIterationSpaceChecker {
7979 /// Reference to Sema.
7980 Sema &SemaRef;
7981 /// Does the loop associated directive support non-rectangular loops?
7982 bool SupportsNonRectangular;
7983 /// Data-sharing stack.
7984 DSAStackTy &Stack;
7985 /// A location for diagnostics (when there is no some better location).
7986 SourceLocation DefaultLoc;
7987 /// A location for diagnostics (when increment is not compatible).
7988 SourceLocation ConditionLoc;
7989 /// The set of variables declared within the (to be collapsed) loop nest.
7990 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7991 /// A source location for referring to loop init later.
7992 SourceRange InitSrcRange;
7993 /// A source location for referring to condition later.
7994 SourceRange ConditionSrcRange;
7995 /// A source location for referring to increment later.
7996 SourceRange IncrementSrcRange;
7997 /// Loop variable.
7998 ValueDecl *LCDecl = nullptr;
7999 /// Reference to loop variable.
8000 Expr *LCRef = nullptr;
8001 /// Lower bound (initializer for the var).
8002 Expr *LB = nullptr;
8003 /// Upper bound.
8004 Expr *UB = nullptr;
8005 /// Loop step (increment).
8006 Expr *Step = nullptr;
8007 /// This flag is true when condition is one of:
8008 /// Var < UB
8009 /// Var <= UB
8010 /// UB > Var
8011 /// UB >= Var
8012 /// This will have no value when the condition is !=
8013 std::optional<bool> TestIsLessOp;
8014 /// This flag is true when condition is strict ( < or > ).
8015 bool TestIsStrictOp = false;
8016 /// This flag is true when step is subtracted on each iteration.
8017 bool SubtractStep = false;
8018 /// The outer loop counter this loop depends on (if any).
8019 const ValueDecl *DepDecl = nullptr;
8020 /// Contains number of loop (starts from 1) on which loop counter init
8021 /// expression of this loop depends on.
8022 std::optional<unsigned> InitDependOnLC;
8023 /// Contains number of loop (starts from 1) on which loop counter condition
8024 /// expression of this loop depends on.
8025 std::optional<unsigned> CondDependOnLC;
8026 /// Checks if the provide statement depends on the loop counter.
8027 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
8028 bool IsInitializer);
8029 /// Original condition required for checking of the exit condition for
8030 /// non-rectangular loop.
8031 Expr *Condition = nullptr;
8032
8033public:
8034 OpenMPIterationSpaceChecker(
8035 Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack,
8036 SourceLocation DefaultLoc,
8037 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
8038 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8039 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
8040 CollapsedLoopVarDecls(CollapsedLoopDecls) {}
8041 /// Check init-expr for canonical loop form and save loop counter
8042 /// variable - #Var and its initialization value - #LB.
8043 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
8044 /// Check test-expr for canonical form, save upper-bound (#UB), flags
8045 /// for less/greater and for strict/non-strict comparison.
8046 bool checkAndSetCond(Expr *S);
8047 /// Check incr-expr for canonical loop form and return true if it
8048 /// does not conform, otherwise save loop step (#Step).
8049 bool checkAndSetInc(Expr *S);
8050 /// Return the loop counter variable.
8051 ValueDecl *getLoopDecl() const { return LCDecl; }
8052 /// Return the reference expression to loop counter variable.
8053 Expr *getLoopDeclRefExpr() const { return LCRef; }
8054 /// Source range of the loop init.
8055 SourceRange getInitSrcRange() const { return InitSrcRange; }
8056 /// Source range of the loop condition.
8057 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
8058 /// Source range of the loop increment.
8059 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
8060 /// True if the step should be subtracted.
8061 bool shouldSubtractStep() const { return SubtractStep; }
8062 /// True, if the compare operator is strict (<, > or !=).
8063 bool isStrictTestOp() const { return TestIsStrictOp; }
8064 /// Build the expression to calculate the number of iterations.
8065 Expr *buildNumIterations(
8066 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8067 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8068 /// Build the precondition expression for the loops.
8069 Expr *
8070 buildPreCond(Scope *S, Expr *Cond,
8071 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8072 /// Build reference expression to the counter be used for codegen.
8073 DeclRefExpr *
8074 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8075 DSAStackTy &DSA) const;
8076 /// Build reference expression to the private counter be used for
8077 /// codegen.
8078 Expr *buildPrivateCounterVar() const;
8079 /// Build initialization of the counter be used for codegen.
8080 Expr *buildCounterInit() const;
8081 /// Build step of the counter be used for codegen.
8082 Expr *buildCounterStep() const;
8083 /// Build loop data with counter value for depend clauses in ordered
8084 /// directives.
8085 Expr *
8086 buildOrderedLoopData(Scope *S, Expr *Counter,
8087 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8088 SourceLocation Loc, Expr *Inc = nullptr,
8089 OverloadedOperatorKind OOK = OO_Amp);
8090 /// Builds the minimum value for the loop counter.
8091 std::pair<Expr *, Expr *> buildMinMaxValues(
8092 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8093 /// Builds final condition for the non-rectangular loops.
8094 Expr *buildFinalCondition(Scope *S) const;
8095 /// Return true if any expression is dependent.
8096 bool dependent() const;
8097 /// Returns true if the initializer forms non-rectangular loop.
8098 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
8099 /// Returns true if the condition forms non-rectangular loop.
8100 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
8101 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
8102 unsigned getLoopDependentIdx() const {
8103 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
8104 }
8105
8106private:
8107 /// Check the right-hand side of an assignment in the increment
8108 /// expression.
8109 bool checkAndSetIncRHS(Expr *RHS);
8110 /// Helper to set loop counter variable and its initializer.
8111 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8112 bool EmitDiags);
8113 /// Helper to set upper bound.
8114 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
8115 SourceRange SR, SourceLocation SL);
8116 /// Helper to set loop increment.
8117 bool setStep(Expr *NewStep, bool Subtract);
8118};
8119
8120bool OpenMPIterationSpaceChecker::dependent() const {
8121 if (!LCDecl) {
8122 assert(!LB && !UB && !Step);
8123 return false;
8124 }
8125 return LCDecl->getType()->isDependentType() ||
8126 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
8127 (Step && Step->isValueDependent());
8128}
8129
8130bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
8131 Expr *NewLCRefExpr,
8132 Expr *NewLB, bool EmitDiags) {
8133 // State consistency checking to ensure correct usage.
8134 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
8135 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8136 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
8137 return true;
8138 LCDecl = getCanonicalDecl(NewLCDecl);
8139 LCRef = NewLCRefExpr;
8140 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
8141 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8142 if ((Ctor->isCopyOrMoveConstructor() ||
8143 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8144 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8145 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
8146 LB = NewLB;
8147 if (EmitDiags)
8148 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
8149 return false;
8150}
8151
8152bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
8153 bool StrictOp, SourceRange SR,
8154 SourceLocation SL) {
8155 // State consistency checking to ensure correct usage.
8156 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
8157 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8158 if (!NewUB || NewUB->containsErrors())
8159 return true;
8160 UB = NewUB;
8161 if (LessOp)
8162 TestIsLessOp = LessOp;
8163 TestIsStrictOp = StrictOp;
8164 ConditionSrcRange = SR;
8165 ConditionLoc = SL;
8166 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
8167 return false;
8168}
8169
8170bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
8171 // State consistency checking to ensure correct usage.
8172 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
8173 if (!NewStep || NewStep->containsErrors())
8174 return true;
8175 if (!NewStep->isValueDependent()) {
8176 // Check that the step is integer expression.
8177 SourceLocation StepLoc = NewStep->getBeginLoc();
8179 StepLoc, getExprAsWritten(NewStep));
8180 if (Val.isInvalid())
8181 return true;
8182 NewStep = Val.get();
8183
8184 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8185 // If test-expr is of form var relational-op b and relational-op is < or
8186 // <= then incr-expr must cause var to increase on each iteration of the
8187 // loop. If test-expr is of form var relational-op b and relational-op is
8188 // > or >= then incr-expr must cause var to decrease on each iteration of
8189 // the loop.
8190 // If test-expr is of form b relational-op var and relational-op is < or
8191 // <= then incr-expr must cause var to decrease on each iteration of the
8192 // loop. If test-expr is of form b relational-op var and relational-op is
8193 // > or >= then incr-expr must cause var to increase on each iteration of
8194 // the loop.
8195 std::optional<llvm::APSInt> Result =
8196 NewStep->getIntegerConstantExpr(SemaRef.Context);
8197 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
8198 bool IsConstNeg =
8199 Result && Result->isSigned() && (Subtract != Result->isNegative());
8200 bool IsConstPos =
8201 Result && Result->isSigned() && (Subtract == Result->isNegative());
8202 bool IsConstZero = Result && !Result->getBoolValue();
8203
8204 // != with increment is treated as <; != with decrement is treated as >
8205 if (!TestIsLessOp)
8206 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8207 if (UB && (IsConstZero ||
8208 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8209 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8210 SemaRef.Diag(NewStep->getExprLoc(),
8211 diag::err_omp_loop_incr_not_compatible)
8212 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
8213 SemaRef.Diag(ConditionLoc,
8214 diag::note_omp_loop_cond_requires_compatible_incr)
8215 << *TestIsLessOp << ConditionSrcRange;
8216 return true;
8217 }
8218 if (*TestIsLessOp == Subtract) {
8219 NewStep =
8220 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
8221 .get();
8222 Subtract = !Subtract;
8223 }
8224 }
8225
8226 Step = NewStep;
8227 SubtractStep = Subtract;
8228 return false;
8229}
8230
8231namespace {
8232/// Checker for the non-rectangular loops. Checks if the initializer or
8233/// condition expression references loop counter variable.
8234class LoopCounterRefChecker final
8235 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8236 Sema &SemaRef;
8237 DSAStackTy &Stack;
8238 const ValueDecl *CurLCDecl = nullptr;
8239 const ValueDecl *DepDecl = nullptr;
8240 const ValueDecl *PrevDepDecl = nullptr;
8241 bool IsInitializer = true;
8242 bool SupportsNonRectangular;
8243 unsigned BaseLoopId = 0;
8244 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8245 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
8246 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8247 << (IsInitializer ? 0 : 1);
8248 return false;
8249 }
8250 const auto &&Data = Stack.isLoopControlVariable(VD);
8251 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8252 // The type of the loop iterator on which we depend may not have a random
8253 // access iterator type.
8254 if (Data.first && VD->getType()->isRecordType()) {
8255 SmallString<128> Name;
8256 llvm::raw_svector_ostream OS(Name);
8257 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8258 /*Qualified=*/true);
8259 SemaRef.Diag(E->getExprLoc(),
8260 diag::err_omp_wrong_dependency_iterator_type)
8261 << OS.str();
8262 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8263 return false;
8264 }
8265 if (Data.first && !SupportsNonRectangular) {
8266 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8267 return false;
8268 }
8269 if (Data.first &&
8270 (DepDecl || (PrevDepDecl &&
8271 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8272 if (!DepDecl && PrevDepDecl)
8273 DepDecl = PrevDepDecl;
8274 SmallString<128> Name;
8275 llvm::raw_svector_ostream OS(Name);
8276 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8277 /*Qualified=*/true);
8278 SemaRef.Diag(E->getExprLoc(),
8279 diag::err_omp_invariant_or_linear_dependency)
8280 << OS.str();
8281 return false;
8282 }
8283 if (Data.first) {
8284 DepDecl = VD;
8285 BaseLoopId = Data.first;
8286 }
8287 return Data.first;
8288 }
8289
8290public:
8291 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8292 const ValueDecl *VD = E->getDecl();
8293 if (isa<VarDecl>(VD))
8294 return checkDecl(E, VD);
8295 return false;
8296 }
8297 bool VisitMemberExpr(const MemberExpr *E) {
8298 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8299 const ValueDecl *VD = E->getMemberDecl();
8300 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8301 return checkDecl(E, VD);
8302 }
8303 return false;
8304 }
8305 bool VisitStmt(const Stmt *S) {
8306 bool Res = false;
8307 for (const Stmt *Child : S->children())
8308 Res = (Child && Visit(Child)) || Res;
8309 return Res;
8310 }
8311 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8312 const ValueDecl *CurLCDecl, bool IsInitializer,
8313 const ValueDecl *PrevDepDecl = nullptr,
8314 bool SupportsNonRectangular = true)
8315 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8316 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8317 SupportsNonRectangular(SupportsNonRectangular) {}
8318 unsigned getBaseLoopId() const {
8319 assert(CurLCDecl && "Expected loop dependency.");
8320 return BaseLoopId;
8321 }
8322 const ValueDecl *getDepDecl() const {
8323 assert(CurLCDecl && "Expected loop dependency.");
8324 return DepDecl;
8325 }
8326};
8327} // namespace
8328
8329std::optional<unsigned>
8330OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8331 bool IsInitializer) {
8332 // Check for the non-rectangular loops.
8333 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8334 DepDecl, SupportsNonRectangular);
8335 if (LoopStmtChecker.Visit(S)) {
8336 DepDecl = LoopStmtChecker.getDepDecl();
8337 return LoopStmtChecker.getBaseLoopId();
8338 }
8339 return std::nullopt;
8340}
8341
8342bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8343 // Check init-expr for canonical loop form and save loop counter
8344 // variable - #Var and its initialization value - #LB.
8345 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8346 // var = lb
8347 // integer-type var = lb
8348 // random-access-iterator-type var = lb
8349 // pointer-type var = lb
8350 //
8351 if (!S) {
8352 if (EmitDiags) {
8353 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8354 }
8355 return true;
8356 }
8357 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8358 if (!ExprTemp->cleanupsHaveSideEffects())
8359 S = ExprTemp->getSubExpr();
8360
8361 if (!CollapsedLoopVarDecls.empty()) {
8362 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8363 if (!FSEC.TraverseStmt(S)) {
8364 SourceRange Range = FSEC.getErrRange();
8365 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8366 << Range.getEnd() << 0 << FSEC.getForbiddenVar();
8367 return true;
8368 }
8369 }
8370
8371 InitSrcRange = S->getSourceRange();
8372 if (Expr *E = dyn_cast<Expr>(S))
8373 S = E->IgnoreParens();
8374 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8375 if (BO->getOpcode() == BO_Assign) {
8376 Expr *LHS = BO->getLHS()->IgnoreParens();
8377 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8378 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8379 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8380 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8381 EmitDiags);
8382 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8383 }
8384 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8385 if (ME->isArrow() &&
8386 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8387 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8388 EmitDiags);
8389 }
8390 }
8391 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8392 if (DS->isSingleDecl()) {
8393 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8394 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8395 // Accept non-canonical init form here but emit ext. warning.
8396 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8397 SemaRef.Diag(S->getBeginLoc(),
8398 diag::ext_omp_loop_not_canonical_init)
8399 << S->getSourceRange();
8400 return setLCDeclAndLB(
8401 Var,
8402 buildDeclRefExpr(SemaRef, Var,
8403 Var->getType().getNonReferenceType(),
8404 DS->getBeginLoc()),
8405 Var->getInit(), EmitDiags);
8406 }
8407 }
8408 }
8409 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8410 if (CE->getOperator() == OO_Equal) {
8411 Expr *LHS = CE->getArg(0);
8412 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8413 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8414 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8415 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8416 EmitDiags);
8417 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8418 }
8419 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8420 if (ME->isArrow() &&
8421 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8422 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8423 EmitDiags);
8424 }
8425 }
8426 }
8427
8428 if (dependent() || SemaRef.CurContext->isDependentContext())
8429 return false;
8430 if (EmitDiags) {
8431 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8432 << S->getSourceRange();
8433 }
8434 return true;
8435}
8436
8437/// Ignore parenthesizes, implicit casts, copy constructor and return the
8438/// variable (which may be the loop variable) if possible.
8439static const ValueDecl *getInitLCDecl(const Expr *E) {
8440 if (!E)
8441 return nullptr;
8442 E = getExprAsWritten(E);
8443 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8444 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8445 if ((Ctor->isCopyOrMoveConstructor() ||
8446 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8447 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8448 E = CE->getArg(0)->IgnoreParenImpCasts();
8449 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8450 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8451 return getCanonicalDecl(VD);
8452 }
8453 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8454 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8455 return getCanonicalDecl(ME->getMemberDecl());
8456 return nullptr;
8457}
8458
8459bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8460 // Check test-expr for canonical form, save upper-bound UB, flags for
8461 // less/greater and for strict/non-strict comparison.
8462 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8463 // var relational-op b
8464 // b relational-op var
8465 //
8466 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8467 if (!S) {
8468 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8469 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8470 return true;
8471 }
8472 Condition = S;
8473 S = getExprAsWritten(S);
8474
8475 if (!CollapsedLoopVarDecls.empty()) {
8476 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8477 if (!FSEC.TraverseStmt(S)) {
8478 SourceRange Range = FSEC.getErrRange();
8479 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8480 << Range.getEnd() << 1 << FSEC.getForbiddenVar();
8481 return true;
8482 }
8483 }
8484
8485 SourceLocation CondLoc = S->getBeginLoc();
8486 auto &&CheckAndSetCond =
8487 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8488 const Expr *RHS, SourceRange SR,
8489 SourceLocation OpLoc) -> std::optional<bool> {
8490 if (BinaryOperator::isRelationalOp(Opcode)) {
8491 if (getInitLCDecl(LHS) == LCDecl)
8492 return setUB(const_cast<Expr *>(RHS),
8493 (Opcode == BO_LT || Opcode == BO_LE),
8494 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8495 if (getInitLCDecl(RHS) == LCDecl)
8496 return setUB(const_cast<Expr *>(LHS),
8497 (Opcode == BO_GT || Opcode == BO_GE),
8498 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8499 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8500 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8501 /*LessOp=*/std::nullopt,
8502 /*StrictOp=*/true, SR, OpLoc);
8503 }
8504 return std::nullopt;
8505 };
8506 std::optional<bool> Res;
8507 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8508 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8509 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8510 RBO->getOperatorLoc());
8511 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8512 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8513 BO->getSourceRange(), BO->getOperatorLoc());
8514 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8515 if (CE->getNumArgs() == 2) {
8516 Res = CheckAndSetCond(
8517 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8518 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8519 }
8520 }
8521 if (Res)
8522 return *Res;
8523 if (dependent() || SemaRef.CurContext->isDependentContext())
8524 return false;
8525 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8526 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8527 return true;
8528}
8529
8530bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8531 // RHS of canonical loop form increment can be:
8532 // var + incr
8533 // incr + var
8534 // var - incr
8535 //
8536 RHS = RHS->IgnoreParenImpCasts();
8537 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8538 if (BO->isAdditiveOp()) {
8539 bool IsAdd = BO->getOpcode() == BO_Add;
8540 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8541 return setStep(BO->getRHS(), !IsAdd);
8542 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8543 return setStep(BO->getLHS(), /*Subtract=*/false);
8544 }
8545 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8546 bool IsAdd = CE->getOperator() == OO_Plus;
8547 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8548 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8549 return setStep(CE->getArg(1), !IsAdd);
8550 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8551 return setStep(CE->getArg(0), /*Subtract=*/false);
8552 }
8553 }
8554 if (dependent() || SemaRef.CurContext->isDependentContext())
8555 return false;
8556 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8557 << RHS->getSourceRange() << LCDecl;
8558 return true;
8559}
8560
8561bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8562 // Check incr-expr for canonical loop form and return true if it
8563 // does not conform.
8564 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8565 // ++var
8566 // var++
8567 // --var
8568 // var--
8569 // var += incr
8570 // var -= incr
8571 // var = var + incr
8572 // var = incr + var
8573 // var = var - incr
8574 //
8575 if (!S) {
8576 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8577 return true;
8578 }
8579 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8580 if (!ExprTemp->cleanupsHaveSideEffects())
8581 S = ExprTemp->getSubExpr();
8582
8583 if (!CollapsedLoopVarDecls.empty()) {
8584 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8585 if (!FSEC.TraverseStmt(S)) {
8586 SourceRange Range = FSEC.getErrRange();
8587 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8588 << Range.getEnd() << 2 << FSEC.getForbiddenVar();
8589 return true;
8590 }
8591 }
8592
8593 IncrementSrcRange = S->getSourceRange();
8594 S = S->IgnoreParens();
8595 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8596 if (UO->isIncrementDecrementOp() &&
8597 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8598 return setStep(SemaRef
8599 .ActOnIntegerConstant(UO->getBeginLoc(),
8600 (UO->isDecrementOp() ? -1 : 1))
8601 .get(),
8602 /*Subtract=*/false);
8603 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8604 switch (BO->getOpcode()) {
8605 case BO_AddAssign:
8606 case BO_SubAssign:
8607 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8608 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8609 break;
8610 case BO_Assign:
8611 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8612 return checkAndSetIncRHS(BO->getRHS());
8613 break;
8614 default:
8615 break;
8616 }
8617 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8618 switch (CE->getOperator()) {
8619 case OO_PlusPlus:
8620 case OO_MinusMinus:
8621 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8622 return setStep(SemaRef
8623 .ActOnIntegerConstant(
8624 CE->getBeginLoc(),
8625 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8626 .get(),
8627 /*Subtract=*/false);
8628 break;
8629 case OO_PlusEqual:
8630 case OO_MinusEqual:
8631 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8632 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8633 break;
8634 case OO_Equal:
8635 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8636 return checkAndSetIncRHS(CE->getArg(1));
8637 break;
8638 default:
8639 break;
8640 }
8641 }
8642 if (dependent() || SemaRef.CurContext->isDependentContext())
8643 return false;
8644 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8645 << S->getSourceRange() << LCDecl;
8646 return true;
8647}
8648
8649static ExprResult
8650tryBuildCapture(Sema &SemaRef, Expr *Capture,
8651 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8652 StringRef Name = ".capture_expr.") {
8653 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8654 return Capture;
8655 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8656 return SemaRef.PerformImplicitConversion(Capture->IgnoreImpCasts(),
8657 Capture->getType(),
8659 /*AllowExplicit=*/true);
8660 auto I = Captures.find(Capture);
8661 if (I != Captures.end())
8662 return buildCapture(SemaRef, Capture, I->second, Name);
8663 DeclRefExpr *Ref = nullptr;
8664 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8665 Captures[Capture] = Ref;
8666 return Res;
8667}
8668
8669/// Calculate number of iterations, transforming to unsigned, if number of
8670/// iterations may be larger than the original type.
8671static Expr *
8672calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8673 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8674 bool TestIsStrictOp, bool RoundToStep,
8675 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8676 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8677 if (!NewStep.isUsable())
8678 return nullptr;
8679 llvm::APSInt LRes, SRes;
8680 bool IsLowerConst = false, IsStepConst = false;
8681 if (std::optional<llvm::APSInt> Res =
8682 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8683 LRes = *Res;
8684 IsLowerConst = true;
8685 }
8686 if (std::optional<llvm::APSInt> Res =
8687 Step->getIntegerConstantExpr(SemaRef.Context)) {
8688 SRes = *Res;
8689 IsStepConst = true;
8690 }
8691 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8692 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8693 (TestIsStrictOp && LRes.isStrictlyPositive()));
8694 bool NeedToReorganize = false;
8695 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8696 if (!NoNeedToConvert && IsLowerConst &&
8697 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8698 NoNeedToConvert = true;
8699 if (RoundToStep) {
8700 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8701 ? LRes.getBitWidth()
8702 : SRes.getBitWidth();
8703 LRes = LRes.extend(BW + 1);
8704 LRes.setIsSigned(true);
8705 SRes = SRes.extend(BW + 1);
8706 SRes.setIsSigned(true);
8707 LRes -= SRes;
8708 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8709 LRes = LRes.trunc(BW);
8710 }
8711 if (TestIsStrictOp) {
8712 unsigned BW = LRes.getBitWidth();
8713 LRes = LRes.extend(BW + 1);
8714 LRes.setIsSigned(true);
8715 ++LRes;
8716 NoNeedToConvert =
8717 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8718 // truncate to the original bitwidth.
8719 LRes = LRes.trunc(BW);
8720 }
8721 NeedToReorganize = NoNeedToConvert;
8722 }
8723 llvm::APSInt URes;
8724 bool IsUpperConst = false;
8725 if (std::optional<llvm::APSInt> Res =
8726 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8727 URes = *Res;
8728 IsUpperConst = true;
8729 }
8730 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8731 (!RoundToStep || IsStepConst)) {
8732 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8733 : URes.getBitWidth();
8734 LRes = LRes.extend(BW + 1);
8735 LRes.setIsSigned(true);
8736 URes = URes.extend(BW + 1);
8737 URes.setIsSigned(true);
8738 URes -= LRes;
8739 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8740 NeedToReorganize = NoNeedToConvert;
8741 }
8742 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8743 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8744 // unsigned.
8745 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8746 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8747 QualType LowerTy = Lower->getType();
8748 QualType UpperTy = Upper->getType();
8749 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8750 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8751 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8752 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8754 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8755 Upper =
8756 SemaRef
8758 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8760 .get();
8761 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8762 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8763 }
8764 }
8765 if (!Lower || !Upper || NewStep.isInvalid())
8766 return nullptr;
8767
8768 ExprResult Diff;
8769 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8770 // 1]).
8771 if (NeedToReorganize) {
8772 Diff = Lower;
8773
8774 if (RoundToStep) {
8775 // Lower - Step
8776 Diff =
8777 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8778 if (!Diff.isUsable())
8779 return nullptr;
8780 }
8781
8782 // Lower - Step [+ 1]
8783 if (TestIsStrictOp)
8784 Diff = SemaRef.BuildBinOp(
8785 S, DefaultLoc, BO_Add, Diff.get(),
8786 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8787 if (!Diff.isUsable())
8788 return nullptr;
8789
8790 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8791 if (!Diff.isUsable())
8792 return nullptr;
8793
8794 // Upper - (Lower - Step [+ 1]).
8795 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8796 if (!Diff.isUsable())
8797 return nullptr;
8798 } else {
8799 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8800
8801 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8802 // BuildBinOp already emitted error, this one is to point user to upper
8803 // and lower bound, and to tell what is passed to 'operator-'.
8804 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8805 << Upper->getSourceRange() << Lower->getSourceRange();
8806 return nullptr;
8807 }
8808
8809 if (!Diff.isUsable())
8810 return nullptr;
8811
8812 // Upper - Lower [- 1]
8813 if (TestIsStrictOp)
8814 Diff = SemaRef.BuildBinOp(
8815 S, DefaultLoc, BO_Sub, Diff.get(),
8816 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8817 if (!Diff.isUsable())
8818 return nullptr;
8819
8820 if (RoundToStep) {
8821 // Upper - Lower [- 1] + Step
8822 Diff =
8823 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8824 if (!Diff.isUsable())
8825 return nullptr;
8826 }
8827 }
8828
8829 // Parentheses (for dumping/debugging purposes only).
8830 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8831 if (!Diff.isUsable())
8832 return nullptr;
8833
8834 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8835 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8836 if (!Diff.isUsable())
8837 return nullptr;
8838
8839 return Diff.get();
8840}
8841
8842/// Build the expression to calculate the number of iterations.
8843Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8844 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8845 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8846 QualType VarType = LCDecl->getType().getNonReferenceType();
8847 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8848 !SemaRef.getLangOpts().CPlusPlus)
8849 return nullptr;
8850 Expr *LBVal = LB;
8851 Expr *UBVal = UB;
8852 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8853 // max(LB(MinVal), LB(MaxVal)))
8854 if (InitDependOnLC) {
8855 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8856 if (!IS.MinValue || !IS.MaxValue)
8857 return nullptr;
8858 // OuterVar = Min
8859 ExprResult MinValue =
8860 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8861 if (!MinValue.isUsable())
8862 return nullptr;
8863
8864 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8865 IS.CounterVar, MinValue.get());
8866 if (!LBMinVal.isUsable())
8867 return nullptr;
8868 // OuterVar = Min, LBVal
8869 LBMinVal =
8870 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8871 if (!LBMinVal.isUsable())
8872 return nullptr;
8873 // (OuterVar = Min, LBVal)
8874 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8875 if (!LBMinVal.isUsable())
8876 return nullptr;
8877
8878 // OuterVar = Max
8879 ExprResult MaxValue =
8880 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8881 if (!MaxValue.isUsable())
8882 return nullptr;
8883
8884 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8885 IS.CounterVar, MaxValue.get());
8886 if (!LBMaxVal.isUsable())
8887 return nullptr;
8888 // OuterVar = Max, LBVal
8889 LBMaxVal =
8890 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8891 if (!LBMaxVal.isUsable())
8892 return nullptr;
8893 // (OuterVar = Max, LBVal)
8894 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8895 if (!LBMaxVal.isUsable())
8896 return nullptr;
8897
8898 Expr *LBMin =
8899 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
8900 Expr *LBMax =
8901 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
8902 if (!LBMin || !LBMax)
8903 return nullptr;
8904 // LB(MinVal) < LB(MaxVal)
8905 ExprResult MinLessMaxRes =
8906 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8907 if (!MinLessMaxRes.isUsable())
8908 return nullptr;
8909 Expr *MinLessMax =
8910 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
8911 .get();
8912 if (!MinLessMax)
8913 return nullptr;
8914 if (*TestIsLessOp) {
8915 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8916 // LB(MaxVal))
8917 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8918 MinLessMax, LBMin, LBMax);
8919 if (!MinLB.isUsable())
8920 return nullptr;
8921 LBVal = MinLB.get();
8922 } else {
8923 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8924 // LB(MaxVal))
8925 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8926 MinLessMax, LBMax, LBMin);
8927 if (!MaxLB.isUsable())
8928 return nullptr;
8929 LBVal = MaxLB.get();
8930 }
8931 // OuterVar = LB
8932 LBMinVal =
8933 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8934 if (!LBMinVal.isUsable())
8935 return nullptr;
8936 LBVal = LBMinVal.get();
8937 }
8938 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8939 // min(UB(MinVal), UB(MaxVal))
8940 if (CondDependOnLC) {
8941 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8942 if (!IS.MinValue || !IS.MaxValue)
8943 return nullptr;
8944 // OuterVar = Min
8945 ExprResult MinValue =
8946 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8947 if (!MinValue.isUsable())
8948 return nullptr;
8949
8950 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8951 IS.CounterVar, MinValue.get());
8952 if (!UBMinVal.isUsable())
8953 return nullptr;
8954 // OuterVar = Min, UBVal
8955 UBMinVal =
8956 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
8957 if (!UBMinVal.isUsable())
8958 return nullptr;
8959 // (OuterVar = Min, UBVal)
8960 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
8961 if (!UBMinVal.isUsable())
8962 return nullptr;
8963
8964 // OuterVar = Max
8965 ExprResult MaxValue =
8966 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8967 if (!MaxValue.isUsable())
8968 return nullptr;
8969
8970 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8971 IS.CounterVar, MaxValue.get());
8972 if (!UBMaxVal.isUsable())
8973 return nullptr;
8974 // OuterVar = Max, UBVal
8975 UBMaxVal =
8976 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
8977 if (!UBMaxVal.isUsable())
8978 return nullptr;
8979 // (OuterVar = Max, UBVal)
8980 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
8981 if (!UBMaxVal.isUsable())
8982 return nullptr;
8983
8984 Expr *UBMin =
8985 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
8986 Expr *UBMax =
8987 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
8988 if (!UBMin || !UBMax)
8989 return nullptr;
8990 // UB(MinVal) > UB(MaxVal)
8991 ExprResult MinGreaterMaxRes =
8992 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8993 if (!MinGreaterMaxRes.isUsable())
8994 return nullptr;
8995 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
8996 Captures, ".min_greater_max")
8997 .get();
8998 if (!MinGreaterMax)
8999 return nullptr;
9000 if (*TestIsLessOp) {
9001 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
9002 // UB(MaxVal))
9003 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
9004 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
9005 if (!MaxUB.isUsable())
9006 return nullptr;
9007 UBVal = MaxUB.get();
9008 } else {
9009 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
9010 // UB(MaxVal))
9011 ExprResult MinUB = SemaRef.ActOnConditionalOp(
9012 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
9013 if (!MinUB.isUsable())
9014 return nullptr;
9015 UBVal = MinUB.get();
9016 }
9017 }
9018 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9019 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9020 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
9021 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
9022 if (!Upper || !Lower)
9023 return nullptr;
9024
9025 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9026 Step, VarType, TestIsStrictOp,
9027 /*RoundToStep=*/true, Captures);
9028 if (!Diff.isUsable())
9029 return nullptr;
9030
9031 // OpenMP runtime requires 32-bit or 64-bit loop variables.
9032 QualType Type = Diff.get()->getType();
9033 ASTContext &C = SemaRef.Context;
9034 bool UseVarType = VarType->hasIntegerRepresentation() &&
9035 C.getTypeSize(Type) > C.getTypeSize(VarType);
9036 if (!Type->isIntegerType() || UseVarType) {
9037 unsigned NewSize =
9038 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
9039 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
9041 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
9042 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
9043 Diff = SemaRef.PerformImplicitConversion(Diff.get(), Type,
9045 /*AllowExplicit=*/true);
9046 if (!Diff.isUsable())
9047 return nullptr;
9048 }
9049 }
9050 if (LimitedType) {
9051 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
9052 if (NewSize != C.getTypeSize(Type)) {
9053 if (NewSize < C.getTypeSize(Type)) {
9054 assert(NewSize == 64 && "incorrect loop var size");
9055 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
9056 << InitSrcRange << ConditionSrcRange;
9057 }
9058 QualType NewType = C.getIntTypeForBitwidth(
9060 C.getTypeSize(Type) < NewSize);
9061 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
9062 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
9064 /*AllowExplicit=*/true);
9065 if (!Diff.isUsable())
9066 return nullptr;
9067 }
9068 }
9069 }
9070
9071 return Diff.get();
9072}
9073
9074std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9075 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9076 // Do not build for iterators, they cannot be used in non-rectangular loop
9077 // nests.
9078 if (LCDecl->getType()->isRecordType())
9079 return std::make_pair(nullptr, nullptr);
9080 // If we subtract, the min is in the condition, otherwise the min is in the
9081 // init value.
9082 Expr *MinExpr = nullptr;
9083 Expr *MaxExpr = nullptr;
9084 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9085 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9086 bool LBNonRect =
9087 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9088 bool UBNonRect =
9089 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9090 Expr *Lower =
9091 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
9092 Expr *Upper =
9093 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
9094 if (!Upper || !Lower)
9095 return std::make_pair(nullptr, nullptr);
9096
9097 if (*TestIsLessOp)
9098 MinExpr = Lower;
9099 else
9100 MaxExpr = Upper;
9101
9102 // Build minimum/maximum value based on number of iterations.
9103 QualType VarType = LCDecl->getType().getNonReferenceType();
9104
9105 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9106 Step, VarType, TestIsStrictOp,
9107 /*RoundToStep=*/false, Captures);
9108 if (!Diff.isUsable())
9109 return std::make_pair(nullptr, nullptr);
9110
9111 // ((Upper - Lower [- 1]) / Step) * Step
9112 // Parentheses (for dumping/debugging purposes only).
9113 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9114 if (!Diff.isUsable())
9115 return std::make_pair(nullptr, nullptr);
9116
9117 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
9118 if (!NewStep.isUsable())
9119 return std::make_pair(nullptr, nullptr);
9120 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
9121 if (!Diff.isUsable())
9122 return std::make_pair(nullptr, nullptr);
9123
9124 // Parentheses (for dumping/debugging purposes only).
9125 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9126 if (!Diff.isUsable())
9127 return std::make_pair(nullptr, nullptr);
9128
9129 // Convert to the ptrdiff_t, if original type is pointer.
9130 if (VarType->isAnyPointerType() &&
9131 !SemaRef.Context.hasSameType(
9132 Diff.get()->getType(),
9134 Diff = SemaRef.PerformImplicitConversion(
9135 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
9136 AssignmentAction::Converting, /*AllowExplicit=*/true);
9137 }
9138 if (!Diff.isUsable())
9139 return std::make_pair(nullptr, nullptr);
9140
9141 if (*TestIsLessOp) {
9142 // MinExpr = Lower;
9143 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
9144 Diff = SemaRef.BuildBinOp(
9145 S, DefaultLoc, BO_Add,
9146 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
9147 Diff.get());
9148 if (!Diff.isUsable())
9149 return std::make_pair(nullptr, nullptr);
9150 } else {
9151 // MaxExpr = Upper;
9152 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
9153 Diff = SemaRef.BuildBinOp(
9154 S, DefaultLoc, BO_Sub,
9155 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
9156 Diff.get());
9157 if (!Diff.isUsable())
9158 return std::make_pair(nullptr, nullptr);
9159 }
9160
9161 // Convert to the original type.
9162 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
9163 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
9165 /*AllowExplicit=*/true);
9166 if (!Diff.isUsable())
9167 return std::make_pair(nullptr, nullptr);
9168
9169 Sema::TentativeAnalysisScope Trap(SemaRef);
9170 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
9171 if (!Diff.isUsable())
9172 return std::make_pair(nullptr, nullptr);
9173
9174 if (*TestIsLessOp)
9175 MaxExpr = Diff.get();
9176 else
9177 MinExpr = Diff.get();
9178
9179 return std::make_pair(MinExpr, MaxExpr);
9180}
9181
9182Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
9183 if (InitDependOnLC || CondDependOnLC)
9184 return Condition;
9185 return nullptr;
9186}
9187
9188Expr *OpenMPIterationSpaceChecker::buildPreCond(
9189 Scope *S, Expr *Cond,
9190 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9191 // Do not build a precondition when the condition/initialization is dependent
9192 // to prevent pessimistic early loop exit.
9193 // TODO: this can be improved by calculating min/max values but not sure that
9194 // it will be very effective.
9195 if (CondDependOnLC || InitDependOnLC)
9196 return SemaRef
9198 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
9199 SemaRef.Context.BoolTy, /*Action=*/AssignmentAction::Casting,
9200 /*AllowExplicit=*/true)
9201 .get();
9202
9203 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
9204 Sema::TentativeAnalysisScope Trap(SemaRef);
9205
9206 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9207 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9208 if (!NewLB.isUsable() || !NewUB.isUsable())
9209 return nullptr;
9210
9211 ExprResult CondExpr =
9212 SemaRef.BuildBinOp(S, DefaultLoc,
9213 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9214 : (TestIsStrictOp ? BO_GT : BO_GE),
9215 NewLB.get(), NewUB.get());
9216 if (CondExpr.isUsable()) {
9217 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
9218 SemaRef.Context.BoolTy))
9219 CondExpr = SemaRef.PerformImplicitConversion(
9220 CondExpr.get(), SemaRef.Context.BoolTy,
9221 /*Action=*/AssignmentAction::Casting,
9222 /*AllowExplicit=*/true);
9223 }
9224
9225 // Otherwise use original loop condition and evaluate it in runtime.
9226 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9227}
9228
9229/// Build reference expression to the counter be used for codegen.
9230DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9231 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9232 DSAStackTy &DSA) const {
9233 auto *VD = dyn_cast<VarDecl>(LCDecl);
9234 if (!VD) {
9235 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(LCDecl);
9237 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
9238 const DSAStackTy::DSAVarData Data =
9239 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
9240 // If the loop control decl is explicitly marked as private, do not mark it
9241 // as captured again.
9242 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
9243 Captures.insert(std::make_pair(LCRef, Ref));
9244 return Ref;
9245 }
9246 return cast<DeclRefExpr>(LCRef);
9247}
9248
9249Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9250 if (LCDecl && !LCDecl->isInvalidDecl()) {
9252 VarDecl *PrivateVar = buildVarDecl(
9253 SemaRef, DefaultLoc, Type, LCDecl->getName(),
9254 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9255 isa<VarDecl>(LCDecl)
9256 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
9257 : nullptr);
9258 if (PrivateVar->isInvalidDecl())
9259 return nullptr;
9260 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
9261 }
9262 return nullptr;
9263}
9264
9265/// Build initialization of the counter to be used for codegen.
9266Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9267
9268/// Build step of the counter be used for codegen.
9269Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9270
9271Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9272 Scope *S, Expr *Counter,
9273 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9274 Expr *Inc, OverloadedOperatorKind OOK) {
9275 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
9276 if (!Cnt)
9277 return nullptr;
9278 if (Inc) {
9279 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9280 "Expected only + or - operations for depend clauses.");
9281 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9282 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
9283 if (!Cnt)
9284 return nullptr;
9285 }
9286 QualType VarType = LCDecl->getType().getNonReferenceType();
9287 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9288 !SemaRef.getLangOpts().CPlusPlus)
9289 return nullptr;
9290 // Upper - Lower
9291 Expr *Upper =
9292 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9293 Expr *Lower =
9294 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9295 if (!Upper || !Lower)
9296 return nullptr;
9297
9298 ExprResult Diff = calculateNumIters(
9299 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9300 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9301 if (!Diff.isUsable())
9302 return nullptr;
9303
9304 return Diff.get();
9305}
9306} // namespace
9307
9309 Stmt *Init) {
9310 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9311 assert(Init && "Expected loop in canonical form.");
9312 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9313 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9314 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
9315 return;
9316
9317 DSAStack->loopStart();
9319 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9320 *DSAStack, ForLoc, EmptyDeclSet);
9321 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9322 if (ValueDecl *D = ISC.getLoopDecl()) {
9323 auto *VD = dyn_cast<VarDecl>(D);
9324 DeclRefExpr *PrivateRef = nullptr;
9325 if (!VD) {
9327 VD = Private;
9328 } else {
9329 PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(),
9330 /*WithInit=*/false);
9331 VD = cast<VarDecl>(PrivateRef->getDecl());
9332 }
9333 }
9334 DSAStack->addLoopControlVariable(D, VD);
9335 const Decl *LD = DSAStack->getPossiblyLoopCounter();
9336 if (LD != D->getCanonicalDecl()) {
9337 DSAStack->resetPossibleLoopCounter();
9338 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9339 SemaRef.MarkDeclarationsReferencedInExpr(buildDeclRefExpr(
9340 SemaRef, const_cast<VarDecl *>(Var),
9341 Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
9342 /*RefersToCapture=*/true));
9343 }
9344 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9345 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9346 // associated for-loop of a simd construct with just one associated
9347 // for-loop may be listed in a linear clause with a constant-linear-step
9348 // that is the increment of the associated for-loop. The loop iteration
9349 // variable(s) in the associated for-loop(s) of a for or parallel for
9350 // construct may be listed in a private or lastprivate clause.
9351 DSAStackTy::DSAVarData DVar =
9352 DSAStack->getTopDSA(D, /*FromParent=*/false);
9353 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9354 // is declared in the loop and it is predetermined as a private.
9355 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9356 OpenMPClauseKind PredeterminedCKind =
9358 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9359 : OMPC_private;
9360 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
9361 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9362 };
9363 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9364 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9365 (getLangOpts().OpenMP <= 45 ||
9366 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9368 IsOpenMPTaskloopDirective(DKind) ||
9370 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9371 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9372 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9373 unsigned OMPVersion = getLangOpts().OpenMP;
9374 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9375 << getOpenMPClauseNameForDiag(DVar.CKind)
9376 << getOpenMPDirectiveName(DKind, OMPVersion)
9377 << getOpenMPClauseNameForDiag(PredeterminedCKind);
9378 if (DVar.RefExpr == nullptr)
9379 DVar.CKind = PredeterminedCKind;
9380 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
9381 } else if (LoopDeclRefExpr) {
9382 // Make the loop iteration variable private (for worksharing
9383 // constructs), linear (for simd directives with the only one
9384 // associated loop) or lastprivate (for simd directives with several
9385 // collapsed or ordered loops).
9386 if (DVar.CKind == OMPC_unknown)
9387 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9388 }
9389 }
9390 }
9391 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9392}
9393
9394namespace {
9395// Utility for OpenMP doacross clause kind
9396class OMPDoacrossKind {
9397public:
9398 bool isSource(const OMPDoacrossClause *C) {
9399 return C->getDependenceType() == OMPC_DOACROSS_source ||
9400 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9401 }
9402 bool isSink(const OMPDoacrossClause *C) {
9403 return C->getDependenceType() == OMPC_DOACROSS_sink;
9404 }
9405 bool isSinkIter(const OMPDoacrossClause *C) {
9406 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9407 }
9408};
9409} // namespace
9410/// Called on a for stmt to check and extract its iteration space
9411/// for further processing (such as collapsing).
9413 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9414 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9415 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9416 Expr *OrderedLoopCountExpr,
9417 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9419 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9420 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9421 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9422 // OpenMP [2.9.1, Canonical Loop Form]
9423 // for (init-expr; test-expr; incr-expr) structured-block
9424 // for (range-decl: range-expr) structured-block
9425 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9426 S = CanonLoop->getLoopStmt();
9427 auto *For = dyn_cast_or_null<ForStmt>(S);
9428 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9429 // Ranged for is supported only in OpenMP 5.0.
9430 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9431 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
9432 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9433 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9434 << getOpenMPDirectiveName(DKind, OMPVersion) << TotalNestedLoopCount
9435 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9436 if (TotalNestedLoopCount > 1) {
9437 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9438 SemaRef.Diag(DSA.getConstructLoc(),
9439 diag::note_omp_collapse_ordered_expr)
9440 << 2 << CollapseLoopCountExpr->getSourceRange()
9441 << OrderedLoopCountExpr->getSourceRange();
9442 else if (CollapseLoopCountExpr)
9443 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9444 diag::note_omp_collapse_ordered_expr)
9445 << 0 << CollapseLoopCountExpr->getSourceRange();
9446 else if (OrderedLoopCountExpr)
9447 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9448 diag::note_omp_collapse_ordered_expr)
9449 << 1 << OrderedLoopCountExpr->getSourceRange();
9450 }
9451 return true;
9452 }
9453 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9454 "No loop body.");
9455 // Postpone analysis in dependent contexts for ranged for loops.
9456 if (CXXFor && SemaRef.CurContext->isDependentContext())
9457 return false;
9458
9459 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9460 For ? For->getForLoc() : CXXFor->getForLoc(),
9461 CollapsedLoopVarDecls);
9462
9463 // Check init.
9464 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9465 if (ISC.checkAndSetInit(Init))
9466 return true;
9467
9468 bool HasErrors = false;
9469
9470 // Check loop variable's type.
9471 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9472 // OpenMP [2.6, Canonical Loop Form]
9473 // Var is one of the following:
9474 // A variable of signed or unsigned integer type.
9475 // For C++, a variable of a random access iterator type.
9476 // For C, a variable of a pointer type.
9477 QualType VarType = LCDecl->getType().getNonReferenceType();
9478 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9479 !VarType->isPointerType() &&
9480 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9481 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9482 << SemaRef.getLangOpts().CPlusPlus;
9483 HasErrors = true;
9484 }
9485
9486 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9487 // a Construct
9488 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9489 // parallel for construct is (are) private.
9490 // The loop iteration variable in the associated for-loop of a simd
9491 // construct with just one associated for-loop is linear with a
9492 // constant-linear-step that is the increment of the associated for-loop.
9493 // Exclude loop var from the list of variables with implicitly defined data
9494 // sharing attributes.
9495 VarsWithImplicitDSA.erase(LCDecl);
9496
9497 assert((isOpenMPLoopDirective(DKind) ||
9499 "DSA for non-loop vars");
9500
9501 // Check test-expr.
9502 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9503
9504 // Check incr-expr.
9505 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9506 }
9507
9508 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9509 return HasErrors;
9510
9511 // Build the loop's iteration space representation.
9512 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9513 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9514 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9515 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9521 Captures);
9522 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9523 ISC.buildCounterVar(Captures, DSA);
9524 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9525 ISC.buildPrivateCounterVar();
9526 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9527 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9528 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9529 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9530 ISC.getConditionSrcRange();
9531 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9532 ISC.getIncrementSrcRange();
9533 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9534 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9535 ISC.isStrictTestOp();
9536 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9537 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9538 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9539 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9540 ISC.buildFinalCondition(DSA.getCurScope());
9541 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9542 ISC.doesInitDependOnLC();
9543 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9544 ISC.doesCondDependOnLC();
9545 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9546 ISC.getLoopDependentIdx();
9547
9548 HasErrors |=
9549 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9550 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9551 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9552 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9553 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9554 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9555 if (!HasErrors && DSA.isOrderedRegion()) {
9556 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9557 if (CurrentNestedLoopCount <
9558 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9559 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9560 CurrentNestedLoopCount,
9561 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9562 DSA.getOrderedRegionParam().second->setLoopCounter(
9563 CurrentNestedLoopCount,
9564 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9565 }
9566 }
9567 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9568 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9569 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9570 unsigned NumLoops =
9571 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9572 if (CurrentNestedLoopCount >= NumLoops) {
9573 // Erroneous case - clause has some problems.
9574 continue;
9575 }
9576 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9577 Pair.second.size() <= CurrentNestedLoopCount) {
9578 // Erroneous case - clause has some problems.
9579 DependC->setLoopData(CurrentNestedLoopCount, nullptr);
9580 continue;
9581 }
9582 OMPDoacrossKind ODK;
9583 if (DoacrossC && ODK.isSink(DoacrossC) &&
9584 Pair.second.size() <= CurrentNestedLoopCount) {
9585 // Erroneous case - clause has some problems.
9586 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
9587 continue;
9588 }
9589 Expr *CntValue;
9590 SourceLocation DepLoc =
9591 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9592 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9593 (DoacrossC && ODK.isSource(DoacrossC)))
9594 CntValue = ISC.buildOrderedLoopData(
9595 DSA.getCurScope(),
9596 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9597 DepLoc);
9598 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9599 Expr *Cnt = SemaRef
9601 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9602 .get();
9603 if (!Cnt)
9604 continue;
9605 // build CounterVar - 1
9606 Expr *Inc =
9607 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
9608 .get();
9609 CntValue = ISC.buildOrderedLoopData(
9610 DSA.getCurScope(),
9611 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9612 DepLoc, Inc, clang::OO_Minus);
9613 } else
9614 CntValue = ISC.buildOrderedLoopData(
9615 DSA.getCurScope(),
9616 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9617 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9618 Pair.second[CurrentNestedLoopCount].second);
9619 if (DependC)
9620 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9621 else
9622 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9623 }
9624 }
9625
9626 return HasErrors;
9627}
9628
9629/// Build 'VarRef = Start.
9630static ExprResult
9632 ExprResult Start, bool IsNonRectangularLB,
9633 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9634 // Build 'VarRef = Start.
9635 ExprResult NewStart = IsNonRectangularLB
9636 ? Start.get()
9637 : tryBuildCapture(SemaRef, Start.get(), Captures);
9638 if (!NewStart.isUsable())
9639 return ExprError();
9640 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9641 VarRef.get()->getType())) {
9642 NewStart = SemaRef.PerformImplicitConversion(
9643 NewStart.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9644 /*AllowExplicit=*/true);
9645 if (!NewStart.isUsable())
9646 return ExprError();
9647 }
9648
9650 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9651 return Init;
9652}
9653
9654/// Build 'VarRef = Start + Iter * Step'.
9656 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9657 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9658 bool IsNonRectangularLB,
9659 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9660 // Add parentheses (for debugging purposes only).
9661 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9662 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9663 !Step.isUsable())
9664 return ExprError();
9665
9666 ExprResult NewStep = Step;
9667 if (Captures)
9668 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9669 if (NewStep.isInvalid())
9670 return ExprError();
9672 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9673 if (!Update.isUsable())
9674 return ExprError();
9675
9676 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9677 // 'VarRef = Start (+|-) Iter * Step'.
9678 if (!Start.isUsable())
9679 return ExprError();
9680 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9681 if (!NewStart.isUsable())
9682 return ExprError();
9683 if (Captures && !IsNonRectangularLB)
9684 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9685 if (NewStart.isInvalid())
9686 return ExprError();
9687
9688 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9689 ExprResult SavedUpdate = Update;
9690 ExprResult UpdateVal;
9691 if (VarRef.get()->getType()->isOverloadableType() ||
9692 NewStart.get()->getType()->isOverloadableType() ||
9693 Update.get()->getType()->isOverloadableType()) {
9694 Sema::TentativeAnalysisScope Trap(SemaRef);
9695
9696 Update =
9697 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9698 if (Update.isUsable()) {
9699 UpdateVal =
9700 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9701 VarRef.get(), SavedUpdate.get());
9702 if (UpdateVal.isUsable()) {
9703 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9704 UpdateVal.get());
9705 }
9706 }
9707 }
9708
9709 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9710 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9711 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9712 NewStart.get(), SavedUpdate.get());
9713 if (!Update.isUsable())
9714 return ExprError();
9715
9716 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9717 VarRef.get()->getType())) {
9719 Update.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9720 /*AllowExplicit=*/true);
9721 if (!Update.isUsable())
9722 return ExprError();
9723 }
9724
9725 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9726 }
9727 return Update;
9728}
9729
9730/// Convert integer expression \a E to make it have at least \a Bits
9731/// bits.
9732static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9733 if (E == nullptr)
9734 return ExprError();
9735 ASTContext &C = SemaRef.Context;
9736 QualType OldType = E->getType();
9737 unsigned HasBits = C.getTypeSize(OldType);
9738 if (HasBits >= Bits)
9739 return ExprResult(E);
9740 // OK to convert to signed, because new type has more bits than old.
9741 QualType NewType = C.getIntTypeForBitwidth(Bits, /*Signed=*/true);
9742 return SemaRef.PerformImplicitConversion(
9743 E, NewType, AssignmentAction::Converting, /*AllowExplicit=*/true);
9744}
9745
9746/// Check if the given expression \a E is a constant integer that fits
9747/// into \a Bits bits.
9748static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9749 if (E == nullptr)
9750 return false;
9751 if (std::optional<llvm::APSInt> Result =
9752 E->getIntegerConstantExpr(SemaRef.Context))
9753 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9754 return false;
9755}
9756
9757/// Build preinits statement for the given declarations.
9759 MutableArrayRef<Decl *> PreInits) {
9760 if (!PreInits.empty()) {
9761 return new (Context) DeclStmt(
9762 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9764 }
9765 return nullptr;
9766}
9767
9768/// Append the \p Item or the content of a CompoundStmt to the list \p
9769/// TargetList.
9770///
9771/// A CompoundStmt is used as container in case multiple statements need to be
9772/// stored in lieu of using an explicit list. Flattening is necessary because
9773/// contained DeclStmts need to be visible after the execution of the list. Used
9774/// for OpenMP pre-init declarations/statements.
9776 Stmt *Item) {
9777 // nullptr represents an empty list.
9778 if (!Item)
9779 return;
9780
9781 if (auto *CS = dyn_cast<CompoundStmt>(Item))
9782 llvm::append_range(TargetList, CS->body());
9783 else
9784 TargetList.push_back(Item);
9785}
9786
9787/// Build preinits statement for the given declarations.
9788static Stmt *
9790 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9791 if (!Captures.empty()) {
9792 SmallVector<Decl *, 16> PreInits;
9793 for (const auto &Pair : Captures)
9794 PreInits.push_back(Pair.second->getDecl());
9795 return buildPreInits(Context, PreInits);
9796 }
9797 return nullptr;
9798}
9799
9800/// Build pre-init statement for the given statements.
9801static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
9802 if (PreInits.empty())
9803 return nullptr;
9804
9805 SmallVector<Stmt *> Stmts;
9806 for (Stmt *S : PreInits)
9807 appendFlattenedStmtList(Stmts, S);
9808 return CompoundStmt::Create(Context, PreInits, FPOptionsOverride(), {}, {});
9809}
9810
9811/// Build postupdate expression for the given list of postupdates expressions.
9812static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9813 Expr *PostUpdate = nullptr;
9814 if (!PostUpdates.empty()) {
9815 for (Expr *E : PostUpdates) {
9816 Expr *ConvE = S.BuildCStyleCastExpr(
9817 E->getExprLoc(),
9819 E->getExprLoc(), E)
9820 .get();
9821 PostUpdate = PostUpdate
9822 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9823 PostUpdate, ConvE)
9824 .get()
9825 : ConvE;
9826 }
9827 }
9828 return PostUpdate;
9829}
9830
9831/// Look for variables declared in the body parts of a for-loop nest. Used
9832/// for verifying loop nest structure before performing a loop collapse
9833/// operation.
9835 int NestingDepth = 0;
9836 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9837
9838public:
9839 explicit ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl *> &VD)
9840 : VarDecls(VD) {}
9841
9842 bool VisitForStmt(ForStmt *F) override {
9843 ++NestingDepth;
9844 TraverseStmt(F->getBody());
9845 --NestingDepth;
9846 return false;
9847 }
9848
9850 ++NestingDepth;
9851 TraverseStmt(RF->getBody());
9852 --NestingDepth;
9853 return false;
9854 }
9855
9856 bool VisitVarDecl(VarDecl *D) override {
9857 Decl *C = D->getCanonicalDecl();
9858 if (NestingDepth > 0)
9859 VarDecls.insert(C);
9860 return true;
9861 }
9862};
9863
9864/// Called on a for stmt to check itself and nested loops (if any).
9865/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9866/// number of collapsed loops otherwise.
9867static unsigned
9868checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9869 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9870 DSAStackTy &DSA,
9871 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9872 OMPLoopBasedDirective::HelperExprs &Built) {
9873 // If either of the loop expressions exist and contain errors, we bail out
9874 // early because diagnostics have already been emitted and we can't reliably
9875 // check more about the loop.
9876 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->containsErrors()) ||
9877 (OrderedLoopCountExpr && OrderedLoopCountExpr->containsErrors()))
9878 return 0;
9879
9880 unsigned NestedLoopCount = 1;
9881 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9883 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopVarDecls;
9884
9885 if (CollapseLoopCountExpr) {
9886 // Found 'collapse' clause - calculate collapse number.
9887 Expr::EvalResult Result;
9888 if (!CollapseLoopCountExpr->isValueDependent() &&
9889 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9890 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9891
9892 ForVarDeclFinder FVDF{CollapsedLoopVarDecls};
9893 FVDF.TraverseStmt(AStmt);
9894 } else {
9895 Built.clear(/*Size=*/1);
9896 return 1;
9897 }
9898 }
9899 unsigned OrderedLoopCount = 1;
9900 if (OrderedLoopCountExpr) {
9901 // Found 'ordered' clause - calculate collapse number.
9902 Expr::EvalResult EVResult;
9903 if (!OrderedLoopCountExpr->isValueDependent() &&
9904 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9905 SemaRef.getASTContext())) {
9906 llvm::APSInt Result = EVResult.Val.getInt();
9907 if (Result.getLimitedValue() < NestedLoopCount) {
9908 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9909 diag::err_omp_wrong_ordered_loop_count)
9910 << OrderedLoopCountExpr->getSourceRange();
9911 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9912 diag::note_collapse_loop_count)
9913 << CollapseLoopCountExpr->getSourceRange();
9914 }
9915 OrderedLoopCount = Result.getLimitedValue();
9916 } else {
9917 Built.clear(/*Size=*/1);
9918 return 1;
9919 }
9920 }
9921 // This is helper routine for loop directives (e.g., 'for', 'simd',
9922 // 'for simd', etc.).
9923 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9924 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9925 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9926 if (!OMPLoopBasedDirective::doForAllLoops(
9927 AStmt->IgnoreContainers(
9929 SupportsNonPerfectlyNested, NumLoops,
9930 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9931 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9932 &IterSpaces, &Captures,
9933 &CollapsedLoopVarDecls](unsigned Cnt, Stmt *CurStmt) {
9935 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9936 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9937 VarsWithImplicitDSA, IterSpaces, Captures,
9938 CollapsedLoopVarDecls))
9939 return true;
9940 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9941 IterSpaces[Cnt].CounterVar) {
9942 // Handle initialization of captured loop iterator variables.
9943 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9944 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9945 Captures[DRE] = DRE;
9946 }
9947 }
9948 return false;
9949 },
9950 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9951 Stmt *DependentPreInits = Transform->getPreInits();
9952 if (!DependentPreInits)
9953 return;
9954
9955 // Search for pre-init declared variables that need to be captured
9956 // to be referenceable inside the directive.
9957 SmallVector<Stmt *> Constituents;
9958 appendFlattenedStmtList(Constituents, DependentPreInits);
9959 for (Stmt *S : Constituents) {
9960 if (auto *DC = dyn_cast<DeclStmt>(S)) {
9961 for (Decl *C : DC->decls()) {
9962 auto *D = cast<VarDecl>(C);
9964 SemaRef, D, D->getType().getNonReferenceType(),
9965 cast<OMPExecutableDirective>(Transform->getDirective())
9966 ->getBeginLoc());
9967 Captures[Ref] = Ref;
9968 }
9969 }
9970 }
9971 }))
9972 return 0;
9973
9974 Built.clear(/*size=*/NestedLoopCount);
9975
9976 if (SemaRef.CurContext->isDependentContext())
9977 return NestedLoopCount;
9978
9979 // An example of what is generated for the following code:
9980 //
9981 // #pragma omp simd collapse(2) ordered(2)
9982 // for (i = 0; i < NI; ++i)
9983 // for (k = 0; k < NK; ++k)
9984 // for (j = J0; j < NJ; j+=2) {
9985 // <loop body>
9986 // }
9987 //
9988 // We generate the code below.
9989 // Note: the loop body may be outlined in CodeGen.
9990 // Note: some counters may be C++ classes, operator- is used to find number of
9991 // iterations and operator+= to calculate counter value.
9992 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9993 // or i64 is currently supported).
9994 //
9995 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9996 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9997 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9998 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9999 // // similar updates for vars in clauses (e.g. 'linear')
10000 // <loop body (using local i and j)>
10001 // }
10002 // i = NI; // assign final values of counters
10003 // j = NJ;
10004 //
10005
10006 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
10007 // the iteration counts of the collapsed for loops.
10008 // Precondition tests if there is at least one iteration (all conditions are
10009 // true).
10010 auto PreCond = ExprResult(IterSpaces[0].PreCond);
10011 Expr *N0 = IterSpaces[0].NumIterations;
10012 ExprResult LastIteration32 = widenIterationCount(
10013 /*Bits=*/32,
10014 SemaRef
10015 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
10017 /*AllowExplicit=*/true)
10018 .get(),
10019 SemaRef);
10020 ExprResult LastIteration64 = widenIterationCount(
10021 /*Bits=*/64,
10022 SemaRef
10023 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
10025 /*AllowExplicit=*/true)
10026 .get(),
10027 SemaRef);
10028
10029 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
10030 return NestedLoopCount;
10031
10032 ASTContext &C = SemaRef.Context;
10033 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
10034
10035 Scope *CurScope = DSA.getCurScope();
10036 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
10037 if (PreCond.isUsable()) {
10038 PreCond =
10039 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
10040 PreCond.get(), IterSpaces[Cnt].PreCond);
10041 }
10042 Expr *N = IterSpaces[Cnt].NumIterations;
10043 SourceLocation Loc = N->getExprLoc();
10044 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
10045 if (LastIteration32.isUsable())
10046 LastIteration32 = SemaRef.BuildBinOp(
10047 CurScope, Loc, BO_Mul, LastIteration32.get(),
10048 SemaRef
10051 /*AllowExplicit=*/true)
10052 .get());
10053 if (LastIteration64.isUsable())
10054 LastIteration64 = SemaRef.BuildBinOp(
10055 CurScope, Loc, BO_Mul, LastIteration64.get(),
10056 SemaRef
10059 /*AllowExplicit=*/true)
10060 .get());
10061 }
10062
10063 // Choose either the 32-bit or 64-bit version.
10064 ExprResult LastIteration = LastIteration64;
10065 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
10066 (LastIteration32.isUsable() &&
10067 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
10068 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
10069 fitsInto(
10070 /*Bits=*/32,
10071 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
10072 LastIteration64.get(), SemaRef))))
10073 LastIteration = LastIteration32;
10074 QualType VType = LastIteration.get()->getType();
10075 QualType RealVType = VType;
10076 QualType StrideVType = VType;
10077 if (isOpenMPTaskLoopDirective(DKind)) {
10078 VType =
10079 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
10080 StrideVType =
10081 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
10082 }
10083
10084 if (!LastIteration.isUsable())
10085 return 0;
10086
10087 // Save the number of iterations.
10088 ExprResult NumIterations = LastIteration;
10089 {
10090 LastIteration = SemaRef.BuildBinOp(
10091 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
10092 LastIteration.get(),
10093 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
10094 if (!LastIteration.isUsable())
10095 return 0;
10096 }
10097
10098 // Calculate the last iteration number beforehand instead of doing this on
10099 // each iteration. Do not do this if the number of iterations may be kfold-ed.
10100 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
10101 ExprResult CalcLastIteration;
10102 if (!IsConstant) {
10103 ExprResult SaveRef =
10104 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
10105 LastIteration = SaveRef;
10106
10107 // Prepare SaveRef + 1.
10108 NumIterations = SemaRef.BuildBinOp(
10109 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
10110 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
10111 if (!NumIterations.isUsable())
10112 return 0;
10113 }
10114
10115 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
10116
10117 // Build variables passed into runtime, necessary for worksharing directives.
10118 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
10123 // Lower bound variable, initialized with zero.
10124 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
10125 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
10126 SemaRef.AddInitializerToDecl(LBDecl,
10127 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10128 /*DirectInit=*/false);
10129
10130 // Upper bound variable, initialized with last iteration number.
10131 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
10132 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
10133 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
10134 /*DirectInit=*/false);
10135
10136 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
10137 // This will be used to implement clause 'lastprivate'.
10138 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
10139 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
10140 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
10141 SemaRef.AddInitializerToDecl(ILDecl,
10142 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10143 /*DirectInit=*/false);
10144
10145 // Stride variable returned by runtime (we initialize it to 1 by default).
10146 VarDecl *STDecl =
10147 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
10148 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
10149 SemaRef.AddInitializerToDecl(STDecl,
10150 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
10151 /*DirectInit=*/false);
10152
10153 // Build expression: UB = min(UB, LastIteration)
10154 // It is necessary for CodeGen of directives with static scheduling.
10155 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
10156 UB.get(), LastIteration.get());
10157 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10158 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
10159 LastIteration.get(), UB.get());
10160 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
10161 CondOp.get());
10162 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue=*/false);
10163
10164 // If we have a combined directive that combines 'distribute', 'for' or
10165 // 'simd' we need to be able to access the bounds of the schedule of the
10166 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
10167 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
10169 // Lower bound variable, initialized with zero.
10170 VarDecl *CombLBDecl =
10171 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
10172 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
10173 SemaRef.AddInitializerToDecl(
10174 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10175 /*DirectInit=*/false);
10176
10177 // Upper bound variable, initialized with last iteration number.
10178 VarDecl *CombUBDecl =
10179 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
10180 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
10181 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
10182 /*DirectInit=*/false);
10183
10184 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
10185 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
10186 ExprResult CombCondOp =
10187 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
10188 LastIteration.get(), CombUB.get());
10189 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
10190 CombCondOp.get());
10191 CombEUB =
10192 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue=*/false);
10193
10194 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
10195 // We expect to have at least 2 more parameters than the 'parallel'
10196 // directive does - the lower and upper bounds of the previous schedule.
10197 assert(CD->getNumParams() >= 4 &&
10198 "Unexpected number of parameters in loop combined directive");
10199
10200 // Set the proper type for the bounds given what we learned from the
10201 // enclosed loops.
10202 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
10203 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
10204
10205 // Previous lower and upper bounds are obtained from the region
10206 // parameters.
10207 PrevLB =
10208 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
10209 PrevUB =
10210 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
10211 }
10212 }
10213
10214 // Build the iteration variable and its initialization before loop.
10215 ExprResult IV;
10216 ExprResult Init, CombInit;
10217 {
10218 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
10219 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
10220 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
10225 ? LB.get()
10226 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10227 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
10228 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue=*/false);
10229
10231 Expr *CombRHS =
10236 ? CombLB.get()
10237 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10238 CombInit =
10239 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
10240 CombInit =
10241 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue=*/false);
10242 }
10243 }
10244
10245 bool UseStrictCompare =
10246 RealVType->hasUnsignedIntegerRepresentation() &&
10247 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
10248 return LIS.IsStrictCompare;
10249 });
10250 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10251 // unsigned IV)) for worksharing loops.
10252 SourceLocation CondLoc = AStmt->getBeginLoc();
10253 Expr *BoundUB = UB.get();
10254 if (UseStrictCompare) {
10255 BoundUB =
10256 SemaRef
10257 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10258 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10259 .get();
10260 BoundUB =
10261 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue=*/false).get();
10262 }
10268 ? SemaRef.BuildBinOp(CurScope, CondLoc,
10269 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
10270 BoundUB)
10271 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10272 NumIterations.get());
10273 ExprResult CombDistCond;
10275 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10276 NumIterations.get());
10277 }
10278
10279 ExprResult CombCond;
10281 Expr *BoundCombUB = CombUB.get();
10282 if (UseStrictCompare) {
10283 BoundCombUB =
10284 SemaRef
10285 .BuildBinOp(
10286 CurScope, CondLoc, BO_Add, BoundCombUB,
10287 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10288 .get();
10289 BoundCombUB =
10290 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue=*/false)
10291 .get();
10292 }
10293 CombCond =
10294 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10295 IV.get(), BoundCombUB);
10296 }
10297 // Loop increment (IV = IV + 1)
10298 SourceLocation IncLoc = AStmt->getBeginLoc();
10299 ExprResult Inc =
10300 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
10301 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
10302 if (!Inc.isUsable())
10303 return 0;
10304 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
10305 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue=*/false);
10306 if (!Inc.isUsable())
10307 return 0;
10308
10309 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10310 // Used for directives with static scheduling.
10311 // In combined construct, add combined version that use CombLB and CombUB
10312 // base variables for the update
10313 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10318 // LB + ST
10319 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
10320 if (!NextLB.isUsable())
10321 return 0;
10322 // LB = LB + ST
10323 NextLB =
10324 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
10325 NextLB =
10326 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue=*/false);
10327 if (!NextLB.isUsable())
10328 return 0;
10329 // UB + ST
10330 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
10331 if (!NextUB.isUsable())
10332 return 0;
10333 // UB = UB + ST
10334 NextUB =
10335 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
10336 NextUB =
10337 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue=*/false);
10338 if (!NextUB.isUsable())
10339 return 0;
10341 CombNextLB =
10342 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
10343 if (!NextLB.isUsable())
10344 return 0;
10345 // LB = LB + ST
10346 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
10347 CombNextLB.get());
10348 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
10349 /*DiscardedValue=*/false);
10350 if (!CombNextLB.isUsable())
10351 return 0;
10352 // UB + ST
10353 CombNextUB =
10354 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
10355 if (!CombNextUB.isUsable())
10356 return 0;
10357 // UB = UB + ST
10358 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
10359 CombNextUB.get());
10360 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
10361 /*DiscardedValue=*/false);
10362 if (!CombNextUB.isUsable())
10363 return 0;
10364 }
10365 }
10366
10367 // Create increment expression for distribute loop when combined in a same
10368 // directive with for as IV = IV + ST; ensure upper bound expression based
10369 // on PrevUB instead of NumIterations - used to implement 'for' when found
10370 // in combination with 'distribute', like in 'distribute parallel for'
10371 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10372 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10374 DistCond = SemaRef.BuildBinOp(
10375 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10376 assert(DistCond.isUsable() && "distribute cond expr was not built");
10377
10378 DistInc =
10379 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10380 assert(DistInc.isUsable() && "distribute inc expr was not built");
10381 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10382 DistInc.get());
10383 DistInc =
10384 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue=*/false);
10385 assert(DistInc.isUsable() && "distribute inc expr was not built");
10386
10387 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10388 // construct
10389 ExprResult NewPrevUB = PrevUB;
10390 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10391 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10392 PrevUB.get()->getType())) {
10393 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10394 DistEUBLoc,
10396 DistEUBLoc, NewPrevUB.get());
10397 if (!NewPrevUB.isUsable())
10398 return 0;
10399 }
10400 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10401 UB.get(), NewPrevUB.get());
10402 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10403 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10404 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10405 CondOp.get());
10406 PrevEUB =
10407 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue=*/false);
10408
10409 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10410 // parallel for is in combination with a distribute directive with
10411 // schedule(static, 1)
10412 Expr *BoundPrevUB = PrevUB.get();
10413 if (UseStrictCompare) {
10414 BoundPrevUB =
10415 SemaRef
10416 .BuildBinOp(
10417 CurScope, CondLoc, BO_Add, BoundPrevUB,
10418 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10419 .get();
10420 BoundPrevUB =
10421 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue=*/false)
10422 .get();
10423 }
10424 ParForInDistCond =
10425 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10426 IV.get(), BoundPrevUB);
10427 }
10428
10429 // Build updates and final values of the loop counters.
10430 bool HasErrors = false;
10431 Built.Counters.resize(NestedLoopCount);
10432 Built.Inits.resize(NestedLoopCount);
10433 Built.Updates.resize(NestedLoopCount);
10434 Built.Finals.resize(NestedLoopCount);
10435 Built.DependentCounters.resize(NestedLoopCount);
10436 Built.DependentInits.resize(NestedLoopCount);
10437 Built.FinalsConditions.resize(NestedLoopCount);
10438 {
10439 // We implement the following algorithm for obtaining the
10440 // original loop iteration variable values based on the
10441 // value of the collapsed loop iteration variable IV.
10442 //
10443 // Let n+1 be the number of collapsed loops in the nest.
10444 // Iteration variables (I0, I1, .... In)
10445 // Iteration counts (N0, N1, ... Nn)
10446 //
10447 // Acc = IV;
10448 //
10449 // To compute Ik for loop k, 0 <= k <= n, generate:
10450 // Prod = N(k+1) * N(k+2) * ... * Nn;
10451 // Ik = Acc / Prod;
10452 // Acc -= Ik * Prod;
10453 //
10454 ExprResult Acc = IV;
10455 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10456 LoopIterationSpace &IS = IterSpaces[Cnt];
10457 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10458 ExprResult Iter;
10459
10460 // Compute prod
10461 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10462 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10463 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10464 IterSpaces[K].NumIterations);
10465
10466 // Iter = Acc / Prod
10467 // If there is at least one more inner loop to avoid
10468 // multiplication by 1.
10469 if (Cnt + 1 < NestedLoopCount)
10470 Iter =
10471 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10472 else
10473 Iter = Acc;
10474 if (!Iter.isUsable()) {
10475 HasErrors = true;
10476 break;
10477 }
10478
10479 // Update Acc:
10480 // Acc -= Iter * Prod
10481 // Check if there is at least one more inner loop to avoid
10482 // multiplication by 1.
10483 if (Cnt + 1 < NestedLoopCount)
10484 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10485 Prod.get());
10486 else
10487 Prod = Iter;
10488 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10489
10490 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10491 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10492 DeclRefExpr *CounterVar = buildDeclRefExpr(
10493 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10494 /*RefersToCapture=*/true);
10496 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10497 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10498 if (!Init.isUsable()) {
10499 HasErrors = true;
10500 break;
10501 }
10503 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10504 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10505 if (!Update.isUsable()) {
10506 HasErrors = true;
10507 break;
10508 }
10509
10510 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10511 ExprResult Final =
10512 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10513 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10514 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10515 if (!Final.isUsable()) {
10516 HasErrors = true;
10517 break;
10518 }
10519
10520 if (!Update.isUsable() || !Final.isUsable()) {
10521 HasErrors = true;
10522 break;
10523 }
10524 // Save results
10525 Built.Counters[Cnt] = IS.CounterVar;
10526 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10527 Built.Inits[Cnt] = Init.get();
10528 Built.Updates[Cnt] = Update.get();
10529 Built.Finals[Cnt] = Final.get();
10530 Built.DependentCounters[Cnt] = nullptr;
10531 Built.DependentInits[Cnt] = nullptr;
10532 Built.FinalsConditions[Cnt] = nullptr;
10533 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10534 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10535 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10536 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10537 }
10538 }
10539 }
10540
10541 if (HasErrors)
10542 return 0;
10543
10544 // Save results
10545 Built.IterationVarRef = IV.get();
10546 Built.LastIteration = LastIteration.get();
10547 Built.NumIterations = NumIterations.get();
10548 Built.CalcLastIteration = SemaRef
10549 .ActOnFinishFullExpr(CalcLastIteration.get(),
10550 /*DiscardedValue=*/false)
10551 .get();
10552 Built.PreCond = PreCond.get();
10553 Built.PreInits = buildPreInits(C, Captures);
10554 Built.Cond = Cond.get();
10555 Built.Init = Init.get();
10556 Built.Inc = Inc.get();
10557 Built.LB = LB.get();
10558 Built.UB = UB.get();
10559 Built.IL = IL.get();
10560 Built.ST = ST.get();
10561 Built.EUB = EUB.get();
10562 Built.NLB = NextLB.get();
10563 Built.NUB = NextUB.get();
10564 Built.PrevLB = PrevLB.get();
10565 Built.PrevUB = PrevUB.get();
10566 Built.DistInc = DistInc.get();
10567 Built.PrevEUB = PrevEUB.get();
10568 Built.DistCombinedFields.LB = CombLB.get();
10569 Built.DistCombinedFields.UB = CombUB.get();
10570 Built.DistCombinedFields.EUB = CombEUB.get();
10571 Built.DistCombinedFields.Init = CombInit.get();
10572 Built.DistCombinedFields.Cond = CombCond.get();
10573 Built.DistCombinedFields.NLB = CombNextLB.get();
10574 Built.DistCombinedFields.NUB = CombNextUB.get();
10575 Built.DistCombinedFields.DistCond = CombDistCond.get();
10576 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10577
10578 return NestedLoopCount;
10579}
10580
10582 auto CollapseClauses =
10583 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10584 if (CollapseClauses.begin() != CollapseClauses.end())
10585 return (*CollapseClauses.begin())->getNumForLoops();
10586 return nullptr;
10587}
10588
10590 auto OrderedClauses =
10591 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10592 if (OrderedClauses.begin() != OrderedClauses.end())
10593 return (*OrderedClauses.begin())->getNumForLoops();
10594 return nullptr;
10595}
10596
10598 const ArrayRef<OMPClause *> Clauses) {
10599 const OMPSafelenClause *Safelen = nullptr;
10600 const OMPSimdlenClause *Simdlen = nullptr;
10601
10602 for (const OMPClause *Clause : Clauses) {
10603 if (Clause->getClauseKind() == OMPC_safelen)
10604 Safelen = cast<OMPSafelenClause>(Clause);
10605 else if (Clause->getClauseKind() == OMPC_simdlen)
10606 Simdlen = cast<OMPSimdlenClause>(Clause);
10607 if (Safelen && Simdlen)
10608 break;
10609 }
10610
10611 if (Simdlen && Safelen) {
10612 const Expr *SimdlenLength = Simdlen->getSimdlen();
10613 const Expr *SafelenLength = Safelen->getSafelen();
10614 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10615 SimdlenLength->isInstantiationDependent() ||
10616 SimdlenLength->containsUnexpandedParameterPack())
10617 return false;
10618 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10619 SafelenLength->isInstantiationDependent() ||
10620 SafelenLength->containsUnexpandedParameterPack())
10621 return false;
10622 Expr::EvalResult SimdlenResult, SafelenResult;
10623 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10624 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10625 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10626 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10627 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10628 // If both simdlen and safelen clauses are specified, the value of the
10629 // simdlen parameter must be less than or equal to the value of the safelen
10630 // parameter.
10631 if (SimdlenRes > SafelenRes) {
10632 S.Diag(SimdlenLength->getExprLoc(),
10633 diag::err_omp_wrong_simdlen_safelen_values)
10634 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10635 return true;
10636 }
10637 }
10638 return false;
10639}
10640
10642 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10643 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10644 if (!AStmt)
10645 return StmtError();
10646
10647 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_simd, AStmt);
10648
10649 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10650 OMPLoopBasedDirective::HelperExprs B;
10651 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10652 // define the nested loops number.
10653 unsigned NestedLoopCount = checkOpenMPLoop(
10654 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10655 CS, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10656 if (NestedLoopCount == 0)
10657 return StmtError();
10658
10659 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10660 return StmtError();
10661
10663 return StmtError();
10664
10665 auto *SimdDirective = OMPSimdDirective::Create(
10666 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10667 return SimdDirective;
10668}
10669
10671 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10672 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10673 if (!AStmt)
10674 return StmtError();
10675
10676 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10677 OMPLoopBasedDirective::HelperExprs B;
10678 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10679 // define the nested loops number.
10680 unsigned NestedLoopCount = checkOpenMPLoop(
10681 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10682 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10683 if (NestedLoopCount == 0)
10684 return StmtError();
10685
10686 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10687 return StmtError();
10688
10689 auto *ForDirective = OMPForDirective::Create(
10690 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10691 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10692 return ForDirective;
10693}
10694
10696 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10697 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10698 if (!AStmt)
10699 return StmtError();
10700
10701 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_for_simd, AStmt);
10702
10703 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10704 OMPLoopBasedDirective::HelperExprs B;
10705 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10706 // define the nested loops number.
10707 unsigned NestedLoopCount =
10708 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10709 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10710 VarsWithImplicitDSA, B);
10711 if (NestedLoopCount == 0)
10712 return StmtError();
10713
10714 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10715 return StmtError();
10716
10718 return StmtError();
10719
10720 return OMPForSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
10721 NestedLoopCount, Clauses, AStmt, B);
10722}
10723
10725 Stmt *AStmt, DSAStackTy *Stack) {
10726 if (!AStmt)
10727 return true;
10728
10729 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10730 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
10731 auto BaseStmt = AStmt;
10732 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10733 BaseStmt = CS->getCapturedStmt();
10734 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10735 auto S = C->children();
10736 if (S.begin() == S.end())
10737 return true;
10738 // All associated statements must be '#pragma omp section' except for
10739 // the first one.
10740 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10741 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10742 if (SectionStmt)
10743 SemaRef.Diag(SectionStmt->getBeginLoc(),
10744 diag::err_omp_sections_substmt_not_section)
10745 << getOpenMPDirectiveName(DKind, OMPVersion);
10746 return true;
10747 }
10748 cast<OMPSectionDirective>(SectionStmt)
10749 ->setHasCancel(Stack->isCancelRegion());
10750 }
10751 } else {
10752 SemaRef.Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10753 << getOpenMPDirectiveName(DKind, OMPVersion);
10754 return true;
10755 }
10756 return false;
10757}
10758
10761 Stmt *AStmt, SourceLocation StartLoc,
10762 SourceLocation EndLoc) {
10763 if (checkSectionsDirective(SemaRef, OMPD_sections, AStmt, DSAStack))
10764 return StmtError();
10765
10766 SemaRef.setFunctionHasBranchProtectedScope();
10767
10768 return OMPSectionsDirective::Create(
10769 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10770 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10771}
10772
10774 SourceLocation StartLoc,
10775 SourceLocation EndLoc) {
10776 if (!AStmt)
10777 return StmtError();
10778
10779 SemaRef.setFunctionHasBranchProtectedScope();
10780 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10781
10782 return OMPSectionDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt,
10783 DSAStack->isCancelRegion());
10784}
10785
10787 E = E->IgnoreParenCasts()->IgnoreImplicit();
10788 if (auto *CE = dyn_cast<CallExpr>(E))
10789 if (CE->getDirectCallee())
10790 return E;
10791 return nullptr;
10792}
10793
10796 Stmt *AStmt, SourceLocation StartLoc,
10797 SourceLocation EndLoc) {
10798 if (!AStmt)
10799 return StmtError();
10800
10801 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10802
10803 // 5.1 OpenMP
10804 // expression-stmt : an expression statement with one of the following forms:
10805 // expression = target-call ( [expression-list] );
10806 // target-call ( [expression-list] );
10807
10808 SourceLocation TargetCallLoc;
10809
10810 if (!SemaRef.CurContext->isDependentContext()) {
10811 Expr *TargetCall = nullptr;
10812
10813 auto *E = dyn_cast<Expr>(S);
10814 if (!E) {
10815 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10816 return StmtError();
10817 }
10818
10819 E = E->IgnoreParenCasts()->IgnoreImplicit();
10820
10821 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10822 if (BO->getOpcode() == BO_Assign)
10823 TargetCall = getDirectCallExpr(BO->getRHS());
10824 } else {
10825 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10826 if (COCE->getOperator() == OO_Equal)
10827 TargetCall = getDirectCallExpr(COCE->getArg(1));
10828 if (!TargetCall)
10829 TargetCall = getDirectCallExpr(E);
10830 }
10831 if (!TargetCall) {
10832 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10833 return StmtError();
10834 }
10835 TargetCallLoc = TargetCall->getExprLoc();
10836 }
10837
10838 SemaRef.setFunctionHasBranchProtectedScope();
10839
10840 return OMPDispatchDirective::Create(getASTContext(), StartLoc, EndLoc,
10841 Clauses, AStmt, TargetCallLoc);
10842}
10843
10846 DSAStackTy *Stack) {
10847 bool ErrorFound = false;
10848 for (OMPClause *C : Clauses) {
10849 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10850 for (Expr *RefExpr : LPC->varlist()) {
10851 SourceLocation ELoc;
10852 SourceRange ERange;
10853 Expr *SimpleRefExpr = RefExpr;
10854 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10855 if (ValueDecl *D = Res.first) {
10856 auto &&Info = Stack->isLoopControlVariable(D);
10857 if (!Info.first) {
10858 unsigned OMPVersion = S.getLangOpts().OpenMP;
10859 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10860 << getOpenMPDirectiveName(K, OMPVersion);
10861 ErrorFound = true;
10862 }
10863 }
10864 }
10865 }
10866 }
10867 return ErrorFound;
10868}
10869
10871 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10872 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10873 if (!AStmt)
10874 return StmtError();
10875
10876 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10877 // A list item may not appear in a lastprivate clause unless it is the
10878 // loop iteration variable of a loop that is associated with the construct.
10879 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack))
10880 return StmtError();
10881
10882 setBranchProtectedScope(SemaRef, OMPD_loop, AStmt);
10883
10884 OMPLoopDirective::HelperExprs B;
10885 // In presence of clause 'collapse', it will define the nested loops number.
10886 unsigned NestedLoopCount = checkOpenMPLoop(
10887 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10888 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10889 if (NestedLoopCount == 0)
10890 return StmtError();
10891
10892 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10893 "omp loop exprs were not built");
10894
10895 return OMPGenericLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
10896 NestedLoopCount, Clauses, AStmt, B);
10897}
10898
10900 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10901 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10902 if (!AStmt)
10903 return StmtError();
10904
10905 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10906 // A list item may not appear in a lastprivate clause unless it is the
10907 // loop iteration variable of a loop that is associated with the construct.
10908 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack))
10909 return StmtError();
10910
10911 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_teams_loop, AStmt);
10912
10913 OMPLoopDirective::HelperExprs B;
10914 // In presence of clause 'collapse', it will define the nested loops number.
10915 unsigned NestedLoopCount =
10916 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10917 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10918 VarsWithImplicitDSA, B);
10919 if (NestedLoopCount == 0)
10920 return StmtError();
10921
10922 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10923 "omp loop exprs were not built");
10924
10925 DSAStack->setParentTeamsRegionLoc(StartLoc);
10926
10928 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10929}
10930
10932 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10933 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10934 if (!AStmt)
10935 return StmtError();
10936
10937 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10938 // A list item may not appear in a lastprivate clause unless it is the
10939 // loop iteration variable of a loop that is associated with the construct.
10940 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop,
10941 DSAStack))
10942 return StmtError();
10943
10944 CapturedStmt *CS =
10945 setBranchProtectedScope(SemaRef, OMPD_target_teams_loop, AStmt);
10946
10947 OMPLoopDirective::HelperExprs B;
10948 // In presence of clause 'collapse', it will define the nested loops number.
10949 unsigned NestedLoopCount =
10950 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10951 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10952 VarsWithImplicitDSA, B);
10953 if (NestedLoopCount == 0)
10954 return StmtError();
10955
10956 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10957 "omp loop exprs were not built");
10958
10960 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10962}
10963
10965 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10966 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10967 if (!AStmt)
10968 return StmtError();
10969
10970 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10971 // A list item may not appear in a lastprivate clause unless it is the
10972 // loop iteration variable of a loop that is associated with the construct.
10973 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_parallel_loop,
10974 DSAStack))
10975 return StmtError();
10976
10977 CapturedStmt *CS =
10978 setBranchProtectedScope(SemaRef, OMPD_parallel_loop, AStmt);
10979
10980 OMPLoopDirective::HelperExprs B;
10981 // In presence of clause 'collapse', it will define the nested loops number.
10982 unsigned NestedLoopCount =
10983 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
10984 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10985 VarsWithImplicitDSA, B);
10986 if (NestedLoopCount == 0)
10987 return StmtError();
10988
10989 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10990 "omp loop exprs were not built");
10991
10993 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10994}
10995
10997 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10998 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10999 if (!AStmt)
11000 return StmtError();
11001
11002 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11003 // A list item may not appear in a lastprivate clause unless it is the
11004 // loop iteration variable of a loop that is associated with the construct.
11005 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_parallel_loop,
11006 DSAStack))
11007 return StmtError();
11008
11009 CapturedStmt *CS =
11010 setBranchProtectedScope(SemaRef, OMPD_target_parallel_loop, AStmt);
11011
11012 OMPLoopDirective::HelperExprs B;
11013 // In presence of clause 'collapse', it will define the nested loops number.
11014 unsigned NestedLoopCount =
11015 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
11016 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
11017 VarsWithImplicitDSA, B);
11018 if (NestedLoopCount == 0)
11019 return StmtError();
11020
11021 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11022 "omp loop exprs were not built");
11023
11025 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11026}
11027
11029 Stmt *AStmt,
11030 SourceLocation StartLoc,
11031 SourceLocation EndLoc) {
11032 if (!AStmt)
11033 return StmtError();
11034
11035 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11036
11037 SemaRef.setFunctionHasBranchProtectedScope();
11038
11039 // OpenMP [2.7.3, single Construct, Restrictions]
11040 // The copyprivate clause must not be used with the nowait clause.
11041 const OMPClause *Nowait = nullptr;
11042 const OMPClause *Copyprivate = nullptr;
11043 for (const OMPClause *Clause : Clauses) {
11044 if (Clause->getClauseKind() == OMPC_nowait)
11045 Nowait = Clause;
11046 else if (Clause->getClauseKind() == OMPC_copyprivate)
11047 Copyprivate = Clause;
11048 if (Copyprivate && Nowait) {
11049 Diag(Copyprivate->getBeginLoc(),
11050 diag::err_omp_single_copyprivate_with_nowait);
11051 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
11052 return StmtError();
11053 }
11054 }
11055
11056 return OMPSingleDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11057 AStmt);
11058}
11059
11061 SourceLocation StartLoc,
11062 SourceLocation EndLoc) {
11063 if (!AStmt)
11064 return StmtError();
11065
11066 SemaRef.setFunctionHasBranchProtectedScope();
11067
11068 return OMPMasterDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt);
11069}
11070
11072 Stmt *AStmt,
11073 SourceLocation StartLoc,
11074 SourceLocation EndLoc) {
11075 if (!AStmt)
11076 return StmtError();
11077
11078 SemaRef.setFunctionHasBranchProtectedScope();
11079
11080 return OMPMaskedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11081 AStmt);
11082}
11083
11085 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
11086 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
11087 if (!AStmt)
11088 return StmtError();
11089
11090 bool ErrorFound = false;
11091 llvm::APSInt Hint;
11092 SourceLocation HintLoc;
11093 bool DependentHint = false;
11094 for (const OMPClause *C : Clauses) {
11095 if (C->getClauseKind() == OMPC_hint) {
11096 if (!DirName.getName()) {
11097 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
11098 ErrorFound = true;
11099 }
11100 Expr *E = cast<OMPHintClause>(C)->getHint();
11101 if (E->isTypeDependent() || E->isValueDependent() ||
11103 DependentHint = true;
11104 } else {
11106 HintLoc = C->getBeginLoc();
11107 }
11108 }
11109 }
11110 if (ErrorFound)
11111 return StmtError();
11112 const auto Pair = DSAStack->getCriticalWithHint(DirName);
11113 if (Pair.first && DirName.getName() && !DependentHint) {
11114 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
11115 Diag(StartLoc, diag::err_omp_critical_with_hint);
11116 if (HintLoc.isValid())
11117 Diag(HintLoc, diag::note_omp_critical_hint_here)
11118 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
11119 else
11120 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
11121 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
11122 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
11123 << 1
11124 << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()),
11125 /*Radix=*/10, /*Signed=*/false);
11126 } else {
11127 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
11128 }
11129 }
11130 }
11131
11132 SemaRef.setFunctionHasBranchProtectedScope();
11133
11134 auto *Dir = OMPCriticalDirective::Create(getASTContext(), DirName, StartLoc,
11135 EndLoc, Clauses, AStmt);
11136 if (!Pair.first && DirName.getName() && !DependentHint)
11137 DSAStack->addCriticalWithHint(Dir, Hint);
11138 return Dir;
11139}
11140
11142 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11143 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11144 if (!AStmt)
11145 return StmtError();
11146
11147 setBranchProtectedScope(SemaRef, OMPD_parallel_for, AStmt);
11148
11149 OMPLoopBasedDirective::HelperExprs B;
11150 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11151 // define the nested loops number.
11152 unsigned NestedLoopCount =
11153 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
11154 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
11155 VarsWithImplicitDSA, B);
11156 if (NestedLoopCount == 0)
11157 return StmtError();
11158
11159 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11160 return StmtError();
11161
11162 return OMPParallelForDirective::Create(
11163 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11164 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11165}
11166
11168 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11169 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11170 if (!AStmt)
11171 return StmtError();
11172
11173 CapturedStmt *CS =
11174 setBranchProtectedScope(SemaRef, OMPD_parallel_for_simd, AStmt);
11175
11176 OMPLoopBasedDirective::HelperExprs B;
11177 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11178 // define the nested loops number.
11179 unsigned NestedLoopCount =
11180 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
11181 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
11182 VarsWithImplicitDSA, B);
11183 if (NestedLoopCount == 0)
11184 return StmtError();
11185
11186 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11187 return StmtError();
11188
11190 return StmtError();
11191
11192 return OMPParallelForSimdDirective::Create(
11193 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11194}
11195
11197 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11198 SourceLocation EndLoc) {
11199 if (!AStmt)
11200 return StmtError();
11201
11202 setBranchProtectedScope(SemaRef, OMPD_parallel_master, AStmt);
11203
11204 return OMPParallelMasterDirective::Create(
11205 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11206 DSAStack->getTaskgroupReductionRef());
11207}
11208
11210 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11211 SourceLocation EndLoc) {
11212 if (!AStmt)
11213 return StmtError();
11214
11215 setBranchProtectedScope(SemaRef, OMPD_parallel_masked, AStmt);
11216
11217 return OMPParallelMaskedDirective::Create(
11218 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11219 DSAStack->getTaskgroupReductionRef());
11220}
11221
11223 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11224 SourceLocation EndLoc) {
11225 if (checkSectionsDirective(SemaRef, OMPD_parallel_sections, AStmt, DSAStack))
11226 return StmtError();
11227
11228 SemaRef.setFunctionHasBranchProtectedScope();
11229
11230 return OMPParallelSectionsDirective::Create(
11231 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11232 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11233}
11234
11235/// Find and diagnose mutually exclusive clause kinds.
11237 Sema &S, ArrayRef<OMPClause *> Clauses,
11238 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11239 const OMPClause *PrevClause = nullptr;
11240 bool ErrorFound = false;
11241 for (const OMPClause *C : Clauses) {
11242 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
11243 if (!PrevClause) {
11244 PrevClause = C;
11245 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11246 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11247 << getOpenMPClauseNameForDiag(C->getClauseKind())
11248 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11249 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
11250 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11251 ErrorFound = true;
11252 }
11253 }
11254 }
11255 return ErrorFound;
11256}
11257
11259 Stmt *AStmt,
11260 SourceLocation StartLoc,
11261 SourceLocation EndLoc) {
11262 if (!AStmt)
11263 return StmtError();
11264
11265 // OpenMP 5.0, 2.10.1 task Construct
11266 // If a detach clause appears on the directive, then a mergeable clause cannot
11267 // appear on the same directive.
11269 {OMPC_detach, OMPC_mergeable}))
11270 return StmtError();
11271
11272 setBranchProtectedScope(SemaRef, OMPD_task, AStmt);
11273
11274 return OMPTaskDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11275 AStmt, DSAStack->isCancelRegion());
11276}
11277
11279 SourceLocation EndLoc) {
11280 return OMPTaskyieldDirective::Create(getASTContext(), StartLoc, EndLoc);
11281}
11282
11284 SourceLocation EndLoc) {
11285 return OMPBarrierDirective::Create(getASTContext(), StartLoc, EndLoc);
11286}
11287
11289 SourceLocation StartLoc,
11290 SourceLocation EndLoc,
11291 bool InExContext) {
11292 const OMPAtClause *AtC =
11293 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11294
11295 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11296 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11297 return StmtError();
11298 }
11299
11300 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11301 const OMPSeverityClause *SeverityC =
11302 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11303 const OMPMessageClause *MessageC =
11304 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11305 std::optional<std::string> SL =
11306 MessageC ? MessageC->tryEvaluateString(getASTContext()) : std::nullopt;
11307
11308 if (MessageC && !SL)
11309 Diag(MessageC->getMessageString()->getBeginLoc(),
11310 diag::warn_clause_expected_string)
11311 << getOpenMPClauseNameForDiag(OMPC_message) << 1;
11312 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11313 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11314 << SL.value_or("WARNING");
11315 else
11316 Diag(StartLoc, diag::err_diagnose_if_succeeded) << SL.value_or("ERROR");
11317 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11318 return StmtError();
11319 }
11320
11321 return OMPErrorDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11322}
11323
11326 SourceLocation StartLoc,
11327 SourceLocation EndLoc) {
11328 const OMPNowaitClause *NowaitC =
11329 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11330 bool HasDependC =
11331 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11332 .empty();
11333 if (NowaitC && !HasDependC) {
11334 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11335 return StmtError();
11336 }
11337
11338 return OMPTaskwaitDirective::Create(getASTContext(), StartLoc, EndLoc,
11339 Clauses);
11340}
11341
11344 Stmt *AStmt, SourceLocation StartLoc,
11345 SourceLocation EndLoc) {
11346 if (!AStmt)
11347 return StmtError();
11348
11349 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11350
11351 SemaRef.setFunctionHasBranchProtectedScope();
11352
11353 return OMPTaskgroupDirective::Create(getASTContext(), StartLoc, EndLoc,
11354 Clauses, AStmt,
11355 DSAStack->getTaskgroupReductionRef());
11356}
11357
11359 SourceLocation StartLoc,
11360 SourceLocation EndLoc) {
11361 OMPFlushClause *FC = nullptr;
11362 OMPClause *OrderClause = nullptr;
11363 for (OMPClause *C : Clauses) {
11364 if (C->getClauseKind() == OMPC_flush)
11365 FC = cast<OMPFlushClause>(C);
11366 else
11367 OrderClause = C;
11368 }
11369 unsigned OMPVersion = getLangOpts().OpenMP;
11370 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11371 SourceLocation MemOrderLoc;
11372 for (const OMPClause *C : Clauses) {
11373 if (C->getClauseKind() == OMPC_acq_rel ||
11374 C->getClauseKind() == OMPC_acquire ||
11375 C->getClauseKind() == OMPC_release ||
11376 C->getClauseKind() == OMPC_seq_cst /*OpenMP 5.1*/) {
11377 if (MemOrderKind != OMPC_unknown) {
11378 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11379 << getOpenMPDirectiveName(OMPD_flush, OMPVersion) << 1
11380 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11381 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11382 << getOpenMPClauseNameForDiag(MemOrderKind);
11383 } else {
11384 MemOrderKind = C->getClauseKind();
11385 MemOrderLoc = C->getBeginLoc();
11386 }
11387 }
11388 }
11389 if (FC && OrderClause) {
11390 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11391 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11392 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11393 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11394 return StmtError();
11395 }
11396 return OMPFlushDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11397}
11398
11400 SourceLocation StartLoc,
11401 SourceLocation EndLoc) {
11402 if (Clauses.empty()) {
11403 Diag(StartLoc, diag::err_omp_depobj_expected);
11404 return StmtError();
11405 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11406 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11407 return StmtError();
11408 }
11409 // Only depobj expression and another single clause is allowed.
11410 if (Clauses.size() > 2) {
11411 Diag(Clauses[2]->getBeginLoc(),
11412 diag::err_omp_depobj_single_clause_expected);
11413 return StmtError();
11414 } else if (Clauses.size() < 1) {
11415 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11416 return StmtError();
11417 }
11418 return OMPDepobjDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11419}
11420
11422 SourceLocation StartLoc,
11423 SourceLocation EndLoc) {
11424 // Check that exactly one clause is specified.
11425 if (Clauses.size() != 1) {
11426 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11427 diag::err_omp_scan_single_clause_expected);
11428 return StmtError();
11429 }
11430 // Check that scan directive is used in the scope of the OpenMP loop body.
11431 if (Scope *S = DSAStack->getCurScope()) {
11432 Scope *ParentS = S->getParent();
11433 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11434 !ParentS->getBreakParent()->isOpenMPLoopScope()) {
11435 unsigned OMPVersion = getLangOpts().OpenMP;
11436 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11437 << getOpenMPDirectiveName(OMPD_scan, OMPVersion) << 5);
11438 }
11439 }
11440 // Check that only one instance of scan directives is used in the same outer
11441 // region.
11442 if (DSAStack->doesParentHasScanDirective()) {
11443 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11444 Diag(DSAStack->getParentScanDirectiveLoc(),
11445 diag::note_omp_previous_directive)
11446 << "scan";
11447 return StmtError();
11448 }
11449 DSAStack->setParentHasScanDirective(StartLoc);
11450 return OMPScanDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11451}
11452
11455 Stmt *AStmt, SourceLocation StartLoc,
11456 SourceLocation EndLoc) {
11457 const OMPClause *DependFound = nullptr;
11458 const OMPClause *DependSourceClause = nullptr;
11459 const OMPClause *DependSinkClause = nullptr;
11460 const OMPClause *DoacrossFound = nullptr;
11461 const OMPClause *DoacrossSourceClause = nullptr;
11462 const OMPClause *DoacrossSinkClause = nullptr;
11463 bool ErrorFound = false;
11464 const OMPThreadsClause *TC = nullptr;
11465 const OMPSIMDClause *SC = nullptr;
11466 for (const OMPClause *C : Clauses) {
11467 auto DOC = dyn_cast<OMPDoacrossClause>(C);
11468 auto DC = dyn_cast<OMPDependClause>(C);
11469 if (DC || DOC) {
11470 DependFound = DC ? C : nullptr;
11471 DoacrossFound = DOC ? C : nullptr;
11472 OMPDoacrossKind ODK;
11473 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11474 (DOC && (ODK.isSource(DOC)))) {
11475 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11476 unsigned OMPVersion = getLangOpts().OpenMP;
11477 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11478 << getOpenMPDirectiveName(OMPD_ordered, OMPVersion)
11479 << getOpenMPClauseNameForDiag(DC ? OMPC_depend : OMPC_doacross)
11480 << 2;
11481 ErrorFound = true;
11482 } else {
11483 if (DC)
11484 DependSourceClause = C;
11485 else
11486 DoacrossSourceClause = C;
11487 }
11488 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11489 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11490 << (DC ? "depend" : "doacross") << 0;
11491 ErrorFound = true;
11492 }
11493 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11494 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11495 if (DependSourceClause || DoacrossSourceClause) {
11496 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11497 << (DC ? "depend" : "doacross") << 1;
11498 ErrorFound = true;
11499 }
11500 if (DC)
11501 DependSinkClause = C;
11502 else
11503 DoacrossSinkClause = C;
11504 }
11505 } else if (C->getClauseKind() == OMPC_threads) {
11507 } else if (C->getClauseKind() == OMPC_simd) {
11508 SC = cast<OMPSIMDClause>(C);
11509 }
11510 }
11511 if (!ErrorFound && !SC &&
11512 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11513 // OpenMP [2.8.1,simd Construct, Restrictions]
11514 // An ordered construct with the simd clause is the only OpenMP construct
11515 // that can appear in the simd region.
11516 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11517 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11518 ErrorFound = true;
11519 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11520 SourceLocation Loc =
11521 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11522 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11523 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend : OMPC_doacross)
11525 : SC->getClauseKind());
11526 ErrorFound = true;
11527 } else if ((DependFound || DoacrossFound) &&
11528 !DSAStack->getParentOrderedRegionParam().first) {
11529 SourceLocation Loc =
11530 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11531 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11532 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend
11533 : OMPC_doacross);
11534 ErrorFound = true;
11535 } else if (TC || Clauses.empty()) {
11536 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11537 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11538 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11539 << (TC != nullptr);
11540 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11541 ErrorFound = true;
11542 }
11543 }
11544 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11545 return StmtError();
11546
11547 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11548 // During execution of an iteration of a worksharing-loop or a loop nest
11549 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11550 // must not execute more than one ordered region corresponding to an ordered
11551 // construct without a depend clause.
11552 if (!DependFound && !DoacrossFound) {
11553 if (DSAStack->doesParentHasOrderedDirective()) {
11554 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11555 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11556 diag::note_omp_previous_directive)
11557 << "ordered";
11558 return StmtError();
11559 }
11560 DSAStack->setParentHasOrderedDirective(StartLoc);
11561 }
11562
11563 if (AStmt) {
11564 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11565
11566 SemaRef.setFunctionHasBranchProtectedScope();
11567 }
11568
11569 return OMPOrderedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11570 AStmt);
11571}
11572
11573namespace {
11574/// Helper class for checking expression in 'omp atomic [update]'
11575/// construct.
11576class OpenMPAtomicUpdateChecker {
11577 /// Error results for atomic update expressions.
11578 enum ExprAnalysisErrorCode {
11579 /// A statement is not an expression statement.
11580 NotAnExpression,
11581 /// Expression is not builtin binary or unary operation.
11582 NotABinaryOrUnaryExpression,
11583 /// Unary operation is not post-/pre- increment/decrement operation.
11584 NotAnUnaryIncDecExpression,
11585 /// An expression is not of scalar type.
11586 NotAScalarType,
11587 /// A binary operation is not an assignment operation.
11588 NotAnAssignmentOp,
11589 /// RHS part of the binary operation is not a binary expression.
11590 NotABinaryExpression,
11591 /// RHS part is not additive/multiplicative/shift/bitwise binary
11592 /// expression.
11593 NotABinaryOperator,
11594 /// RHS binary operation does not have reference to the updated LHS
11595 /// part.
11596 NotAnUpdateExpression,
11597 /// An expression contains semantical error not related to
11598 /// 'omp atomic [update]'
11599 NotAValidExpression,
11600 /// No errors is found.
11601 NoError
11602 };
11603 /// Reference to Sema.
11604 Sema &SemaRef;
11605 /// A location for note diagnostics (when error is found).
11606 SourceLocation NoteLoc;
11607 /// 'x' lvalue part of the source atomic expression.
11608 Expr *X;
11609 /// 'expr' rvalue part of the source atomic expression.
11610 Expr *E;
11611 /// Helper expression of the form
11612 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11613 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11614 Expr *UpdateExpr;
11615 /// Is 'x' a LHS in a RHS part of full update expression. It is
11616 /// important for non-associative operations.
11617 bool IsXLHSInRHSPart;
11619 SourceLocation OpLoc;
11620 /// true if the source expression is a postfix unary operation, false
11621 /// if it is a prefix unary operation.
11622 bool IsPostfixUpdate;
11623
11624public:
11625 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11626 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11627 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11628 /// Check specified statement that it is suitable for 'atomic update'
11629 /// constructs and extract 'x', 'expr' and Operation from the original
11630 /// expression. If DiagId and NoteId == 0, then only check is performed
11631 /// without error notification.
11632 /// \param DiagId Diagnostic which should be emitted if error is found.
11633 /// \param NoteId Diagnostic note for the main error message.
11634 /// \return true if statement is not an update expression, false otherwise.
11635 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11636 /// Return the 'x' lvalue part of the source atomic expression.
11637 Expr *getX() const { return X; }
11638 /// Return the 'expr' rvalue part of the source atomic expression.
11639 Expr *getExpr() const { return E; }
11640 /// Return the update expression used in calculation of the updated
11641 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11642 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11643 Expr *getUpdateExpr() const { return UpdateExpr; }
11644 /// Return true if 'x' is LHS in RHS part of full update expression,
11645 /// false otherwise.
11646 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11647
11648 /// true if the source expression is a postfix unary operation, false
11649 /// if it is a prefix unary operation.
11650 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11651
11652private:
11653 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11654 unsigned NoteId = 0);
11655};
11656
11657bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11658 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11659 ExprAnalysisErrorCode ErrorFound = NoError;
11660 SourceLocation ErrorLoc, NoteLoc;
11661 SourceRange ErrorRange, NoteRange;
11662 // Allowed constructs are:
11663 // x = x binop expr;
11664 // x = expr binop x;
11665 if (AtomicBinOp->getOpcode() == BO_Assign) {
11666 X = AtomicBinOp->getLHS();
11667 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11668 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11669 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11670 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11671 AtomicInnerBinOp->isBitwiseOp()) {
11672 Op = AtomicInnerBinOp->getOpcode();
11673 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11674 Expr *LHS = AtomicInnerBinOp->getLHS();
11675 Expr *RHS = AtomicInnerBinOp->getRHS();
11676 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11677 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11678 /*Canonical=*/true);
11679 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11680 /*Canonical=*/true);
11681 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11682 /*Canonical=*/true);
11683 if (XId == LHSId) {
11684 E = RHS;
11685 IsXLHSInRHSPart = true;
11686 } else if (XId == RHSId) {
11687 E = LHS;
11688 IsXLHSInRHSPart = false;
11689 } else {
11690 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11691 ErrorRange = AtomicInnerBinOp->getSourceRange();
11692 NoteLoc = X->getExprLoc();
11693 NoteRange = X->getSourceRange();
11694 ErrorFound = NotAnUpdateExpression;
11695 }
11696 } else {
11697 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11698 ErrorRange = AtomicInnerBinOp->getSourceRange();
11699 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11700 NoteRange = SourceRange(NoteLoc, NoteLoc);
11701 ErrorFound = NotABinaryOperator;
11702 }
11703 } else {
11704 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11705 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11706 ErrorFound = NotABinaryExpression;
11707 }
11708 } else {
11709 ErrorLoc = AtomicBinOp->getExprLoc();
11710 ErrorRange = AtomicBinOp->getSourceRange();
11711 NoteLoc = AtomicBinOp->getOperatorLoc();
11712 NoteRange = SourceRange(NoteLoc, NoteLoc);
11713 ErrorFound = NotAnAssignmentOp;
11714 }
11715 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11716 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11717 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11718 return true;
11719 }
11720 if (SemaRef.CurContext->isDependentContext())
11721 E = X = UpdateExpr = nullptr;
11722 return ErrorFound != NoError;
11723}
11724
11725bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11726 unsigned NoteId) {
11727 ExprAnalysisErrorCode ErrorFound = NoError;
11728 SourceLocation ErrorLoc, NoteLoc;
11729 SourceRange ErrorRange, NoteRange;
11730 // Allowed constructs are:
11731 // x++;
11732 // x--;
11733 // ++x;
11734 // --x;
11735 // x binop= expr;
11736 // x = x binop expr;
11737 // x = expr binop x;
11738 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11739 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11740 if (AtomicBody->getType()->isScalarType() ||
11741 AtomicBody->isInstantiationDependent()) {
11742 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11743 AtomicBody->IgnoreParenImpCasts())) {
11744 // Check for Compound Assignment Operation
11746 AtomicCompAssignOp->getOpcode());
11747 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11748 E = AtomicCompAssignOp->getRHS();
11749 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11750 IsXLHSInRHSPart = true;
11751 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11752 AtomicBody->IgnoreParenImpCasts())) {
11753 // Check for Binary Operation
11754 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11755 return true;
11756 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11757 AtomicBody->IgnoreParenImpCasts())) {
11758 // Check for Unary Operation
11759 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11760 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11761 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11762 OpLoc = AtomicUnaryOp->getOperatorLoc();
11763 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11764 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11765 IsXLHSInRHSPart = true;
11766 } else {
11767 ErrorFound = NotAnUnaryIncDecExpression;
11768 ErrorLoc = AtomicUnaryOp->getExprLoc();
11769 ErrorRange = AtomicUnaryOp->getSourceRange();
11770 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11771 NoteRange = SourceRange(NoteLoc, NoteLoc);
11772 }
11773 } else if (!AtomicBody->isInstantiationDependent()) {
11774 ErrorFound = NotABinaryOrUnaryExpression;
11775 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11776 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11777 } else if (AtomicBody->containsErrors()) {
11778 ErrorFound = NotAValidExpression;
11779 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11780 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11781 }
11782 } else {
11783 ErrorFound = NotAScalarType;
11784 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11785 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11786 }
11787 } else {
11788 ErrorFound = NotAnExpression;
11789 NoteLoc = ErrorLoc = S->getBeginLoc();
11790 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11791 }
11792 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11793 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11794 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11795 return true;
11796 }
11797 if (SemaRef.CurContext->isDependentContext())
11798 E = X = UpdateExpr = nullptr;
11799 if (ErrorFound == NoError && E && X) {
11800 // Build an update expression of form 'OpaqueValueExpr(x) binop
11801 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11802 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11803 auto *OVEX = new (SemaRef.getASTContext())
11804 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11805 auto *OVEExpr = new (SemaRef.getASTContext())
11808 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11809 IsXLHSInRHSPart ? OVEExpr : OVEX);
11810 if (Update.isInvalid())
11811 return true;
11812 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11814 if (Update.isInvalid())
11815 return true;
11816 UpdateExpr = Update.get();
11817 }
11818 return ErrorFound != NoError;
11819}
11820
11821/// Get the node id of the fixed point of an expression \a S.
11822llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11823 llvm::FoldingSetNodeID Id;
11824 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11825 return Id;
11826}
11827
11828/// Check if two expressions are same.
11829bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11830 const Expr *RHS) {
11831 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11832}
11833
11834class OpenMPAtomicCompareChecker {
11835public:
11836 /// All kinds of errors that can occur in `atomic compare`
11837 enum ErrorTy {
11838 /// Empty compound statement.
11839 NoStmt = 0,
11840 /// More than one statement in a compound statement.
11841 MoreThanOneStmt,
11842 /// Not an assignment binary operator.
11843 NotAnAssignment,
11844 /// Not a conditional operator.
11845 NotCondOp,
11846 /// Wrong false expr. According to the spec, 'x' should be at the false
11847 /// expression of a conditional expression.
11848 WrongFalseExpr,
11849 /// The condition of a conditional expression is not a binary operator.
11850 NotABinaryOp,
11851 /// Invalid binary operator (not <, >, or ==).
11852 InvalidBinaryOp,
11853 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11854 InvalidComparison,
11855 /// X is not a lvalue.
11856 XNotLValue,
11857 /// Not a scalar.
11858 NotScalar,
11859 /// Not an integer.
11860 NotInteger,
11861 /// 'else' statement is not expected.
11862 UnexpectedElse,
11863 /// Not an equality operator.
11864 NotEQ,
11865 /// Invalid assignment (not v == x).
11866 InvalidAssignment,
11867 /// Not if statement
11868 NotIfStmt,
11869 /// More than two statements in a compound statement.
11870 MoreThanTwoStmts,
11871 /// Not a compound statement.
11872 NotCompoundStmt,
11873 /// No else statement.
11874 NoElse,
11875 /// Not 'if (r)'.
11876 InvalidCondition,
11877 /// No error.
11878 NoError,
11879 };
11880
11881 struct ErrorInfoTy {
11882 ErrorTy Error;
11883 SourceLocation ErrorLoc;
11884 SourceRange ErrorRange;
11885 SourceLocation NoteLoc;
11886 SourceRange NoteRange;
11887 };
11888
11889 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11890
11891 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11892 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11893
11894 Expr *getX() const { return X; }
11895 Expr *getE() const { return E; }
11896 Expr *getD() const { return D; }
11897 Expr *getCond() const { return C; }
11898 bool isXBinopExpr() const { return IsXBinopExpr; }
11899
11900protected:
11901 /// Reference to ASTContext
11902 ASTContext &ContextRef;
11903 /// 'x' lvalue part of the source atomic expression.
11904 Expr *X = nullptr;
11905 /// 'expr' or 'e' rvalue part of the source atomic expression.
11906 Expr *E = nullptr;
11907 /// 'd' rvalue part of the source atomic expression.
11908 Expr *D = nullptr;
11909 /// 'cond' part of the source atomic expression. It is in one of the following
11910 /// forms:
11911 /// expr ordop x
11912 /// x ordop expr
11913 /// x == e
11914 /// e == x
11915 Expr *C = nullptr;
11916 /// True if the cond expr is in the form of 'x ordop expr'.
11917 bool IsXBinopExpr = true;
11918
11919 /// Check if it is a valid conditional update statement (cond-update-stmt).
11920 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11921
11922 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11923 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11924
11925 /// Check if all captured values have right type.
11926 bool checkType(ErrorInfoTy &ErrorInfo) const;
11927
11928 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11929 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11930 if (E->isInstantiationDependent())
11931 return true;
11932
11933 if (ShouldBeLValue && !E->isLValue()) {
11934 ErrorInfo.Error = ErrorTy::XNotLValue;
11935 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11936 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11937 return false;
11938 }
11939
11940 QualType QTy = E->getType();
11941 if (!QTy->isScalarType()) {
11942 ErrorInfo.Error = ErrorTy::NotScalar;
11943 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11944 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11945 return false;
11946 }
11947 if (ShouldBeInteger && !QTy->isIntegerType()) {
11948 ErrorInfo.Error = ErrorTy::NotInteger;
11949 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11950 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11951 return false;
11952 }
11953
11954 return true;
11955 }
11956};
11957
11958bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11959 ErrorInfoTy &ErrorInfo) {
11960 auto *Then = S->getThen();
11961 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11962 if (CS->body_empty()) {
11963 ErrorInfo.Error = ErrorTy::NoStmt;
11964 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11965 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11966 return false;
11967 }
11968 if (CS->size() > 1) {
11969 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11970 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11971 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11972 return false;
11973 }
11974 Then = CS->body_front();
11975 }
11976
11977 auto *BO = dyn_cast<BinaryOperator>(Then);
11978 if (!BO) {
11979 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11980 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11981 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11982 return false;
11983 }
11984 if (BO->getOpcode() != BO_Assign) {
11985 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11986 ErrorInfo.ErrorLoc = BO->getExprLoc();
11987 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11988 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11989 return false;
11990 }
11991
11992 X = BO->getLHS();
11993
11994 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11995 auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
11996 Expr *LHS = nullptr;
11997 Expr *RHS = nullptr;
11998 if (Cond) {
11999 LHS = Cond->getLHS();
12000 RHS = Cond->getRHS();
12001 } else if (Call) {
12002 LHS = Call->getArg(0);
12003 RHS = Call->getArg(1);
12004 } else {
12005 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12006 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12007 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12008 return false;
12009 }
12010
12011 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12012 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12013 C = S->getCond();
12014 D = BO->getRHS();
12015 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12016 E = RHS;
12017 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12018 E = LHS;
12019 } else {
12020 ErrorInfo.Error = ErrorTy::InvalidComparison;
12021 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12022 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12023 S->getCond()->getSourceRange();
12024 return false;
12025 }
12026 } else if ((Cond &&
12027 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12028 (Call &&
12029 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12030 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12031 E = BO->getRHS();
12032 if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
12033 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12034 C = S->getCond();
12035 } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12036 checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12037 C = S->getCond();
12038 IsXBinopExpr = false;
12039 } else {
12040 ErrorInfo.Error = ErrorTy::InvalidComparison;
12041 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12042 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12043 S->getCond()->getSourceRange();
12044 return false;
12045 }
12046 } else {
12047 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12048 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12049 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12050 return false;
12051 }
12052
12053 if (S->getElse()) {
12054 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12055 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
12056 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
12057 return false;
12058 }
12059
12060 return true;
12061}
12062
12063bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
12064 ErrorInfoTy &ErrorInfo) {
12065 auto *BO = dyn_cast<BinaryOperator>(S);
12066 if (!BO) {
12067 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12068 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12069 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12070 return false;
12071 }
12072 if (BO->getOpcode() != BO_Assign) {
12073 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12074 ErrorInfo.ErrorLoc = BO->getExprLoc();
12075 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12076 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12077 return false;
12078 }
12079
12080 X = BO->getLHS();
12081
12082 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
12083 if (!CO) {
12084 ErrorInfo.Error = ErrorTy::NotCondOp;
12085 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12086 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12087 return false;
12088 }
12089
12090 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
12091 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12092 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12093 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12094 CO->getFalseExpr()->getSourceRange();
12095 return false;
12096 }
12097
12098 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
12099 auto *Call = dyn_cast<CXXOperatorCallExpr>(CO->getCond());
12100 Expr *LHS = nullptr;
12101 Expr *RHS = nullptr;
12102 if (Cond) {
12103 LHS = Cond->getLHS();
12104 RHS = Cond->getRHS();
12105 } else if (Call) {
12106 LHS = Call->getArg(0);
12107 RHS = Call->getArg(1);
12108 } else {
12109 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12110 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12111 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12112 CO->getCond()->getSourceRange();
12113 return false;
12114 }
12115
12116 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12117 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12118 C = CO->getCond();
12119 D = CO->getTrueExpr();
12120 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12121 E = RHS;
12122 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12123 E = LHS;
12124 } else {
12125 ErrorInfo.Error = ErrorTy::InvalidComparison;
12126 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12127 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12128 CO->getCond()->getSourceRange();
12129 return false;
12130 }
12131 } else if ((Cond &&
12132 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12133 (Call &&
12134 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12135 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12136
12137 E = CO->getTrueExpr();
12138 if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
12139 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12140 C = CO->getCond();
12141 } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12142 checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12143 C = CO->getCond();
12144 IsXBinopExpr = false;
12145 } else {
12146 ErrorInfo.Error = ErrorTy::InvalidComparison;
12147 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12148 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12149 CO->getCond()->getSourceRange();
12150 return false;
12151 }
12152 } else {
12153 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12154 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12155 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12156 CO->getCond()->getSourceRange();
12157 return false;
12158 }
12159
12160 return true;
12161}
12162
12163bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
12164 // 'x' and 'e' cannot be nullptr
12165 assert(X && E && "X and E cannot be nullptr");
12166
12167 if (!CheckValue(X, ErrorInfo, true))
12168 return false;
12169
12170 if (!CheckValue(E, ErrorInfo, false))
12171 return false;
12172
12173 if (D && !CheckValue(D, ErrorInfo, false))
12174 return false;
12175
12176 return true;
12177}
12178
12179bool OpenMPAtomicCompareChecker::checkStmt(
12180 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12181 auto *CS = dyn_cast<CompoundStmt>(S);
12182 if (CS) {
12183 if (CS->body_empty()) {
12184 ErrorInfo.Error = ErrorTy::NoStmt;
12185 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12186 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12187 return false;
12188 }
12189
12190 if (CS->size() != 1) {
12191 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12192 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12193 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12194 return false;
12195 }
12196 S = CS->body_front();
12197 }
12198
12199 auto Res = false;
12200
12201 if (auto *IS = dyn_cast<IfStmt>(S)) {
12202 // Check if the statement is in one of the following forms
12203 // (cond-update-stmt):
12204 // if (expr ordop x) { x = expr; }
12205 // if (x ordop expr) { x = expr; }
12206 // if (x == e) { x = d; }
12207 Res = checkCondUpdateStmt(IS, ErrorInfo);
12208 } else {
12209 // Check if the statement is in one of the following forms (cond-expr-stmt):
12210 // x = expr ordop x ? expr : x;
12211 // x = x ordop expr ? expr : x;
12212 // x = x == e ? d : x;
12213 Res = checkCondExprStmt(S, ErrorInfo);
12214 }
12215
12216 if (!Res)
12217 return false;
12218
12219 return checkType(ErrorInfo);
12220}
12221
12222class OpenMPAtomicCompareCaptureChecker final
12223 : public OpenMPAtomicCompareChecker {
12224public:
12225 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12226
12227 Expr *getV() const { return V; }
12228 Expr *getR() const { return R; }
12229 bool isFailOnly() const { return IsFailOnly; }
12230 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12231
12232 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12233 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12234
12235private:
12236 bool checkType(ErrorInfoTy &ErrorInfo);
12237
12238 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12239 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12240 // spec p.p. 82:
12241 // (1) { v = x; cond-update-stmt }
12242 // (2) { cond-update-stmt v = x; }
12243 // (3) if(x == e) { x = d; } else { v = x; }
12244 // (4) { r = x == e; if(r) { x = d; } }
12245 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12246
12247 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12248 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12249
12250 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12251 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12252 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12253
12254 /// 'v' lvalue part of the source atomic expression.
12255 Expr *V = nullptr;
12256 /// 'r' lvalue part of the source atomic expression.
12257 Expr *R = nullptr;
12258 /// If 'v' is only updated when the comparison fails.
12259 bool IsFailOnly = false;
12260 /// If original value of 'x' must be stored in 'v', not an updated one.
12261 bool IsPostfixUpdate = false;
12262};
12263
12264bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12265 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12266 return false;
12267
12268 if (V && !CheckValue(V, ErrorInfo, true))
12269 return false;
12270
12271 if (R && !CheckValue(R, ErrorInfo, true, true))
12272 return false;
12273
12274 return true;
12275}
12276
12277bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12278 ErrorInfoTy &ErrorInfo) {
12279 IsFailOnly = true;
12280
12281 auto *Then = S->getThen();
12282 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12283 if (CS->body_empty()) {
12284 ErrorInfo.Error = ErrorTy::NoStmt;
12285 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12286 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12287 return false;
12288 }
12289 if (CS->size() > 1) {
12290 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12291 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12292 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12293 return false;
12294 }
12295 Then = CS->body_front();
12296 }
12297
12298 auto *BO = dyn_cast<BinaryOperator>(Then);
12299 if (!BO) {
12300 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12301 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12302 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12303 return false;
12304 }
12305 if (BO->getOpcode() != BO_Assign) {
12306 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12307 ErrorInfo.ErrorLoc = BO->getExprLoc();
12308 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12309 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12310 return false;
12311 }
12312
12313 X = BO->getLHS();
12314 D = BO->getRHS();
12315
12316 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12317 auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
12318 Expr *LHS = nullptr;
12319 Expr *RHS = nullptr;
12320 if (Cond) {
12321 LHS = Cond->getLHS();
12322 RHS = Cond->getRHS();
12323 } else if (Call) {
12324 LHS = Call->getArg(0);
12325 RHS = Call->getArg(1);
12326 } else {
12327 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12328 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12329 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12330 return false;
12331 }
12332 if ((Cond && Cond->getOpcode() != BO_EQ) ||
12333 (Call && Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12334 ErrorInfo.Error = ErrorTy::NotEQ;
12335 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12336 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12337 return false;
12338 }
12339
12340 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12341 E = RHS;
12342 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12343 E = LHS;
12344 } else {
12345 ErrorInfo.Error = ErrorTy::InvalidComparison;
12346 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12347 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12348 return false;
12349 }
12350
12351 C = S->getCond();
12352
12353 if (!S->getElse()) {
12354 ErrorInfo.Error = ErrorTy::NoElse;
12355 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12356 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12357 return false;
12358 }
12359
12360 auto *Else = S->getElse();
12361 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12362 if (CS->body_empty()) {
12363 ErrorInfo.Error = ErrorTy::NoStmt;
12364 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12365 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12366 return false;
12367 }
12368 if (CS->size() > 1) {
12369 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12370 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12371 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12372 return false;
12373 }
12374 Else = CS->body_front();
12375 }
12376
12377 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12378 if (!ElseBO) {
12379 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12380 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12381 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12382 return false;
12383 }
12384 if (ElseBO->getOpcode() != BO_Assign) {
12385 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12386 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12387 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12388 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12389 return false;
12390 }
12391
12392 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12393 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12394 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12395 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12396 ElseBO->getRHS()->getSourceRange();
12397 return false;
12398 }
12399
12400 V = ElseBO->getLHS();
12401
12402 return checkType(ErrorInfo);
12403}
12404
12405bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12406 ErrorInfoTy &ErrorInfo) {
12407 // We don't check here as they should be already done before call this
12408 // function.
12409 auto *CS = cast<CompoundStmt>(S);
12410 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12411 auto *S1 = cast<BinaryOperator>(CS->body_front());
12412 auto *S2 = cast<IfStmt>(CS->body_back());
12413 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12414
12415 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12416 ErrorInfo.Error = ErrorTy::InvalidCondition;
12417 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12418 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12419 return false;
12420 }
12421
12422 R = S1->getLHS();
12423
12424 auto *Then = S2->getThen();
12425 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12426 if (ThenCS->body_empty()) {
12427 ErrorInfo.Error = ErrorTy::NoStmt;
12428 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12429 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12430 return false;
12431 }
12432 if (ThenCS->size() > 1) {
12433 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12434 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12435 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12436 return false;
12437 }
12438 Then = ThenCS->body_front();
12439 }
12440
12441 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12442 if (!ThenBO) {
12443 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12444 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12445 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12446 return false;
12447 }
12448 if (ThenBO->getOpcode() != BO_Assign) {
12449 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12450 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12451 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12452 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12453 return false;
12454 }
12455
12456 X = ThenBO->getLHS();
12457 D = ThenBO->getRHS();
12458
12459 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12460 if (BO->getOpcode() != BO_EQ) {
12461 ErrorInfo.Error = ErrorTy::NotEQ;
12462 ErrorInfo.ErrorLoc = BO->getExprLoc();
12463 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12464 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12465 return false;
12466 }
12467
12468 C = BO;
12469
12470 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12471 E = BO->getRHS();
12472 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12473 E = BO->getLHS();
12474 } else {
12475 ErrorInfo.Error = ErrorTy::InvalidComparison;
12476 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12477 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12478 return false;
12479 }
12480
12481 if (S2->getElse()) {
12482 IsFailOnly = true;
12483
12484 auto *Else = S2->getElse();
12485 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12486 if (ElseCS->body_empty()) {
12487 ErrorInfo.Error = ErrorTy::NoStmt;
12488 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12489 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12490 return false;
12491 }
12492 if (ElseCS->size() > 1) {
12493 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12494 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12495 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12496 return false;
12497 }
12498 Else = ElseCS->body_front();
12499 }
12500
12501 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12502 if (!ElseBO) {
12503 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12504 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12505 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12506 return false;
12507 }
12508 if (ElseBO->getOpcode() != BO_Assign) {
12509 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12510 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12511 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12512 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12513 return false;
12514 }
12515 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12516 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12517 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12518 ErrorInfo.NoteLoc = X->getExprLoc();
12519 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12520 ErrorInfo.NoteRange = X->getSourceRange();
12521 return false;
12522 }
12523
12524 V = ElseBO->getLHS();
12525 }
12526
12527 return checkType(ErrorInfo);
12528}
12529
12530bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12531 ErrorInfoTy &ErrorInfo) {
12532 // if(x == e) { x = d; } else { v = x; }
12533 if (auto *IS = dyn_cast<IfStmt>(S))
12534 return checkForm3(IS, ErrorInfo);
12535
12536 auto *CS = dyn_cast<CompoundStmt>(S);
12537 if (!CS) {
12538 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12539 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12540 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12541 return false;
12542 }
12543 if (CS->body_empty()) {
12544 ErrorInfo.Error = ErrorTy::NoStmt;
12545 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12546 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12547 return false;
12548 }
12549
12550 // { if(x == e) { x = d; } else { v = x; } }
12551 if (CS->size() == 1) {
12552 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12553 if (!IS) {
12554 ErrorInfo.Error = ErrorTy::NotIfStmt;
12555 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12556 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12557 CS->body_front()->getSourceRange();
12558 return false;
12559 }
12560
12561 return checkForm3(IS, ErrorInfo);
12562 } else if (CS->size() == 2) {
12563 auto *S1 = CS->body_front();
12564 auto *S2 = CS->body_back();
12565
12566 Stmt *UpdateStmt = nullptr;
12567 Stmt *CondUpdateStmt = nullptr;
12568 Stmt *CondExprStmt = nullptr;
12569
12570 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12571 // It could be one of the following cases:
12572 // { v = x; cond-update-stmt }
12573 // { v = x; cond-expr-stmt }
12574 // { cond-expr-stmt; v = x; }
12575 // form 45
12576 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12577 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12578 // check if form 45
12579 if (isa<IfStmt>(S2))
12580 return checkForm45(CS, ErrorInfo);
12581 // { cond-expr-stmt; v = x; }
12582 CondExprStmt = S1;
12583 UpdateStmt = S2;
12584 } else {
12585 IsPostfixUpdate = true;
12586 UpdateStmt = S1;
12587 if (isa<IfStmt>(S2)) {
12588 // { v = x; cond-update-stmt }
12589 CondUpdateStmt = S2;
12590 } else {
12591 // { v = x; cond-expr-stmt }
12592 CondExprStmt = S2;
12593 }
12594 }
12595 } else {
12596 // { cond-update-stmt v = x; }
12597 UpdateStmt = S2;
12598 CondUpdateStmt = S1;
12599 }
12600
12601 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12602 auto *IS = dyn_cast<IfStmt>(CUS);
12603 if (!IS) {
12604 ErrorInfo.Error = ErrorTy::NotIfStmt;
12605 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12606 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12607 return false;
12608 }
12609
12610 return checkCondUpdateStmt(IS, ErrorInfo);
12611 };
12612
12613 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12614 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12615 auto *BO = dyn_cast<BinaryOperator>(US);
12616 if (!BO) {
12617 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12618 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12619 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12620 return false;
12621 }
12622 if (BO->getOpcode() != BO_Assign) {
12623 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12624 ErrorInfo.ErrorLoc = BO->getExprLoc();
12625 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12626 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12627 return false;
12628 }
12629 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12630 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12631 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12632 ErrorInfo.NoteLoc = this->X->getExprLoc();
12633 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12634 ErrorInfo.NoteRange = this->X->getSourceRange();
12635 return false;
12636 }
12637
12638 this->V = BO->getLHS();
12639
12640 return true;
12641 };
12642
12643 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12644 return false;
12645 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12646 return false;
12647 if (!CheckUpdateStmt(UpdateStmt))
12648 return false;
12649 } else {
12650 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12651 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12652 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12653 return false;
12654 }
12655
12656 return checkType(ErrorInfo);
12657}
12658} // namespace
12659
12661 Stmt *AStmt,
12662 SourceLocation StartLoc,
12663 SourceLocation EndLoc) {
12664 ASTContext &Context = getASTContext();
12665 unsigned OMPVersion = getLangOpts().OpenMP;
12666 // Register location of the first atomic directive.
12667 DSAStack->addAtomicDirectiveLoc(StartLoc);
12668 if (!AStmt)
12669 return StmtError();
12670
12671 // 1.2.2 OpenMP Language Terminology
12672 // Structured block - An executable statement with a single entry at the
12673 // top and a single exit at the bottom.
12674 // The point of exit cannot be a branch out of the structured block.
12675 // longjmp() and throw() must not violate the entry/exit criteria.
12676 OpenMPClauseKind AtomicKind = OMPC_unknown;
12677 SourceLocation AtomicKindLoc;
12678 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12679 SourceLocation MemOrderLoc;
12680 bool MutexClauseEncountered = false;
12681 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12682 for (const OMPClause *C : Clauses) {
12683 switch (C->getClauseKind()) {
12684 case OMPC_read:
12685 case OMPC_write:
12686 case OMPC_update:
12687 MutexClauseEncountered = true;
12688 [[fallthrough]];
12689 case OMPC_capture:
12690 case OMPC_compare: {
12691 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12692 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12693 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12694 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12695 << getOpenMPClauseNameForDiag(AtomicKind);
12696 } else {
12697 AtomicKind = C->getClauseKind();
12698 AtomicKindLoc = C->getBeginLoc();
12699 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12700 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12701 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12702 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12703 << getOpenMPClauseNameForDiag(AtomicKind);
12704 }
12705 }
12706 break;
12707 }
12708 case OMPC_weak:
12709 case OMPC_fail: {
12710 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12711 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12712 << getOpenMPClauseNameForDiag(C->getClauseKind())
12713 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12714 return StmtError();
12715 }
12716 break;
12717 }
12718 case OMPC_seq_cst:
12719 case OMPC_acq_rel:
12720 case OMPC_acquire:
12721 case OMPC_release:
12722 case OMPC_relaxed: {
12723 if (MemOrderKind != OMPC_unknown) {
12724 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12725 << getOpenMPDirectiveName(OMPD_atomic, OMPVersion) << 0
12726 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12727 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12728 << getOpenMPClauseNameForDiag(MemOrderKind);
12729 } else {
12730 MemOrderKind = C->getClauseKind();
12731 MemOrderLoc = C->getBeginLoc();
12732 }
12733 break;
12734 }
12735 // The following clauses are allowed, but we don't need to do anything here.
12736 case OMPC_hint:
12737 break;
12738 default:
12739 llvm_unreachable("unknown clause is encountered");
12740 }
12741 }
12742 bool IsCompareCapture = false;
12743 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12744 EncounteredAtomicKinds.contains(OMPC_capture)) {
12745 IsCompareCapture = true;
12746 AtomicKind = OMPC_compare;
12747 }
12748 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12749 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12750 // release.
12751 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12752 // acquire.
12753 // If atomic-clause is update or not present then memory-order-clause must not
12754 // be acq_rel or acquire.
12755 if ((AtomicKind == OMPC_read &&
12756 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12757 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12758 AtomicKind == OMPC_unknown) &&
12759 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12760 SourceLocation Loc = AtomicKindLoc;
12761 if (AtomicKind == OMPC_unknown)
12762 Loc = StartLoc;
12763 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12764 << getOpenMPClauseNameForDiag(AtomicKind)
12765 << (AtomicKind == OMPC_unknown ? 1 : 0)
12766 << getOpenMPClauseNameForDiag(MemOrderKind);
12767 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12768 << getOpenMPClauseNameForDiag(MemOrderKind);
12769 }
12770
12771 Stmt *Body = AStmt;
12772 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12773 Body = EWC->getSubExpr();
12774
12775 Expr *X = nullptr;
12776 Expr *V = nullptr;
12777 Expr *E = nullptr;
12778 Expr *UE = nullptr;
12779 Expr *D = nullptr;
12780 Expr *CE = nullptr;
12781 Expr *R = nullptr;
12782 bool IsXLHSInRHSPart = false;
12783 bool IsPostfixUpdate = false;
12784 bool IsFailOnly = false;
12785 // OpenMP [2.12.6, atomic Construct]
12786 // In the next expressions:
12787 // * x and v (as applicable) are both l-value expressions with scalar type.
12788 // * During the execution of an atomic region, multiple syntactic
12789 // occurrences of x must designate the same storage location.
12790 // * Neither of v and expr (as applicable) may access the storage location
12791 // designated by x.
12792 // * Neither of x and expr (as applicable) may access the storage location
12793 // designated by v.
12794 // * expr is an expression with scalar type.
12795 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12796 // * binop, binop=, ++, and -- are not overloaded operators.
12797 // * The expression x binop expr must be numerically equivalent to x binop
12798 // (expr). This requirement is satisfied if the operators in expr have
12799 // precedence greater than binop, or by using parentheses around expr or
12800 // subexpressions of expr.
12801 // * The expression expr binop x must be numerically equivalent to (expr)
12802 // binop x. This requirement is satisfied if the operators in expr have
12803 // precedence equal to or greater than binop, or by using parentheses around
12804 // expr or subexpressions of expr.
12805 // * For forms that allow multiple occurrences of x, the number of times
12806 // that x is evaluated is unspecified.
12807 if (AtomicKind == OMPC_read) {
12808 enum {
12809 NotAnExpression,
12810 NotAnAssignmentOp,
12811 NotAScalarType,
12812 NotAnLValue,
12813 NoError
12814 } ErrorFound = NoError;
12815 SourceLocation ErrorLoc, NoteLoc;
12816 SourceRange ErrorRange, NoteRange;
12817 // If clause is read:
12818 // v = x;
12819 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12820 const auto *AtomicBinOp =
12821 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12822 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12823 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12824 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12825 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12826 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12827 if (!X->isLValue() || !V->isLValue()) {
12828 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12829 ErrorFound = NotAnLValue;
12830 ErrorLoc = AtomicBinOp->getExprLoc();
12831 ErrorRange = AtomicBinOp->getSourceRange();
12832 NoteLoc = NotLValueExpr->getExprLoc();
12833 NoteRange = NotLValueExpr->getSourceRange();
12834 }
12835 } else if (!X->isInstantiationDependent() ||
12836 !V->isInstantiationDependent()) {
12837 const Expr *NotScalarExpr =
12838 (X->isInstantiationDependent() || X->getType()->isScalarType())
12839 ? V
12840 : X;
12841 ErrorFound = NotAScalarType;
12842 ErrorLoc = AtomicBinOp->getExprLoc();
12843 ErrorRange = AtomicBinOp->getSourceRange();
12844 NoteLoc = NotScalarExpr->getExprLoc();
12845 NoteRange = NotScalarExpr->getSourceRange();
12846 }
12847 } else if (!AtomicBody->isInstantiationDependent()) {
12848 ErrorFound = NotAnAssignmentOp;
12849 ErrorLoc = AtomicBody->getExprLoc();
12850 ErrorRange = AtomicBody->getSourceRange();
12851 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12852 : AtomicBody->getExprLoc();
12853 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12854 : AtomicBody->getSourceRange();
12855 }
12856 } else {
12857 ErrorFound = NotAnExpression;
12858 NoteLoc = ErrorLoc = Body->getBeginLoc();
12859 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12860 }
12861 if (ErrorFound != NoError) {
12862 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12863 << ErrorRange;
12864 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12865 << ErrorFound << NoteRange;
12866 return StmtError();
12867 }
12868 if (SemaRef.CurContext->isDependentContext())
12869 V = X = nullptr;
12870 } else if (AtomicKind == OMPC_write) {
12871 enum {
12872 NotAnExpression,
12873 NotAnAssignmentOp,
12874 NotAScalarType,
12875 NotAnLValue,
12876 NoError
12877 } ErrorFound = NoError;
12878 SourceLocation ErrorLoc, NoteLoc;
12879 SourceRange ErrorRange, NoteRange;
12880 // If clause is write:
12881 // x = expr;
12882 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12883 const auto *AtomicBinOp =
12884 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12885 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12886 X = AtomicBinOp->getLHS();
12887 E = AtomicBinOp->getRHS();
12888 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12889 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
12890 if (!X->isLValue()) {
12891 ErrorFound = NotAnLValue;
12892 ErrorLoc = AtomicBinOp->getExprLoc();
12893 ErrorRange = AtomicBinOp->getSourceRange();
12894 NoteLoc = X->getExprLoc();
12895 NoteRange = X->getSourceRange();
12896 }
12897 } else if (!X->isInstantiationDependent() ||
12899 const Expr *NotScalarExpr =
12900 (X->isInstantiationDependent() || X->getType()->isScalarType())
12901 ? E
12902 : X;
12903 ErrorFound = NotAScalarType;
12904 ErrorLoc = AtomicBinOp->getExprLoc();
12905 ErrorRange = AtomicBinOp->getSourceRange();
12906 NoteLoc = NotScalarExpr->getExprLoc();
12907 NoteRange = NotScalarExpr->getSourceRange();
12908 }
12909 } else if (!AtomicBody->isInstantiationDependent()) {
12910 ErrorFound = NotAnAssignmentOp;
12911 ErrorLoc = AtomicBody->getExprLoc();
12912 ErrorRange = AtomicBody->getSourceRange();
12913 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12914 : AtomicBody->getExprLoc();
12915 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12916 : AtomicBody->getSourceRange();
12917 }
12918 } else {
12919 ErrorFound = NotAnExpression;
12920 NoteLoc = ErrorLoc = Body->getBeginLoc();
12921 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12922 }
12923 if (ErrorFound != NoError) {
12924 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12925 << ErrorRange;
12926 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12927 << ErrorFound << NoteRange;
12928 return StmtError();
12929 }
12930 if (SemaRef.CurContext->isDependentContext())
12931 E = X = nullptr;
12932 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12933 // If clause is update:
12934 // x++;
12935 // x--;
12936 // ++x;
12937 // --x;
12938 // x binop= expr;
12939 // x = x binop expr;
12940 // x = expr binop x;
12941 OpenMPAtomicUpdateChecker Checker(SemaRef);
12942 if (Checker.checkStatement(
12943 Body,
12944 (AtomicKind == OMPC_update)
12945 ? diag::err_omp_atomic_update_not_expression_statement
12946 : diag::err_omp_atomic_not_expression_statement,
12947 diag::note_omp_atomic_update))
12948 return StmtError();
12949 if (!SemaRef.CurContext->isDependentContext()) {
12950 E = Checker.getExpr();
12951 X = Checker.getX();
12952 UE = Checker.getUpdateExpr();
12953 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12954 }
12955 } else if (AtomicKind == OMPC_capture) {
12956 enum {
12957 NotAnAssignmentOp,
12958 NotACompoundStatement,
12959 NotTwoSubstatements,
12960 NotASpecificExpression,
12961 NoError
12962 } ErrorFound = NoError;
12963 SourceLocation ErrorLoc, NoteLoc;
12964 SourceRange ErrorRange, NoteRange;
12965 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12966 // If clause is a capture:
12967 // v = x++;
12968 // v = x--;
12969 // v = ++x;
12970 // v = --x;
12971 // v = x binop= expr;
12972 // v = x = x binop expr;
12973 // v = x = expr binop x;
12974 const auto *AtomicBinOp =
12975 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12976 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12977 V = AtomicBinOp->getLHS();
12978 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12979 OpenMPAtomicUpdateChecker Checker(SemaRef);
12980 if (Checker.checkStatement(
12981 Body, diag::err_omp_atomic_capture_not_expression_statement,
12982 diag::note_omp_atomic_update))
12983 return StmtError();
12984 E = Checker.getExpr();
12985 X = Checker.getX();
12986 UE = Checker.getUpdateExpr();
12987 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12988 IsPostfixUpdate = Checker.isPostfixUpdate();
12989 } else if (!AtomicBody->isInstantiationDependent()) {
12990 ErrorLoc = AtomicBody->getExprLoc();
12991 ErrorRange = AtomicBody->getSourceRange();
12992 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12993 : AtomicBody->getExprLoc();
12994 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12995 : AtomicBody->getSourceRange();
12996 ErrorFound = NotAnAssignmentOp;
12997 }
12998 if (ErrorFound != NoError) {
12999 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
13000 << ErrorRange;
13001 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13002 return StmtError();
13003 }
13004 if (SemaRef.CurContext->isDependentContext())
13005 UE = V = E = X = nullptr;
13006 } else {
13007 // If clause is a capture:
13008 // { v = x; x = expr; }
13009 // { v = x; x++; }
13010 // { v = x; x--; }
13011 // { v = x; ++x; }
13012 // { v = x; --x; }
13013 // { v = x; x binop= expr; }
13014 // { v = x; x = x binop expr; }
13015 // { v = x; x = expr binop x; }
13016 // { x++; v = x; }
13017 // { x--; v = x; }
13018 // { ++x; v = x; }
13019 // { --x; v = x; }
13020 // { x binop= expr; v = x; }
13021 // { x = x binop expr; v = x; }
13022 // { x = expr binop x; v = x; }
13023 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
13024 // Check that this is { expr1; expr2; }
13025 if (CS->size() == 2) {
13026 Stmt *First = CS->body_front();
13027 Stmt *Second = CS->body_back();
13028 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
13029 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13030 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
13031 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13032 // Need to find what subexpression is 'v' and what is 'x'.
13033 OpenMPAtomicUpdateChecker Checker(SemaRef);
13034 bool IsUpdateExprFound = !Checker.checkStatement(Second);
13035 BinaryOperator *BinOp = nullptr;
13036 if (IsUpdateExprFound) {
13037 BinOp = dyn_cast<BinaryOperator>(First);
13038 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13039 }
13040 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
13041 // { v = x; x++; }
13042 // { v = x; x--; }
13043 // { v = x; ++x; }
13044 // { v = x; --x; }
13045 // { v = x; x binop= expr; }
13046 // { v = x; x = x binop expr; }
13047 // { v = x; x = expr binop x; }
13048 // Check that the first expression has form v = x.
13049 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13050 llvm::FoldingSetNodeID XId, PossibleXId;
13051 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13052 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13053 IsUpdateExprFound = XId == PossibleXId;
13054 if (IsUpdateExprFound) {
13055 V = BinOp->getLHS();
13056 X = Checker.getX();
13057 E = Checker.getExpr();
13058 UE = Checker.getUpdateExpr();
13059 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13060 IsPostfixUpdate = true;
13061 }
13062 }
13063 if (!IsUpdateExprFound) {
13064 IsUpdateExprFound = !Checker.checkStatement(First);
13065 BinOp = nullptr;
13066 if (IsUpdateExprFound) {
13067 BinOp = dyn_cast<BinaryOperator>(Second);
13068 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13069 }
13070 if (IsUpdateExprFound &&
13071 !SemaRef.CurContext->isDependentContext()) {
13072 // { x++; v = x; }
13073 // { x--; v = x; }
13074 // { ++x; v = x; }
13075 // { --x; v = x; }
13076 // { x binop= expr; v = x; }
13077 // { x = x binop expr; v = x; }
13078 // { x = expr binop x; v = x; }
13079 // Check that the second expression has form v = x.
13080 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13081 llvm::FoldingSetNodeID XId, PossibleXId;
13082 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13083 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13084 IsUpdateExprFound = XId == PossibleXId;
13085 if (IsUpdateExprFound) {
13086 V = BinOp->getLHS();
13087 X = Checker.getX();
13088 E = Checker.getExpr();
13089 UE = Checker.getUpdateExpr();
13090 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13091 IsPostfixUpdate = false;
13092 }
13093 }
13094 }
13095 if (!IsUpdateExprFound) {
13096 // { v = x; x = expr; }
13097 auto *FirstExpr = dyn_cast<Expr>(First);
13098 auto *SecondExpr = dyn_cast<Expr>(Second);
13099 if (!FirstExpr || !SecondExpr ||
13100 !(FirstExpr->isInstantiationDependent() ||
13101 SecondExpr->isInstantiationDependent())) {
13102 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
13103 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13104 ErrorFound = NotAnAssignmentOp;
13105 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13106 : First->getBeginLoc();
13107 NoteRange = ErrorRange = FirstBinOp
13108 ? FirstBinOp->getSourceRange()
13109 : SourceRange(ErrorLoc, ErrorLoc);
13110 } else {
13111 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
13112 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13113 ErrorFound = NotAnAssignmentOp;
13114 NoteLoc = ErrorLoc = SecondBinOp
13115 ? SecondBinOp->getOperatorLoc()
13116 : Second->getBeginLoc();
13117 NoteRange = ErrorRange =
13118 SecondBinOp ? SecondBinOp->getSourceRange()
13119 : SourceRange(ErrorLoc, ErrorLoc);
13120 } else {
13121 Expr *PossibleXRHSInFirst =
13122 FirstBinOp->getRHS()->IgnoreParenImpCasts();
13123 Expr *PossibleXLHSInSecond =
13124 SecondBinOp->getLHS()->IgnoreParenImpCasts();
13125 llvm::FoldingSetNodeID X1Id, X2Id;
13126 PossibleXRHSInFirst->Profile(X1Id, Context,
13127 /*Canonical=*/true);
13128 PossibleXLHSInSecond->Profile(X2Id, Context,
13129 /*Canonical=*/true);
13130 IsUpdateExprFound = X1Id == X2Id;
13131 if (IsUpdateExprFound) {
13132 V = FirstBinOp->getLHS();
13133 X = SecondBinOp->getLHS();
13134 E = SecondBinOp->getRHS();
13135 UE = nullptr;
13136 IsXLHSInRHSPart = false;
13137 IsPostfixUpdate = true;
13138 } else {
13139 ErrorFound = NotASpecificExpression;
13140 ErrorLoc = FirstBinOp->getExprLoc();
13141 ErrorRange = FirstBinOp->getSourceRange();
13142 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13143 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13144 }
13145 }
13146 }
13147 }
13148 }
13149 } else {
13150 NoteLoc = ErrorLoc = Body->getBeginLoc();
13151 NoteRange = ErrorRange =
13152 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13153 ErrorFound = NotTwoSubstatements;
13154 }
13155 } else {
13156 NoteLoc = ErrorLoc = Body->getBeginLoc();
13157 NoteRange = ErrorRange =
13158 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13159 ErrorFound = NotACompoundStatement;
13160 }
13161 }
13162 if (ErrorFound != NoError) {
13163 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_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 if (AtomicKind == OMPC_compare) {
13171 if (IsCompareCapture) {
13172 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13173 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
13174 if (!Checker.checkStmt(Body, ErrorInfo)) {
13175 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
13176 << ErrorInfo.ErrorRange;
13177 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13178 << ErrorInfo.Error << ErrorInfo.NoteRange;
13179 return StmtError();
13180 }
13181 X = Checker.getX();
13182 E = Checker.getE();
13183 D = Checker.getD();
13184 CE = Checker.getCond();
13185 V = Checker.getV();
13186 R = Checker.getR();
13187 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13188 IsXLHSInRHSPart = Checker.isXBinopExpr();
13189 IsFailOnly = Checker.isFailOnly();
13190 IsPostfixUpdate = Checker.isPostfixUpdate();
13191 } else {
13192 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13193 OpenMPAtomicCompareChecker Checker(SemaRef);
13194 if (!Checker.checkStmt(Body, ErrorInfo)) {
13195 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
13196 << ErrorInfo.ErrorRange;
13197 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13198 << ErrorInfo.Error << ErrorInfo.NoteRange;
13199 return StmtError();
13200 }
13201 X = Checker.getX();
13202 E = Checker.getE();
13203 D = Checker.getD();
13204 CE = Checker.getCond();
13205 // The weak clause may only appear if the resulting atomic operation is
13206 // an atomic conditional update for which the comparison tests for
13207 // equality. It was not possible to do this check in
13208 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
13209 // could not be performed (Clauses are not available).
13210 auto *It = find_if(Clauses, [](OMPClause *C) {
13211 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13212 });
13213 if (It != Clauses.end()) {
13214 auto *Cond = dyn_cast<BinaryOperator>(CE);
13215 if (Cond->getOpcode() != BO_EQ) {
13216 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13217 ErrorInfo.ErrorLoc = Cond->getExprLoc();
13218 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
13219 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
13220
13221 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
13222 << ErrorInfo.ErrorRange;
13223 return StmtError();
13224 }
13225 }
13226 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13227 IsXLHSInRHSPart = Checker.isXBinopExpr();
13228 }
13229 }
13230
13231 SemaRef.setFunctionHasBranchProtectedScope();
13232
13233 return OMPAtomicDirective::Create(
13234 Context, StartLoc, EndLoc, Clauses, AStmt,
13235 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
13236}
13237
13239 Stmt *AStmt,
13240 SourceLocation StartLoc,
13241 SourceLocation EndLoc) {
13242 if (!AStmt)
13243 return StmtError();
13244
13245 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target, AStmt);
13246
13247 // OpenMP [2.16, Nesting of Regions]
13248 // If specified, a teams construct must be contained within a target
13249 // construct. That target construct must contain no statements or directives
13250 // outside of the teams construct.
13251 if (DSAStack->hasInnerTeamsRegion()) {
13252 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13253 bool OMPTeamsFound = true;
13254 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
13255 auto I = CS->body_begin();
13256 while (I != CS->body_end()) {
13257 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13258 bool IsTeams = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13259 if (!IsTeams || I != CS->body_begin()) {
13260 OMPTeamsFound = false;
13261 if (IsTeams && I != CS->body_begin()) {
13262 // This is the two teams case. Since the InnerTeamsRegionLoc will
13263 // point to this second one reset the iterator to the other teams.
13264 --I;
13265 }
13266 break;
13267 }
13268 ++I;
13269 }
13270 assert(I != CS->body_end() && "Not found statement");
13271 S = *I;
13272 } else {
13273 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13274 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13275 }
13276 if (!OMPTeamsFound) {
13277 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13278 Diag(DSAStack->getInnerTeamsRegionLoc(),
13279 diag::note_omp_nested_teams_construct_here);
13280 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
13282 return StmtError();
13283 }
13284 }
13285
13286 return OMPTargetDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13287 AStmt);
13288}
13289
13291 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13292 SourceLocation EndLoc) {
13293 if (!AStmt)
13294 return StmtError();
13295
13296 setBranchProtectedScope(SemaRef, OMPD_target_parallel, AStmt);
13297
13299 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
13300 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13301}
13302
13304 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13305 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13306 if (!AStmt)
13307 return StmtError();
13308
13309 CapturedStmt *CS =
13310 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for, AStmt);
13311
13312 OMPLoopBasedDirective::HelperExprs B;
13313 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13314 // define the nested loops number.
13315 unsigned NestedLoopCount =
13316 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13317 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13318 VarsWithImplicitDSA, B);
13319 if (NestedLoopCount == 0)
13320 return StmtError();
13321
13322 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13323 return StmtError();
13324
13326 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13327 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13328}
13329
13330/// Check for existence of a map clause in the list of clauses.
13332 const OpenMPClauseKind K) {
13333 return llvm::any_of(
13334 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13335}
13336
13337template <typename... Params>
13339 const Params... ClauseTypes) {
13340 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13341}
13342
13343/// Check if the variables in the mapping clause are externally visible.
13345 for (const OMPClause *C : Clauses) {
13346 if (auto *TC = dyn_cast<OMPToClause>(C))
13347 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13348 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13349 (VD->isExternallyVisible() &&
13350 VD->getVisibility() != HiddenVisibility);
13351 });
13352 else if (auto *FC = dyn_cast<OMPFromClause>(C))
13353 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13354 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13355 (VD->isExternallyVisible() &&
13356 VD->getVisibility() != HiddenVisibility);
13357 });
13358 }
13359
13360 return true;
13361}
13362
13365 Stmt *AStmt, SourceLocation StartLoc,
13366 SourceLocation EndLoc) {
13367 if (!AStmt)
13368 return StmtError();
13369
13370 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13371
13372 // OpenMP [2.12.2, target data Construct, Restrictions]
13373 // At least one map, use_device_addr or use_device_ptr clause must appear on
13374 // the directive.
13375 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13376 (getLangOpts().OpenMP < 50 ||
13377 !hasClauses(Clauses, OMPC_use_device_addr))) {
13378 StringRef Expected;
13379 if (getLangOpts().OpenMP < 50)
13380 Expected = "'map' or 'use_device_ptr'";
13381 else
13382 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13383 unsigned OMPVersion = getLangOpts().OpenMP;
13384 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13385 << Expected << getOpenMPDirectiveName(OMPD_target_data, OMPVersion);
13386 return StmtError();
13387 }
13388
13389 SemaRef.setFunctionHasBranchProtectedScope();
13390
13391 return OMPTargetDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13392 Clauses, AStmt);
13393}
13394
13396 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13397 SourceLocation EndLoc, Stmt *AStmt) {
13398 if (!AStmt)
13399 return StmtError();
13400
13401 setBranchProtectedScope(SemaRef, OMPD_target_enter_data, AStmt);
13402
13403 // OpenMP [2.10.2, Restrictions, p. 99]
13404 // At least one map clause must appear on the directive.
13405 if (!hasClauses(Clauses, OMPC_map)) {
13406 unsigned OMPVersion = getLangOpts().OpenMP;
13407 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13408 << "'map'"
13409 << getOpenMPDirectiveName(OMPD_target_enter_data, OMPVersion);
13410 return StmtError();
13411 }
13412
13413 return OMPTargetEnterDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13414 Clauses, AStmt);
13415}
13416
13418 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13419 SourceLocation EndLoc, Stmt *AStmt) {
13420 if (!AStmt)
13421 return StmtError();
13422
13423 setBranchProtectedScope(SemaRef, OMPD_target_exit_data, AStmt);
13424
13425 // OpenMP [2.10.3, Restrictions, p. 102]
13426 // At least one map clause must appear on the directive.
13427 if (!hasClauses(Clauses, OMPC_map)) {
13428 unsigned OMPVersion = getLangOpts().OpenMP;
13429 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13430 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data, OMPVersion);
13431 return StmtError();
13432 }
13433
13434 return OMPTargetExitDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13435 Clauses, AStmt);
13436}
13437
13439 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13440 SourceLocation EndLoc, Stmt *AStmt) {
13441 if (!AStmt)
13442 return StmtError();
13443
13444 setBranchProtectedScope(SemaRef, OMPD_target_update, AStmt);
13445
13446 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13447 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13448 return StmtError();
13449 }
13450
13451 if (!isClauseMappable(Clauses)) {
13452 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13453 return StmtError();
13454 }
13455
13456 return OMPTargetUpdateDirective::Create(getASTContext(), StartLoc, EndLoc,
13457 Clauses, AStmt);
13458}
13459
13460/// This checks whether a \p ClauseType clause \p C has at most \p Max
13461/// expression. If not, a diag of number \p Diag will be emitted.
13462template <typename ClauseType>
13463static bool checkNumExprsInClause(SemaBase &SemaRef,
13464 ArrayRef<OMPClause *> Clauses,
13465 unsigned MaxNum, unsigned Diag) {
13466 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13467 if (ClauseItr == Clauses.end())
13468 return true;
13469 const auto *C = cast<ClauseType>(*ClauseItr);
13470 auto VarList = C->getVarRefs();
13471 if (VarList.size() > MaxNum) {
13472 SemaRef.Diag(VarList[MaxNum]->getBeginLoc(), Diag)
13473 << getOpenMPClauseNameForDiag(C->getClauseKind());
13474 return false;
13475 }
13476 return true;
13477}
13478
13480 Stmt *AStmt,
13481 SourceLocation StartLoc,
13482 SourceLocation EndLoc) {
13483 if (!AStmt)
13484 return StmtError();
13485
13487 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
13489 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
13490 return StmtError();
13491
13492 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13493 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13494 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13495
13496 setBranchProtectedScope(SemaRef, OMPD_teams, AStmt);
13497
13498 DSAStack->setParentTeamsRegionLoc(StartLoc);
13499
13500 return OMPTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13501 AStmt);
13502}
13503
13505 SourceLocation StartLoc, SourceLocation EndLoc,
13506 OpenMPDirectiveKind CancelRegion) {
13507 if (DSAStack->isParentNowaitRegion()) {
13508 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13509 return StmtError();
13510 }
13511 if (DSAStack->isParentOrderedRegion()) {
13512 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13513 return StmtError();
13514 }
13516 EndLoc, CancelRegion);
13517}
13518
13520 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13521 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13522 if (DSAStack->isParentNowaitRegion()) {
13523 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13524 return StmtError();
13525 }
13526 if (DSAStack->isParentOrderedRegion()) {
13527 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13528 return StmtError();
13529 }
13530 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13531 return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13532 CancelRegion);
13533}
13534
13536 ArrayRef<OMPClause *> Clauses) {
13537 const OMPClause *ReductionClause = nullptr;
13538 const OMPClause *NogroupClause = nullptr;
13539 for (const OMPClause *C : Clauses) {
13540 if (C->getClauseKind() == OMPC_reduction) {
13541 ReductionClause = C;
13542 if (NogroupClause)
13543 break;
13544 continue;
13545 }
13546 if (C->getClauseKind() == OMPC_nogroup) {
13547 NogroupClause = C;
13548 if (ReductionClause)
13549 break;
13550 continue;
13551 }
13552 }
13553 if (ReductionClause && NogroupClause) {
13554 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13555 << SourceRange(NogroupClause->getBeginLoc(),
13556 NogroupClause->getEndLoc());
13557 return true;
13558 }
13559 return false;
13560}
13561
13563 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13564 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13565 if (!AStmt)
13566 return StmtError();
13567
13568 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13569 OMPLoopBasedDirective::HelperExprs B;
13570 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13571 // define the nested loops number.
13572 unsigned NestedLoopCount =
13573 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13574 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13575 *DSAStack, VarsWithImplicitDSA, B);
13576 if (NestedLoopCount == 0)
13577 return StmtError();
13578
13579 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13580 "omp for loop exprs were not built");
13581
13582 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13583 // The grainsize clause and num_tasks clause are mutually exclusive and may
13584 // not appear on the same taskloop directive.
13586 {OMPC_grainsize, OMPC_num_tasks}))
13587 return StmtError();
13588 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13589 // If a reduction clause is present on the taskloop directive, the nogroup
13590 // clause must not be specified.
13592 return StmtError();
13593
13594 SemaRef.setFunctionHasBranchProtectedScope();
13595 return OMPTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13596 NestedLoopCount, Clauses, AStmt, B,
13597 DSAStack->isCancelRegion());
13598}
13599
13601 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13602 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13603 if (!AStmt)
13604 return StmtError();
13605
13606 CapturedStmt *CS =
13607 setBranchProtectedScope(SemaRef, OMPD_taskloop_simd, AStmt);
13608
13609 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13610 OMPLoopBasedDirective::HelperExprs B;
13611 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13612 // define the nested loops number.
13613 unsigned NestedLoopCount =
13614 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13615 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13616 VarsWithImplicitDSA, B);
13617 if (NestedLoopCount == 0)
13618 return StmtError();
13619
13620 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13621 return StmtError();
13622
13623 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13624 // The grainsize clause and num_tasks clause are mutually exclusive and may
13625 // not appear on the same taskloop directive.
13627 {OMPC_grainsize, OMPC_num_tasks}))
13628 return StmtError();
13629 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13630 // If a reduction clause is present on the taskloop directive, the nogroup
13631 // clause must not be specified.
13633 return StmtError();
13635 return StmtError();
13636
13637 return OMPTaskLoopSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13638 NestedLoopCount, Clauses, AStmt, B);
13639}
13640
13642 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13643 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13644 if (!AStmt)
13645 return StmtError();
13646
13647 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13648 OMPLoopBasedDirective::HelperExprs B;
13649 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13650 // define the nested loops number.
13651 unsigned NestedLoopCount =
13652 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13653 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13654 *DSAStack, VarsWithImplicitDSA, B);
13655 if (NestedLoopCount == 0)
13656 return StmtError();
13657
13658 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13659 "omp for loop exprs were not built");
13660
13661 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13662 // The grainsize clause and num_tasks clause are mutually exclusive and may
13663 // not appear on the same taskloop directive.
13665 {OMPC_grainsize, OMPC_num_tasks}))
13666 return StmtError();
13667 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13668 // If a reduction clause is present on the taskloop directive, the nogroup
13669 // clause must not be specified.
13671 return StmtError();
13672
13673 SemaRef.setFunctionHasBranchProtectedScope();
13674 return OMPMasterTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13675 NestedLoopCount, Clauses, AStmt, B,
13676 DSAStack->isCancelRegion());
13677}
13678
13680 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13681 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13682 if (!AStmt)
13683 return StmtError();
13684
13685 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13686 OMPLoopBasedDirective::HelperExprs B;
13687 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13688 // define the nested loops number.
13689 unsigned NestedLoopCount =
13690 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13691 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13692 *DSAStack, VarsWithImplicitDSA, B);
13693 if (NestedLoopCount == 0)
13694 return StmtError();
13695
13696 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13697 "omp for loop exprs were not built");
13698
13699 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13700 // The grainsize clause and num_tasks clause are mutually exclusive and may
13701 // not appear on the same taskloop directive.
13703 {OMPC_grainsize, OMPC_num_tasks}))
13704 return StmtError();
13705 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13706 // If a reduction clause is present on the taskloop directive, the nogroup
13707 // clause must not be specified.
13709 return StmtError();
13710
13711 SemaRef.setFunctionHasBranchProtectedScope();
13712 return OMPMaskedTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13713 NestedLoopCount, Clauses, AStmt, B,
13714 DSAStack->isCancelRegion());
13715}
13716
13718 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13719 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13720 if (!AStmt)
13721 return StmtError();
13722
13723 CapturedStmt *CS =
13724 setBranchProtectedScope(SemaRef, OMPD_master_taskloop_simd, AStmt);
13725
13726 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13727 OMPLoopBasedDirective::HelperExprs B;
13728 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13729 // define the nested loops number.
13730 unsigned NestedLoopCount =
13731 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13732 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13733 VarsWithImplicitDSA, B);
13734 if (NestedLoopCount == 0)
13735 return StmtError();
13736
13737 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13738 return StmtError();
13739
13740 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13741 // The grainsize clause and num_tasks clause are mutually exclusive and may
13742 // not appear on the same taskloop directive.
13744 {OMPC_grainsize, OMPC_num_tasks}))
13745 return StmtError();
13746 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13747 // If a reduction clause is present on the taskloop directive, the nogroup
13748 // clause must not be specified.
13750 return StmtError();
13752 return StmtError();
13753
13755 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13756}
13757
13759 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13760 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13761 if (!AStmt)
13762 return StmtError();
13763
13764 CapturedStmt *CS =
13765 setBranchProtectedScope(SemaRef, OMPD_masked_taskloop_simd, AStmt);
13766
13767 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13768 OMPLoopBasedDirective::HelperExprs B;
13769 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13770 // define the nested loops number.
13771 unsigned NestedLoopCount =
13772 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13773 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13774 VarsWithImplicitDSA, B);
13775 if (NestedLoopCount == 0)
13776 return StmtError();
13777
13778 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13779 return StmtError();
13780
13781 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13782 // The grainsize clause and num_tasks clause are mutually exclusive and may
13783 // not appear on the same taskloop directive.
13785 {OMPC_grainsize, OMPC_num_tasks}))
13786 return StmtError();
13787 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13788 // If a reduction clause is present on the taskloop directive, the nogroup
13789 // clause must not be specified.
13791 return StmtError();
13793 return StmtError();
13794
13796 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13797}
13798
13800 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13801 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13802 if (!AStmt)
13803 return StmtError();
13804
13805 CapturedStmt *CS =
13806 setBranchProtectedScope(SemaRef, OMPD_parallel_master_taskloop, AStmt);
13807
13808 OMPLoopBasedDirective::HelperExprs B;
13809 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13810 // define the nested loops number.
13811 unsigned NestedLoopCount = checkOpenMPLoop(
13812 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13813 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13814 VarsWithImplicitDSA, B);
13815 if (NestedLoopCount == 0)
13816 return StmtError();
13817
13818 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13819 "omp for loop exprs were not built");
13820
13821 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13822 // The grainsize clause and num_tasks clause are mutually exclusive and may
13823 // not appear on the same taskloop directive.
13825 {OMPC_grainsize, OMPC_num_tasks}))
13826 return StmtError();
13827 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13828 // If a reduction clause is present on the taskloop directive, the nogroup
13829 // clause must not be specified.
13831 return StmtError();
13832
13834 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13835 DSAStack->isCancelRegion());
13836}
13837
13839 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13840 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13841 if (!AStmt)
13842 return StmtError();
13843
13844 CapturedStmt *CS =
13845 setBranchProtectedScope(SemaRef, OMPD_parallel_masked_taskloop, AStmt);
13846
13847 OMPLoopBasedDirective::HelperExprs B;
13848 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13849 // define the nested loops number.
13850 unsigned NestedLoopCount = checkOpenMPLoop(
13851 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13852 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13853 VarsWithImplicitDSA, B);
13854 if (NestedLoopCount == 0)
13855 return StmtError();
13856
13857 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13858 "omp for loop exprs were not built");
13859
13860 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13861 // The grainsize clause and num_tasks clause are mutually exclusive and may
13862 // not appear on the same taskloop directive.
13864 {OMPC_grainsize, OMPC_num_tasks}))
13865 return StmtError();
13866 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13867 // If a reduction clause is present on the taskloop directive, the nogroup
13868 // clause must not be specified.
13870 return StmtError();
13871
13873 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13874 DSAStack->isCancelRegion());
13875}
13876
13878 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13879 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13880 if (!AStmt)
13881 return StmtError();
13882
13884 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13885
13886 OMPLoopBasedDirective::HelperExprs B;
13887 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13888 // define the nested loops number.
13889 unsigned NestedLoopCount = checkOpenMPLoop(
13890 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13891 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13892 VarsWithImplicitDSA, B);
13893 if (NestedLoopCount == 0)
13894 return StmtError();
13895
13896 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13897 return StmtError();
13898
13899 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13900 // The grainsize clause and num_tasks clause are mutually exclusive and may
13901 // not appear on the same taskloop directive.
13903 {OMPC_grainsize, OMPC_num_tasks}))
13904 return StmtError();
13905 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13906 // If a reduction clause is present on the taskloop directive, the nogroup
13907 // clause must not be specified.
13909 return StmtError();
13911 return StmtError();
13912
13914 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13915}
13916
13918 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13919 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13920 if (!AStmt)
13921 return StmtError();
13922
13924 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13925
13926 OMPLoopBasedDirective::HelperExprs B;
13927 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13928 // define the nested loops number.
13929 unsigned NestedLoopCount = checkOpenMPLoop(
13930 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13931 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13932 VarsWithImplicitDSA, B);
13933 if (NestedLoopCount == 0)
13934 return StmtError();
13935
13936 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13937 return StmtError();
13938
13939 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13940 // The grainsize clause and num_tasks clause are mutually exclusive and may
13941 // not appear on the same taskloop directive.
13943 {OMPC_grainsize, OMPC_num_tasks}))
13944 return StmtError();
13945 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13946 // If a reduction clause is present on the taskloop directive, the nogroup
13947 // clause must not be specified.
13949 return StmtError();
13951 return StmtError();
13952
13954 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13955}
13956
13958 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13959 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13960 if (!AStmt)
13961 return StmtError();
13962
13963 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13964 OMPLoopBasedDirective::HelperExprs B;
13965 // In presence of clause 'collapse' with number of loops, it will
13966 // define the nested loops number.
13967 unsigned NestedLoopCount =
13968 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
13969 nullptr /*ordered not a clause on distribute*/, AStmt,
13970 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13971 if (NestedLoopCount == 0)
13972 return StmtError();
13973
13974 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13975 "omp for loop exprs were not built");
13976
13977 SemaRef.setFunctionHasBranchProtectedScope();
13978 auto *DistributeDirective = OMPDistributeDirective::Create(
13979 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13980 return DistributeDirective;
13981}
13982
13984 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13985 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13986 if (!AStmt)
13987 return StmtError();
13988
13989 CapturedStmt *CS =
13990 setBranchProtectedScope(SemaRef, OMPD_distribute_parallel_for, AStmt);
13991
13992 OMPLoopBasedDirective::HelperExprs B;
13993 // In presence of clause 'collapse' with number of loops, it will
13994 // define the nested loops number.
13995 unsigned NestedLoopCount = checkOpenMPLoop(
13996 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13997 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13998 VarsWithImplicitDSA, B);
13999 if (NestedLoopCount == 0)
14000 return StmtError();
14001
14002 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14003 "omp for loop exprs were not built");
14004
14006 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14007 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14008}
14009
14011 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14012 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14013 if (!AStmt)
14014 return StmtError();
14015
14017 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
14018
14019 OMPLoopBasedDirective::HelperExprs B;
14020 // In presence of clause 'collapse' with number of loops, it will
14021 // define the nested loops number.
14022 unsigned NestedLoopCount = checkOpenMPLoop(
14023 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14024 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14025 VarsWithImplicitDSA, B);
14026 if (NestedLoopCount == 0)
14027 return StmtError();
14028
14029 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14030 return StmtError();
14031
14033 return StmtError();
14034
14036 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
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_distribute_simd, AStmt);
14047
14048 OMPLoopBasedDirective::HelperExprs B;
14049 // In presence of clause 'collapse' with number of loops, it will
14050 // define the nested loops number.
14051 unsigned NestedLoopCount =
14052 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
14053 nullptr /*ordered not a clause on distribute*/, CS,
14054 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14055 if (NestedLoopCount == 0)
14056 return StmtError();
14057
14058 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14059 return StmtError();
14060
14062 return StmtError();
14063
14064 return OMPDistributeSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
14065 NestedLoopCount, Clauses, AStmt, B);
14066}
14067
14069 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14070 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14071 if (!AStmt)
14072 return StmtError();
14073
14074 CapturedStmt *CS =
14075 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for_simd, AStmt);
14076
14077 OMPLoopBasedDirective::HelperExprs B;
14078 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14079 // define the nested loops number.
14080 unsigned NestedLoopCount = checkOpenMPLoop(
14081 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
14082 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
14083 VarsWithImplicitDSA, B);
14084 if (NestedLoopCount == 0)
14085 return StmtError();
14086
14087 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14088 return StmtError();
14089
14091 return StmtError();
14092
14094 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14095}
14096
14098 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14099 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14100 if (!AStmt)
14101 return StmtError();
14102
14103 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target_simd, AStmt);
14104
14105 OMPLoopBasedDirective::HelperExprs B;
14106 // In presence of clause 'collapse' with number of loops, it will define the
14107 // nested loops number.
14108 unsigned NestedLoopCount =
14109 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
14110 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
14111 VarsWithImplicitDSA, B);
14112 if (NestedLoopCount == 0)
14113 return StmtError();
14114
14115 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14116 return StmtError();
14117
14119 return StmtError();
14120
14121 return OMPTargetSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
14122 NestedLoopCount, Clauses, AStmt, B);
14123}
14124
14126 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14127 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14128 if (!AStmt)
14129 return StmtError();
14130
14131 CapturedStmt *CS =
14132 setBranchProtectedScope(SemaRef, OMPD_teams_distribute, AStmt);
14133
14134 OMPLoopBasedDirective::HelperExprs B;
14135 // In presence of clause 'collapse' with number of loops, it will
14136 // define the nested loops number.
14137 unsigned NestedLoopCount =
14138 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
14139 nullptr /*ordered not a clause on distribute*/, CS,
14140 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14141 if (NestedLoopCount == 0)
14142 return StmtError();
14143
14144 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14145 "omp teams distribute loop exprs were not built");
14146
14147 DSAStack->setParentTeamsRegionLoc(StartLoc);
14148
14150 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14151}
14152
14154 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14155 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14156 if (!AStmt)
14157 return StmtError();
14158
14159 CapturedStmt *CS =
14160 setBranchProtectedScope(SemaRef, OMPD_teams_distribute_simd, AStmt);
14161
14162 OMPLoopBasedDirective::HelperExprs B;
14163 // In presence of clause 'collapse' with number of loops, it will
14164 // define the nested loops number.
14165 unsigned NestedLoopCount = checkOpenMPLoop(
14166 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14167 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14168 VarsWithImplicitDSA, B);
14169 if (NestedLoopCount == 0)
14170 return StmtError();
14171
14172 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14173 return StmtError();
14174
14176 return StmtError();
14177
14178 DSAStack->setParentTeamsRegionLoc(StartLoc);
14179
14181 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14182}
14183
14185 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14186 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14187 if (!AStmt)
14188 return StmtError();
14189
14191 SemaRef, OMPD_teams_distribute_parallel_for_simd, 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_teams_distribute_parallel_for_simd, 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 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14204 return StmtError();
14205
14207 return StmtError();
14208
14209 DSAStack->setParentTeamsRegionLoc(StartLoc);
14210
14212 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14213}
14214
14216 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14217 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14218 if (!AStmt)
14219 return StmtError();
14220
14222 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
14223
14224 OMPLoopBasedDirective::HelperExprs B;
14225 // In presence of clause 'collapse' with number of loops, it will
14226 // define the nested loops number.
14227 unsigned NestedLoopCount = checkOpenMPLoop(
14228 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14229 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14230 VarsWithImplicitDSA, B);
14231
14232 if (NestedLoopCount == 0)
14233 return StmtError();
14234
14235 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14236 "omp for loop exprs were not built");
14237
14238 DSAStack->setParentTeamsRegionLoc(StartLoc);
14239
14241 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14242 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14243}
14244
14246 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14247 SourceLocation EndLoc) {
14248 if (!AStmt)
14249 return StmtError();
14250
14251 setBranchProtectedScope(SemaRef, OMPD_target_teams, AStmt);
14252
14253 const OMPClause *BareClause = nullptr;
14254 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) &&
14255 hasClauses(Clauses, OMPC_thread_limit);
14256 bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) {
14257 BareClause = C;
14258 return C->getClauseKind() == OMPC_ompx_bare;
14259 });
14260
14261 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14262 Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
14263 return StmtError();
14264 }
14265
14266 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
14267 unsigned DiagNo = HasBareClause
14268 ? diag::err_ompx_more_than_three_expr_not_allowed
14269 : diag::err_omp_multi_expr_not_allowed;
14270 if (!checkNumExprsInClause<OMPNumTeamsClause>(*this, Clauses,
14271 ClauseMaxNumExprs, DiagNo) ||
14273 ClauseMaxNumExprs, DiagNo))
14274 return StmtError();
14275
14276 return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc,
14277 Clauses, AStmt);
14278}
14279
14281 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14282 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14283 if (!AStmt)
14284 return StmtError();
14285
14287 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14289 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14290 return StmtError();
14291
14292 CapturedStmt *CS =
14293 setBranchProtectedScope(SemaRef, OMPD_target_teams_distribute, AStmt);
14294
14295 OMPLoopBasedDirective::HelperExprs B;
14296 // In presence of clause 'collapse' with number of loops, it will
14297 // define the nested loops number.
14298 unsigned NestedLoopCount = checkOpenMPLoop(
14299 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14300 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14301 VarsWithImplicitDSA, B);
14302 if (NestedLoopCount == 0)
14303 return StmtError();
14304
14305 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14306 "omp target teams distribute loop exprs were not built");
14307
14309 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14310}
14311
14313 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14314 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14315 if (!AStmt)
14316 return StmtError();
14317
14319 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14321 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14322 return StmtError();
14323
14325 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14326
14327 OMPLoopBasedDirective::HelperExprs B;
14328 // In presence of clause 'collapse' with number of loops, it will
14329 // define the nested loops number.
14330 unsigned NestedLoopCount = checkOpenMPLoop(
14331 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14332 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14333 VarsWithImplicitDSA, B);
14334 if (NestedLoopCount == 0)
14335 return StmtError();
14336
14337 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14338 return StmtError();
14339
14341 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14342 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14343}
14344
14346 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14347 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14348 if (!AStmt)
14349 return StmtError();
14350
14352 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14354 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14355 return StmtError();
14356
14358 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14359
14360 OMPLoopBasedDirective::HelperExprs B;
14361 // In presence of clause 'collapse' with number of loops, it will
14362 // define the nested loops number.
14363 unsigned NestedLoopCount =
14364 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14365 getCollapseNumberExpr(Clauses),
14366 nullptr /*ordered not a clause on distribute*/, CS,
14367 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14368 if (NestedLoopCount == 0)
14369 return StmtError();
14370
14371 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14372 return StmtError();
14373
14375 return StmtError();
14376
14378 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14379}
14380
14382 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14383 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14384 if (!AStmt)
14385 return StmtError();
14386
14388 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14390 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14391 return StmtError();
14392
14394 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14395
14396 OMPLoopBasedDirective::HelperExprs B;
14397 // In presence of clause 'collapse' with number of loops, it will
14398 // define the nested loops number.
14399 unsigned NestedLoopCount = checkOpenMPLoop(
14400 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14401 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14402 VarsWithImplicitDSA, B);
14403 if (NestedLoopCount == 0)
14404 return StmtError();
14405
14406 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14407 return StmtError();
14408
14410 return StmtError();
14411
14413 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14414}
14415
14416/// Updates OriginalInits by checking Transform against loop transformation
14417/// directives and appending their pre-inits if a match is found.
14419 SmallVectorImpl<Stmt *> &PreInits) {
14420 Stmt *Dir = Transform->getDirective();
14421 switch (Dir->getStmtClass()) {
14422#define STMT(CLASS, PARENT)
14423#define ABSTRACT_STMT(CLASS)
14424#define COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT) \
14425 case Stmt::CLASS##Class: \
14426 appendFlattenedStmtList(PreInits, \
14427 static_cast<const CLASS *>(Dir)->getPreInits()); \
14428 break;
14429#define OMPCANONICALLOOPNESTTRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14430 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14431#define OMPCANONICALLOOPSEQUENCETRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14432 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14433#include "clang/AST/StmtNodes.inc"
14434#undef COMMON_OMP_LOOP_TRANSFORMATION
14435 default:
14436 llvm_unreachable("Not a loop transformation");
14437 }
14438}
14439
14440bool SemaOpenMP::checkTransformableLoopNest(
14441 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14443 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *>> &OriginalInits) {
14444 OriginalInits.emplace_back();
14445 bool Result = OMPLoopBasedDirective::doForAllLoops(
14446 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14447 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14448 Stmt *CurStmt) {
14449 VarsWithInheritedDSAType TmpDSA;
14450 unsigned SingleNumLoops =
14451 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14452 TmpDSA, LoopHelpers[Cnt]);
14453 if (SingleNumLoops == 0)
14454 return true;
14455 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14456 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14457 OriginalInits.back().push_back(For->getInit());
14458 Body = For->getBody();
14459 } else {
14460 assert(isa<CXXForRangeStmt>(CurStmt) &&
14461 "Expected canonical for or range-based for loops.");
14462 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14463 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14464 Body = CXXFor->getBody();
14465 }
14466 OriginalInits.emplace_back();
14467 return false;
14468 },
14469 [&OriginalInits](OMPLoopTransformationDirective *Transform) {
14470 updatePreInits(Transform, OriginalInits.back());
14471 });
14472 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14473 OriginalInits.pop_back();
14474 return Result;
14475}
14476
14477/// Counts the total number of OpenMP canonical nested loops, including the
14478/// outermost loop (the original loop). PRECONDITION of this visitor is that it
14479/// must be invoked from the original loop to be analyzed. The traversal stops
14480/// for Decl's and Expr's given that they may contain inner loops that must not
14481/// be counted.
14482///
14483/// Example AST structure for the code:
14484///
14485/// int main() {
14486/// #pragma omp fuse
14487/// {
14488/// for (int i = 0; i < 100; i++) { <-- Outer loop
14489/// []() {
14490/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (1)
14491/// };
14492/// for(int j = 0; j < 5; ++j) {} <-- Inner loop
14493/// }
14494/// for (int r = 0; i < 100; i++) { <-- Outer loop
14495/// struct LocalClass {
14496/// void bar() {
14497/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (2)
14498/// }
14499/// };
14500/// for(int k = 0; k < 10; ++k) {} <-- Inner loop
14501/// {x = 5; for(k = 0; k < 10; ++k) x += k; x}; <-- NOT A LOOP (3)
14502/// }
14503/// }
14504/// }
14505/// (1) because in a different function (here: a lambda)
14506/// (2) because in a different function (here: class method)
14507/// (3) because considered to be intervening-code of non-perfectly nested loop
14508/// Result: Loop 'i' contains 2 loops, Loop 'r' also contains 2 loops.
14510private:
14511 unsigned NestedLoopCount = 0;
14512
14513public:
14514 explicit NestedLoopCounterVisitor() = default;
14515
14516 unsigned getNestedLoopCount() const { return NestedLoopCount; }
14517
14518 bool VisitForStmt(ForStmt *FS) override {
14519 ++NestedLoopCount;
14520 return true;
14521 }
14522
14524 ++NestedLoopCount;
14525 return true;
14526 }
14527
14528 bool TraverseStmt(Stmt *S) override {
14529 if (!S)
14530 return true;
14531
14532 // Skip traversal of all expressions, including special cases like
14533 // LambdaExpr, StmtExpr, BlockExpr, and RequiresExpr. These expressions
14534 // may contain inner statements (and even loops), but they are not part
14535 // of the syntactic body of the surrounding loop structure.
14536 // Therefore must not be counted.
14537 if (isa<Expr>(S))
14538 return true;
14539
14540 // Only recurse into CompoundStmt (block {}) and loop bodies.
14543 }
14544
14545 // Stop traversal of the rest of statements, that break perfect
14546 // loop nesting, such as control flow (IfStmt, SwitchStmt...).
14547 return true;
14548 }
14549
14550 bool TraverseDecl(Decl *D) override {
14551 // Stop in the case of finding a declaration, it is not important
14552 // in order to find nested loops (Possible CXXRecordDecl, RecordDecl,
14553 // FunctionDecl...).
14554 return true;
14555 }
14556};
14557
14558bool SemaOpenMP::analyzeLoopSequence(Stmt *LoopSeqStmt,
14559 LoopSequenceAnalysis &SeqAnalysis,
14560 ASTContext &Context,
14561 OpenMPDirectiveKind Kind) {
14563 // Helper Lambda to handle storing initialization and body statements for
14564 // both ForStmt and CXXForRangeStmt.
14565 auto StoreLoopStatements = [](LoopAnalysis &Analysis, Stmt *LoopStmt) {
14566 if (auto *For = dyn_cast<ForStmt>(LoopStmt)) {
14567 Analysis.OriginalInits.push_back(For->getInit());
14568 Analysis.TheForStmt = For;
14569 } else {
14570 auto *CXXFor = cast<CXXForRangeStmt>(LoopStmt);
14571 Analysis.OriginalInits.push_back(CXXFor->getBeginStmt());
14572 Analysis.TheForStmt = CXXFor;
14573 }
14574 };
14575
14576 // Helper lambda functions to encapsulate the processing of different
14577 // derivations of the canonical loop sequence grammar
14578 // Modularized code for handling loop generation and transformations.
14579 auto AnalyzeLoopGeneration = [&](Stmt *Child) {
14580 auto *LoopTransform = cast<OMPLoopTransformationDirective>(Child);
14581 Stmt *TransformedStmt = LoopTransform->getTransformedStmt();
14582 unsigned NumGeneratedTopLevelLoops =
14583 LoopTransform->getNumGeneratedTopLevelLoops();
14584 // Handle the case where transformed statement is not available due to
14585 // dependent contexts
14586 if (!TransformedStmt) {
14587 if (NumGeneratedTopLevelLoops > 0) {
14588 SeqAnalysis.LoopSeqSize += NumGeneratedTopLevelLoops;
14589 return true;
14590 }
14591 // Unroll full (0 loops produced)
14592 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14593 << 0 << getOpenMPDirectiveName(Kind);
14594 return false;
14595 }
14596 // Handle loop transformations with multiple loop nests
14597 // Unroll full
14598 if (!NumGeneratedTopLevelLoops) {
14599 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14600 << 0 << getOpenMPDirectiveName(Kind);
14601 return false;
14602 }
14603 // Loop transformatons such as split or loopranged fuse
14604 if (NumGeneratedTopLevelLoops > 1) {
14605 // Get the preinits related to this loop sequence generating
14606 // loop transformation (i.e loopranged fuse, split...)
14607 // These preinits differ slightly from regular inits/pre-inits related
14608 // to single loop generating loop transformations (interchange, unroll)
14609 // given that they are not bounded to a particular loop nest
14610 // so they need to be treated independently
14611 updatePreInits(LoopTransform, SeqAnalysis.LoopSequencePreInits);
14612 return analyzeLoopSequence(TransformedStmt, SeqAnalysis, Context, Kind);
14613 }
14614 // Vast majority: (Tile, Unroll, Stripe, Reverse, Interchange, Fuse all)
14615 // Process the transformed loop statement
14616 LoopAnalysis &NewTransformedSingleLoop =
14617 SeqAnalysis.Loops.emplace_back(Child);
14618 unsigned IsCanonical = checkOpenMPLoop(
14619 Kind, nullptr, nullptr, TransformedStmt, SemaRef, *DSAStack, TmpDSA,
14620 NewTransformedSingleLoop.HelperExprs);
14621
14622 if (!IsCanonical)
14623 return false;
14624
14625 StoreLoopStatements(NewTransformedSingleLoop, TransformedStmt);
14626 updatePreInits(LoopTransform, NewTransformedSingleLoop.TransformsPreInits);
14627
14628 SeqAnalysis.LoopSeqSize++;
14629 return true;
14630 };
14631
14632 // Modularized code for handling regular canonical loops.
14633 auto AnalyzeRegularLoop = [&](Stmt *Child) {
14634 LoopAnalysis &NewRegularLoop = SeqAnalysis.Loops.emplace_back(Child);
14635 unsigned IsCanonical =
14636 checkOpenMPLoop(Kind, nullptr, nullptr, Child, SemaRef, *DSAStack,
14637 TmpDSA, NewRegularLoop.HelperExprs);
14638
14639 if (!IsCanonical)
14640 return false;
14641
14642 StoreLoopStatements(NewRegularLoop, Child);
14643 NestedLoopCounterVisitor NLCV;
14644 NLCV.TraverseStmt(Child);
14645 return true;
14646 };
14647
14648 // High level grammar validation.
14649 for (Stmt *Child : LoopSeqStmt->children()) {
14650 if (!Child)
14651 continue;
14652 // Skip over non-loop-sequence statements.
14653 if (!LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14654 Child = Child->IgnoreContainers();
14655 // Ignore empty compound statement.
14656 if (!Child)
14657 continue;
14658 // In the case of a nested loop sequence ignoring containers would not
14659 // be enough, a recurisve transversal of the loop sequence is required.
14660 if (isa<CompoundStmt>(Child)) {
14661 if (!analyzeLoopSequence(Child, SeqAnalysis, Context, Kind))
14662 return false;
14663 // Already been treated, skip this children
14664 continue;
14665 }
14666 }
14667 // Regular loop sequence handling.
14668 if (LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14669 if (LoopAnalysis::isLoopTransformation(Child)) {
14670 if (!AnalyzeLoopGeneration(Child))
14671 return false;
14672 // AnalyzeLoopGeneration updates SeqAnalysis.LoopSeqSize accordingly.
14673 } else {
14674 if (!AnalyzeRegularLoop(Child))
14675 return false;
14676 SeqAnalysis.LoopSeqSize++;
14677 }
14678 } else {
14679 // Report error for invalid statement inside canonical loop sequence.
14680 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14681 << 0 << getOpenMPDirectiveName(Kind);
14682 return false;
14683 }
14684 }
14685 return true;
14686}
14687
14688bool SemaOpenMP::checkTransformableLoopSequence(
14689 OpenMPDirectiveKind Kind, Stmt *AStmt, LoopSequenceAnalysis &SeqAnalysis,
14690 ASTContext &Context) {
14691 // Following OpenMP 6.0 API Specification, a Canonical Loop Sequence follows
14692 // the grammar:
14693 //
14694 // canonical-loop-sequence:
14695 // {
14696 // loop-sequence+
14697 // }
14698 // where loop-sequence can be any of the following:
14699 // 1. canonical-loop-sequence
14700 // 2. loop-nest
14701 // 3. loop-sequence-generating-construct (i.e OMPLoopTransformationDirective)
14702 //
14703 // To recognise and traverse this structure the helper function
14704 // analyzeLoopSequence serves as the recurisve entry point
14705 // and tries to match the input AST to the canonical loop sequence grammar
14706 // structure. This function will perform both a semantic and syntactical
14707 // analysis of the given statement according to OpenMP 6.0 definition of
14708 // the aforementioned canonical loop sequence.
14709
14710 // We expect an outer compound statement.
14711 if (!isa<CompoundStmt>(AStmt)) {
14712 Diag(AStmt->getBeginLoc(), diag::err_omp_not_a_loop_sequence)
14713 << getOpenMPDirectiveName(Kind);
14714 return false;
14715 }
14716
14717 // Recursive entry point to process the main loop sequence
14718 if (!analyzeLoopSequence(AStmt, SeqAnalysis, Context, Kind))
14719 return false;
14720
14721 // Diagnose an empty loop sequence.
14722 if (!SeqAnalysis.LoopSeqSize) {
14723 Diag(AStmt->getBeginLoc(), diag::err_omp_empty_loop_sequence)
14724 << getOpenMPDirectiveName(Kind);
14725 return false;
14726 }
14727 return true;
14728}
14729
14730/// Add preinit statements that need to be propagated from the selected loop.
14731static void addLoopPreInits(ASTContext &Context,
14732 OMPLoopBasedDirective::HelperExprs &LoopHelper,
14733 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
14734 SmallVectorImpl<Stmt *> &PreInits) {
14735
14736 // For range-based for-statements, ensure that their syntactic sugar is
14737 // executed by adding them as pre-init statements.
14738 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14739 Stmt *RangeInit = CXXRangeFor->getInit();
14740 if (RangeInit)
14741 PreInits.push_back(RangeInit);
14742
14743 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14744 PreInits.push_back(new (Context) DeclStmt(RangeStmt->getDeclGroup(),
14745 RangeStmt->getBeginLoc(),
14746 RangeStmt->getEndLoc()));
14747
14748 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14749 PreInits.push_back(new (Context) DeclStmt(RangeEnd->getDeclGroup(),
14750 RangeEnd->getBeginLoc(),
14751 RangeEnd->getEndLoc()));
14752 }
14753
14754 llvm::append_range(PreInits, OriginalInit);
14755
14756 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
14757 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
14758 PreInits.push_back(new (Context) DeclStmt(
14759 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14760 }
14761
14762 // Gather declarations for the data members used as counters.
14763 for (Expr *CounterRef : LoopHelper.Counters) {
14764 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14765 if (isa<OMPCapturedExprDecl>(CounterDecl))
14766 PreInits.push_back(new (Context) DeclStmt(
14767 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
14768 }
14769}
14770
14771/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
14772/// loop of a construct.
14773static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) {
14774 size_t NumLoops = LoopStmts.size();
14775 OMPLoopBasedDirective::doForAllLoops(
14776 AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
14777 [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
14778 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
14779 LoopStmts[Cnt] = CurStmt;
14780 return false;
14781 });
14782 assert(!is_contained(LoopStmts, nullptr) &&
14783 "Expecting a loop statement for each affected loop");
14784}
14785
14786/// Build and return a DeclRefExpr for the floor induction variable using the
14787/// SemaRef and the provided parameters.
14788static Expr *makeFloorIVRef(Sema &SemaRef, ArrayRef<VarDecl *> FloorIndVars,
14789 int I, QualType IVTy, DeclRefExpr *OrigCntVar) {
14790 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14791 OrigCntVar->getExprLoc());
14792}
14793
14795 Stmt *AStmt,
14796 SourceLocation StartLoc,
14797 SourceLocation EndLoc) {
14798 ASTContext &Context = getASTContext();
14799 Scope *CurScope = SemaRef.getCurScope();
14800
14801 const auto *SizesClause =
14802 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14803 if (!SizesClause ||
14804 llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; }))
14805 return StmtError();
14806 unsigned NumLoops = SizesClause->getNumSizes();
14807
14808 // Empty statement should only be possible if there already was an error.
14809 if (!AStmt)
14810 return StmtError();
14811
14812 // Verify and diagnose loop nest.
14814 Stmt *Body = nullptr;
14815 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
14816 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14817 OriginalInits))
14818 return StmtError();
14819
14820 // Delay tiling to when template is completely instantiated.
14821 if (SemaRef.CurContext->isDependentContext())
14822 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14823 NumLoops, AStmt, nullptr, nullptr);
14824
14825 assert(LoopHelpers.size() == NumLoops &&
14826 "Expecting loop iteration space dimensionality to match number of "
14827 "affected loops");
14828 assert(OriginalInits.size() == NumLoops &&
14829 "Expecting loop iteration space dimensionality to match number of "
14830 "affected loops");
14831
14832 // Collect all affected loop statements.
14833 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14834 collectLoopStmts(AStmt, LoopStmts);
14835
14836 SmallVector<Stmt *, 4> PreInits;
14837 CaptureVars CopyTransformer(SemaRef);
14838
14839 // Create iteration variables for the generated loops.
14840 SmallVector<VarDecl *, 4> FloorIndVars;
14841 SmallVector<VarDecl *, 4> TileIndVars;
14842 FloorIndVars.resize(NumLoops);
14843 TileIndVars.resize(NumLoops);
14844 for (unsigned I = 0; I < NumLoops; ++I) {
14845 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14846
14847 assert(LoopHelper.Counters.size() == 1 &&
14848 "Expect single-dimensional loop iteration space");
14849 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14850 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14851 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14852 QualType CntTy = IterVarRef->getType();
14853
14854 // Iteration variable for the floor (i.e. outer) loop.
14855 {
14856 std::string FloorCntName =
14857 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14858 VarDecl *FloorCntDecl =
14859 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14860 FloorIndVars[I] = FloorCntDecl;
14861 }
14862
14863 // Iteration variable for the tile (i.e. inner) loop.
14864 {
14865 std::string TileCntName =
14866 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14867
14868 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14869 // used by the expressions to derive the original iteration variable's
14870 // value from the logical iteration number.
14871 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14872 TileCntDecl->setDeclName(
14873 &SemaRef.PP.getIdentifierTable().get(TileCntName));
14874 TileIndVars[I] = TileCntDecl;
14875 }
14876
14877 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
14878 PreInits);
14879 }
14880
14881 // Once the original iteration values are set, append the innermost body.
14882 Stmt *Inner = Body;
14883
14884 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
14885 SizesClause, CurScope](int I) -> Expr * {
14886 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14887
14888 if (DimTileSizeExpr->containsErrors())
14889 return nullptr;
14890
14891 if (isa<ConstantExpr>(DimTileSizeExpr))
14892 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14893
14894 // When the tile size is not a constant but a variable, it is possible to
14895 // pass non-positive numbers. For instance:
14896 // \code{c}
14897 // int a = 0;
14898 // #pragma omp tile sizes(a)
14899 // for (int i = 0; i < 42; ++i)
14900 // body(i);
14901 // \endcode
14902 // Although there is no meaningful interpretation of the tile size, the body
14903 // should still be executed 42 times to avoid surprises. To preserve the
14904 // invariant that every loop iteration is executed exactly once and not
14905 // cause an infinite loop, apply a minimum tile size of one.
14906 // Build expr:
14907 // \code{c}
14908 // (TS <= 0) ? 1 : TS
14909 // \endcode
14910 QualType DimTy = DimTileSizeExpr->getType();
14911 uint64_t DimWidth = Context.getTypeSize(DimTy);
14913 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14914 IntegerLiteral *One =
14915 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
14916 Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
14917 CurScope, {}, BO_LE,
14918 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
14919 Expr *MinOne = new (Context) ConditionalOperator(
14920 Cond, {}, One, {},
14921 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14923 return MinOne;
14924 };
14925
14926 // Create tile loops from the inside to the outside.
14927 for (int I = NumLoops - 1; I >= 0; --I) {
14928 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14929 Expr *NumIterations = LoopHelper.NumIterations;
14930 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14931 QualType IVTy = NumIterations->getType();
14932 Stmt *LoopStmt = LoopStmts[I];
14933
14934 // Commonly used variables. One of the constraints of an AST is that every
14935 // node object must appear at most once, hence we define a lambda that
14936 // creates a new AST node at every use.
14937 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
14938 OrigCntVar]() {
14939 return buildDeclRefExpr(SemaRef, TileIndVars[I], IVTy,
14940 OrigCntVar->getExprLoc());
14941 };
14942
14943 // For init-statement: auto .tile.iv = .floor.iv
14944 SemaRef.AddInitializerToDecl(
14945 TileIndVars[I],
14946 SemaRef
14947 .DefaultLvalueConversion(
14948 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
14949 .get(),
14950 /*DirectInit=*/false);
14951 Decl *CounterDecl = TileIndVars[I];
14952 StmtResult InitStmt = new (Context)
14953 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14954 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14955 if (!InitStmt.isUsable())
14956 return StmtError();
14957
14958 // For cond-expression:
14959 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
14960 Expr *DimTileSize = MakeDimTileSize(I);
14961 if (!DimTileSize)
14962 return StmtError();
14963 ExprResult EndOfTile = SemaRef.BuildBinOp(
14964 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14965 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14966 DimTileSize);
14967 if (!EndOfTile.isUsable())
14968 return StmtError();
14969 ExprResult IsPartialTile =
14970 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14971 NumIterations, EndOfTile.get());
14972 if (!IsPartialTile.isUsable())
14973 return StmtError();
14974 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
14975 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14976 IsPartialTile.get(), NumIterations, EndOfTile.get());
14977 if (!MinTileAndIterSpace.isUsable())
14978 return StmtError();
14979 ExprResult CondExpr =
14980 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14981 MakeTileIVRef(), MinTileAndIterSpace.get());
14982 if (!CondExpr.isUsable())
14983 return StmtError();
14984
14985 // For incr-statement: ++.tile.iv
14986 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14987 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
14988 if (!IncrStmt.isUsable())
14989 return StmtError();
14990
14991 // Statements to set the original iteration variable's value from the
14992 // logical iteration number.
14993 // Generated for loop is:
14994 // \code
14995 // Original_for_init;
14996 // for (auto .tile.iv = .floor.iv;
14997 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
14998 // ++.tile.iv) {
14999 // Original_Body;
15000 // Original_counter_update;
15001 // }
15002 // \endcode
15003 // FIXME: If the innermost body is an loop itself, inserting these
15004 // statements stops it being recognized as a perfectly nested loop (e.g.
15005 // for applying tiling again). If this is the case, sink the expressions
15006 // further into the inner loop.
15007 SmallVector<Stmt *, 4> BodyParts;
15008 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15009 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15010 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15011 BodyParts.push_back(Inner);
15012 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15013 Inner->getBeginLoc(), Inner->getEndLoc());
15014 Inner = new (Context)
15015 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15016 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15017 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15018 }
15019
15020 // Create floor loops from the inside to the outside.
15021 for (int I = NumLoops - 1; I >= 0; --I) {
15022 auto &LoopHelper = LoopHelpers[I];
15023 Expr *NumIterations = LoopHelper.NumIterations;
15024 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15025 QualType IVTy = NumIterations->getType();
15026
15027 // For init-statement: auto .floor.iv = 0
15028 SemaRef.AddInitializerToDecl(
15029 FloorIndVars[I],
15030 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15031 /*DirectInit=*/false);
15032 Decl *CounterDecl = FloorIndVars[I];
15033 StmtResult InitStmt = new (Context)
15034 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15035 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15036 if (!InitStmt.isUsable())
15037 return StmtError();
15038
15039 // For cond-expression: .floor.iv < NumIterations
15040 ExprResult CondExpr = SemaRef.BuildBinOp(
15041 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15042 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15043 NumIterations);
15044 if (!CondExpr.isUsable())
15045 return StmtError();
15046
15047 // For incr-statement: .floor.iv += DimTileSize
15048 Expr *DimTileSize = MakeDimTileSize(I);
15049 if (!DimTileSize)
15050 return StmtError();
15051 ExprResult IncrStmt = SemaRef.BuildBinOp(
15052 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15053 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15054 DimTileSize);
15055 if (!IncrStmt.isUsable())
15056 return StmtError();
15057
15058 Inner = new (Context)
15059 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15060 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15061 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15062 }
15063
15064 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
15065 AStmt, Inner,
15066 buildPreInits(Context, PreInits));
15067}
15068
15070 Stmt *AStmt,
15071 SourceLocation StartLoc,
15072 SourceLocation EndLoc) {
15073 ASTContext &Context = getASTContext();
15074 Scope *CurScope = SemaRef.getCurScope();
15075
15076 const auto *SizesClause =
15077 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
15078 if (!SizesClause ||
15079 llvm::any_of(SizesClause->getSizesRefs(), [](const Expr *SizeExpr) {
15080 return !SizeExpr || SizeExpr->containsErrors();
15081 }))
15082 return StmtError();
15083 unsigned NumLoops = SizesClause->getNumSizes();
15084
15085 // Empty statement should only be possible if there already was an error.
15086 if (!AStmt)
15087 return StmtError();
15088
15089 // Verify and diagnose loop nest.
15091 Stmt *Body = nullptr;
15092 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
15093 if (!checkTransformableLoopNest(OMPD_stripe, AStmt, NumLoops, LoopHelpers,
15094 Body, OriginalInits))
15095 return StmtError();
15096
15097 // Delay striping to when template is completely instantiated.
15098 if (SemaRef.CurContext->isDependentContext())
15099 return OMPStripeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15100 NumLoops, AStmt, nullptr, nullptr);
15101
15102 assert(LoopHelpers.size() == NumLoops &&
15103 "Expecting loop iteration space dimensionality to match number of "
15104 "affected loops");
15105 assert(OriginalInits.size() == NumLoops &&
15106 "Expecting loop iteration space dimensionality to match number of "
15107 "affected loops");
15108
15109 // Collect all affected loop statements.
15110 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15111 collectLoopStmts(AStmt, LoopStmts);
15112
15113 SmallVector<Stmt *, 4> PreInits;
15114 CaptureVars CopyTransformer(SemaRef);
15115
15116 // Create iteration variables for the generated loops.
15117 SmallVector<VarDecl *, 4> FloorIndVars;
15118 SmallVector<VarDecl *, 4> StripeIndVars;
15119 FloorIndVars.resize(NumLoops);
15120 StripeIndVars.resize(NumLoops);
15121 for (unsigned I : llvm::seq<unsigned>(NumLoops)) {
15122 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15123
15124 assert(LoopHelper.Counters.size() == 1 &&
15125 "Expect single-dimensional loop iteration space");
15126 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15127 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15128 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15129 QualType CntTy = IterVarRef->getType();
15130
15131 // Iteration variable for the stripe (i.e. outer) loop.
15132 {
15133 std::string FloorCntName =
15134 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15135 VarDecl *FloorCntDecl =
15136 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
15137 FloorIndVars[I] = FloorCntDecl;
15138 }
15139
15140 // Iteration variable for the stripe (i.e. inner) loop.
15141 {
15142 std::string StripeCntName =
15143 (Twine(".stripe_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15144
15145 // Reuse the iteration variable created by checkOpenMPLoop. It is also
15146 // used by the expressions to derive the original iteration variable's
15147 // value from the logical iteration number.
15148 auto *StripeCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15149 StripeCntDecl->setDeclName(
15150 &SemaRef.PP.getIdentifierTable().get(StripeCntName));
15151 StripeIndVars[I] = StripeCntDecl;
15152 }
15153
15154 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
15155 PreInits);
15156 }
15157
15158 // Once the original iteration values are set, append the innermost body.
15159 Stmt *Inner = Body;
15160
15161 auto MakeDimStripeSize = [&](int I) -> Expr * {
15162 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
15163 if (isa<ConstantExpr>(DimStripeSizeExpr))
15164 return AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr));
15165
15166 // When the stripe size is not a constant but a variable, it is possible to
15167 // pass non-positive numbers. For instance:
15168 // \code{c}
15169 // int a = 0;
15170 // #pragma omp stripe sizes(a)
15171 // for (int i = 0; i < 42; ++i)
15172 // body(i);
15173 // \endcode
15174 // Although there is no meaningful interpretation of the stripe size, the
15175 // body should still be executed 42 times to avoid surprises. To preserve
15176 // the invariant that every loop iteration is executed exactly once and not
15177 // cause an infinite loop, apply a minimum stripe size of one.
15178 // Build expr:
15179 // \code{c}
15180 // (TS <= 0) ? 1 : TS
15181 // \endcode
15182 QualType DimTy = DimStripeSizeExpr->getType();
15183 uint64_t DimWidth = Context.getTypeSize(DimTy);
15185 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
15186 IntegerLiteral *One =
15187 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
15188 Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
15189 CurScope, {}, BO_LE,
15190 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), Zero));
15191 Expr *MinOne = new (Context) ConditionalOperator(
15192 Cond, {}, One, {},
15193 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), DimTy,
15195 return MinOne;
15196 };
15197
15198 // Create stripe loops from the inside to the outside.
15199 for (int I = NumLoops - 1; I >= 0; --I) {
15200 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15201 Expr *NumIterations = LoopHelper.NumIterations;
15202 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15203 QualType IVTy = NumIterations->getType();
15204 Stmt *LoopStmt = LoopStmts[I];
15205
15206 // For init-statement: auto .stripe.iv = .floor.iv
15207 SemaRef.AddInitializerToDecl(
15208 StripeIndVars[I],
15209 SemaRef
15210 .DefaultLvalueConversion(
15211 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
15212 .get(),
15213 /*DirectInit=*/false);
15214 Decl *CounterDecl = StripeIndVars[I];
15215 StmtResult InitStmt = new (Context)
15216 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15217 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15218 if (!InitStmt.isUsable())
15219 return StmtError();
15220
15221 // For cond-expression:
15222 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations)
15223 ExprResult EndOfStripe = SemaRef.BuildBinOp(
15224 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15225 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15226 MakeDimStripeSize(I));
15227 if (!EndOfStripe.isUsable())
15228 return StmtError();
15229 ExprResult IsPartialStripe =
15230 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15231 NumIterations, EndOfStripe.get());
15232 if (!IsPartialStripe.isUsable())
15233 return StmtError();
15234 ExprResult MinStripeAndIterSpace = SemaRef.ActOnConditionalOp(
15235 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15236 IsPartialStripe.get(), NumIterations, EndOfStripe.get());
15237 if (!MinStripeAndIterSpace.isUsable())
15238 return StmtError();
15239 ExprResult CondExpr = SemaRef.BuildBinOp(
15240 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15241 makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar),
15242 MinStripeAndIterSpace.get());
15243 if (!CondExpr.isUsable())
15244 return StmtError();
15245
15246 // For incr-statement: ++.stripe.iv
15247 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15248 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc,
15249 makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar));
15250 if (!IncrStmt.isUsable())
15251 return StmtError();
15252
15253 // Statements to set the original iteration variable's value from the
15254 // logical iteration number.
15255 // Generated for loop is:
15256 // \code
15257 // Original_for_init;
15258 // for (auto .stripe.iv = .floor.iv;
15259 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations);
15260 // ++.stripe.iv) {
15261 // Original_Body;
15262 // Original_counter_update;
15263 // }
15264 // \endcode
15265 // FIXME: If the innermost body is a loop itself, inserting these
15266 // statements stops it being recognized as a perfectly nested loop (e.g.
15267 // for applying another loop transformation). If this is the case, sink the
15268 // expressions further into the inner loop.
15269 SmallVector<Stmt *, 4> BodyParts;
15270 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15271 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15272 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15273 BodyParts.push_back(Inner);
15274 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15275 Inner->getBeginLoc(), Inner->getEndLoc());
15276 Inner = new (Context)
15277 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15278 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15279 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15280 }
15281
15282 // Create grid loops from the inside to the outside.
15283 for (int I = NumLoops - 1; I >= 0; --I) {
15284 auto &LoopHelper = LoopHelpers[I];
15285 Expr *NumIterations = LoopHelper.NumIterations;
15286 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15287 QualType IVTy = NumIterations->getType();
15288
15289 // For init-statement: auto .grid.iv = 0
15290 SemaRef.AddInitializerToDecl(
15291 FloorIndVars[I],
15292 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15293 /*DirectInit=*/false);
15294 Decl *CounterDecl = FloorIndVars[I];
15295 StmtResult InitStmt = new (Context)
15296 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15297 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15298 if (!InitStmt.isUsable())
15299 return StmtError();
15300
15301 // For cond-expression: .floor.iv < NumIterations
15302 ExprResult CondExpr = SemaRef.BuildBinOp(
15303 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15304 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15305 NumIterations);
15306 if (!CondExpr.isUsable())
15307 return StmtError();
15308
15309 // For incr-statement: .floor.iv += DimStripeSize
15310 ExprResult IncrStmt = SemaRef.BuildBinOp(
15311 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15312 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15313 MakeDimStripeSize(I));
15314 if (!IncrStmt.isUsable())
15315 return StmtError();
15316
15317 Inner = new (Context)
15318 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15319 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15320 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15321 }
15322
15323 return OMPStripeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15324 NumLoops, AStmt, Inner,
15325 buildPreInits(Context, PreInits));
15326}
15327
15329 Stmt *AStmt,
15330 SourceLocation StartLoc,
15331 SourceLocation EndLoc) {
15332 ASTContext &Context = getASTContext();
15333 Scope *CurScope = SemaRef.getCurScope();
15334 // Empty statement should only be possible if there already was an error.
15335 if (!AStmt)
15336 return StmtError();
15337
15339 {OMPC_partial, OMPC_full}))
15340 return StmtError();
15341
15342 const OMPFullClause *FullClause =
15343 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15344 const OMPPartialClause *PartialClause =
15345 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15346 assert(!(FullClause && PartialClause) &&
15347 "mutual exclusivity must have been checked before");
15348
15349 constexpr unsigned NumLoops = 1;
15350 Stmt *Body = nullptr;
15352 NumLoops);
15353 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
15354 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15355 Body, OriginalInits))
15356 return StmtError();
15357
15358 unsigned NumGeneratedTopLevelLoops = PartialClause ? 1 : 0;
15359
15360 // Delay unrolling to when template is completely instantiated.
15361 if (SemaRef.CurContext->isDependentContext())
15362 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15363 NumGeneratedTopLevelLoops, nullptr,
15364 nullptr);
15365
15366 assert(LoopHelpers.size() == NumLoops &&
15367 "Expecting a single-dimensional loop iteration space");
15368 assert(OriginalInits.size() == NumLoops &&
15369 "Expecting a single-dimensional loop iteration space");
15370 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15371
15372 if (FullClause) {
15374 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
15375 /*SuppressExprDiags=*/true)
15376 .isUsable()) {
15377 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
15378 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
15379 << "#pragma omp unroll full";
15380 return StmtError();
15381 }
15382 }
15383
15384 // The generated loop may only be passed to other loop-associated directive
15385 // when a partial clause is specified. Without the requirement it is
15386 // sufficient to generate loop unroll metadata at code-generation.
15387 if (NumGeneratedTopLevelLoops == 0)
15388 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15389 NumGeneratedTopLevelLoops, nullptr,
15390 nullptr);
15391
15392 // Otherwise, we need to provide a de-sugared/transformed AST that can be
15393 // associated with another loop directive.
15394 //
15395 // The canonical loop analysis return by checkTransformableLoopNest assumes
15396 // the following structure to be the same loop without transformations or
15397 // directives applied: \code OriginalInits; LoopHelper.PreInits;
15398 // LoopHelper.Counters;
15399 // for (; IV < LoopHelper.NumIterations; ++IV) {
15400 // LoopHelper.Updates;
15401 // Body;
15402 // }
15403 // \endcode
15404 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
15405 // and referenced by LoopHelper.IterationVarRef.
15406 //
15407 // The unrolling directive transforms this into the following loop:
15408 // \code
15409 // OriginalInits; \
15410 // LoopHelper.PreInits; > NewPreInits
15411 // LoopHelper.Counters; /
15412 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
15413 // #pragma clang loop unroll_count(Factor)
15414 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
15415 // {
15416 // LoopHelper.Updates;
15417 // Body;
15418 // }
15419 // }
15420 // \endcode
15421 // where UIV is a new logical iteration counter. IV must be the same VarDecl
15422 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
15423 // references it. If the partially unrolled loop is associated with another
15424 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
15425 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
15426 // OpenMP canonical loop. The inner loop is not an associable canonical loop
15427 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
15428 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
15429 // property of the OMPLoopBasedDirective instead of statements in
15430 // CompoundStatement. This is to allow the loop to become a non-outermost loop
15431 // of a canonical loop nest where these PreInits are emitted before the
15432 // outermost directive.
15433
15434 // Find the loop statement.
15435 Stmt *LoopStmt = nullptr;
15436 collectLoopStmts(AStmt, {LoopStmt});
15437
15438 // Determine the PreInit declarations.
15439 SmallVector<Stmt *, 4> PreInits;
15440 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15441
15442 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15443 QualType IVTy = IterationVarRef->getType();
15444 assert(LoopHelper.Counters.size() == 1 &&
15445 "Expecting a single-dimensional loop iteration space");
15446 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15447
15448 // Determine the unroll factor.
15449 uint64_t Factor;
15450 SourceLocation FactorLoc;
15451 if (Expr *FactorVal = PartialClause->getFactor();
15452 FactorVal && !FactorVal->containsErrors()) {
15453 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15454 FactorLoc = FactorVal->getExprLoc();
15455 } else {
15456 // TODO: Use a better profitability model.
15457 Factor = 2;
15458 }
15459 assert(Factor > 0 && "Expected positive unroll factor");
15460 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
15462 getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor),
15463 IVTy, FactorLoc);
15464 };
15465
15466 // Iteration variable SourceLocations.
15467 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15468 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15469 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15470
15471 // Internal variable names.
15472 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15473 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
15474 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
15475
15476 // Create the iteration variable for the unrolled loop.
15477 VarDecl *OuterIVDecl =
15478 buildVarDecl(SemaRef, {}, IVTy, OuterIVName, nullptr, OrigVar);
15479 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
15480 return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc);
15481 };
15482
15483 // Iteration variable for the inner loop: Reuse the iteration variable created
15484 // by checkOpenMPLoop.
15485 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15486 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(InnerIVName));
15487 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
15488 return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc);
15489 };
15490
15491 // Make a copy of the NumIterations expression for each use: By the AST
15492 // constraints, every expression object in a DeclContext must be unique.
15493 CaptureVars CopyTransformer(SemaRef);
15494 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15495 return AssertSuccess(
15496 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15497 };
15498
15499 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15500 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(MakeOuterRef());
15501 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(),
15502 /*DirectInit=*/false);
15503 StmtResult InnerInit = new (Context)
15504 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15505 if (!InnerInit.isUsable())
15506 return StmtError();
15507
15508 // Inner For cond-expression:
15509 // \code
15510 // .unroll_inner.iv < .unrolled.iv + Factor &&
15511 // .unroll_inner.iv < NumIterations
15512 // \endcode
15513 // This conjunction of two conditions allows ScalarEvolution to derive the
15514 // maximum trip count of the inner loop.
15515 ExprResult EndOfTile =
15516 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15517 MakeOuterRef(), MakeFactorExpr());
15518 if (!EndOfTile.isUsable())
15519 return StmtError();
15520 ExprResult InnerCond1 =
15521 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15522 MakeInnerRef(), EndOfTile.get());
15523 if (!InnerCond1.isUsable())
15524 return StmtError();
15525 ExprResult InnerCond2 =
15526 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15527 MakeInnerRef(), MakeNumIterations());
15528 if (!InnerCond2.isUsable())
15529 return StmtError();
15530 ExprResult InnerCond =
15531 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15532 InnerCond1.get(), InnerCond2.get());
15533 if (!InnerCond.isUsable())
15534 return StmtError();
15535
15536 // Inner For incr-statement: ++.unroll_inner.iv
15537 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
15538 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
15539 if (!InnerIncr.isUsable())
15540 return StmtError();
15541
15542 // Inner For statement.
15543 SmallVector<Stmt *> InnerBodyStmts;
15544 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15545 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15546 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15547 InnerBodyStmts.push_back(Body);
15548 CompoundStmt *InnerBody =
15550 Body->getBeginLoc(), Body->getEndLoc());
15551 ForStmt *InnerFor = new (Context)
15552 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15553 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15554 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15555
15556 // Unroll metadata for the inner loop.
15557 // This needs to take into account the remainder portion of the unrolled loop,
15558 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15559 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15560 // the maximum trip count, which will also generate a remainder loop. Just
15561 // `unroll(enable)` (which could have been useful if the user has not
15562 // specified a concrete factor; even though the outer loop cannot be
15563 // influenced anymore, would avoid more code bloat than necessary) will refuse
15564 // the loop because "Won't unroll; remainder loop could not be generated when
15565 // assuming runtime trip count". Even if it did work, it must not choose a
15566 // larger unroll factor than the maximum loop length, or it would always just
15567 // execute the remainder loop.
15568 LoopHintAttr *UnrollHintAttr =
15569 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15570 LoopHintAttr::Numeric, MakeFactorExpr());
15571 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
15572 getASTContext(), StartLoc, {UnrollHintAttr}, InnerFor);
15573
15574 // Outer For init-statement: auto .unrolled.iv = 0
15575 SemaRef.AddInitializerToDecl(
15576 OuterIVDecl,
15577 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15578 /*DirectInit=*/false);
15579 StmtResult OuterInit = new (Context)
15580 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15581 if (!OuterInit.isUsable())
15582 return StmtError();
15583
15584 // Outer For cond-expression: .unrolled.iv < NumIterations
15585 ExprResult OuterConde =
15586 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15587 MakeOuterRef(), MakeNumIterations());
15588 if (!OuterConde.isUsable())
15589 return StmtError();
15590
15591 // Outer For incr-statement: .unrolled.iv += Factor
15592 ExprResult OuterIncr =
15593 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15594 MakeOuterRef(), MakeFactorExpr());
15595 if (!OuterIncr.isUsable())
15596 return StmtError();
15597
15598 // Outer For statement.
15599 ForStmt *OuterFor = new (Context)
15600 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15601 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15602 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15603
15604 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15605 NumGeneratedTopLevelLoops, OuterFor,
15606 buildPreInits(Context, PreInits));
15607}
15608
15610 SourceLocation StartLoc,
15611 SourceLocation EndLoc) {
15612 ASTContext &Context = getASTContext();
15613 Scope *CurScope = SemaRef.getCurScope();
15614
15615 // Empty statement should only be possible if there already was an error.
15616 if (!AStmt)
15617 return StmtError();
15618
15619 constexpr unsigned NumLoops = 1;
15620 Stmt *Body = nullptr;
15622 NumLoops);
15623 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
15624 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
15625 Body, OriginalInits))
15626 return StmtError();
15627
15628 // Delay applying the transformation to when template is completely
15629 // instantiated.
15630 if (SemaRef.CurContext->isDependentContext())
15631 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
15632 NumLoops, nullptr, nullptr);
15633
15634 assert(LoopHelpers.size() == NumLoops &&
15635 "Expecting a single-dimensional loop iteration space");
15636 assert(OriginalInits.size() == NumLoops &&
15637 "Expecting a single-dimensional loop iteration space");
15638 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15639
15640 // Find the loop statement.
15641 Stmt *LoopStmt = nullptr;
15642 collectLoopStmts(AStmt, {LoopStmt});
15643
15644 // Determine the PreInit declarations.
15645 SmallVector<Stmt *> PreInits;
15646 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15647
15648 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15649 QualType IVTy = IterationVarRef->getType();
15650 uint64_t IVWidth = Context.getTypeSize(IVTy);
15651 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15652
15653 // Iteration variable SourceLocations.
15654 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15655 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15656 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15657
15658 // Locations pointing to the transformation.
15659 SourceLocation TransformLoc = StartLoc;
15660 SourceLocation TransformLocBegin = StartLoc;
15661 SourceLocation TransformLocEnd = EndLoc;
15662
15663 // Internal variable names.
15664 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15665 SmallString<64> ForwardIVName(".forward.iv.");
15666 ForwardIVName += OrigVarName;
15667 SmallString<64> ReversedIVName(".reversed.iv.");
15668 ReversedIVName += OrigVarName;
15669
15670 // LoopHelper.Updates will read the logical iteration number from
15671 // LoopHelper.IterationVarRef, compute the value of the user loop counter of
15672 // that logical iteration from it, then assign it to the user loop counter
15673 // variable. We cannot directly use LoopHelper.IterationVarRef as the
15674 // induction variable of the generated loop because it may cause an underflow:
15675 // \code{.c}
15676 // for (unsigned i = 0; i < n; ++i)
15677 // body(i);
15678 // \endcode
15679 //
15680 // Naive reversal:
15681 // \code{.c}
15682 // for (unsigned i = n-1; i >= 0; --i)
15683 // body(i);
15684 // \endcode
15685 //
15686 // Instead, we introduce a new iteration variable representing the logical
15687 // iteration counter of the original loop, convert it to the logical iteration
15688 // number of the reversed loop, then let LoopHelper.Updates compute the user's
15689 // loop iteration variable from it.
15690 // \code{.cpp}
15691 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
15692 // auto .reversed.iv = n - .forward.iv - 1;
15693 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates
15694 // body(i); // Body
15695 // }
15696 // \endcode
15697
15698 // Subexpressions with more than one use. One of the constraints of an AST is
15699 // that every node object must appear at most once, hence we define a lambda
15700 // that creates a new AST node at every use.
15701 CaptureVars CopyTransformer(SemaRef);
15702 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15703 return AssertSuccess(
15704 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15705 };
15706
15707 // Create the iteration variable for the forward loop (from 0 to n-1).
15708 VarDecl *ForwardIVDecl =
15709 buildVarDecl(SemaRef, {}, IVTy, ForwardIVName, nullptr, OrigVar);
15710 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
15711 OrigVarLoc]() {
15712 return buildDeclRefExpr(SemaRef, ForwardIVDecl, IVTy, OrigVarLoc);
15713 };
15714
15715 // Iteration variable for the reversed induction variable (from n-1 downto 0):
15716 // Reuse the iteration variable created by checkOpenMPLoop.
15717 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15718 ReversedIVDecl->setDeclName(
15719 &SemaRef.PP.getIdentifierTable().get(ReversedIVName));
15720
15721 // For init-statement:
15722 // \code{.cpp}
15723 // auto .forward.iv = 0;
15724 // \endcode
15725 auto *Zero = IntegerLiteral::Create(Context, llvm::APInt::getZero(IVWidth),
15726 ForwardIVDecl->getType(), OrigVarLoc);
15727 SemaRef.AddInitializerToDecl(ForwardIVDecl, Zero, /*DirectInit=*/false);
15728 StmtResult Init = new (Context)
15729 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15730 if (!Init.isUsable())
15731 return StmtError();
15732
15733 // Forward iv cond-expression:
15734 // \code{.cpp}
15735 // .forward.iv < MakeNumIterations()
15736 // \endcode
15738 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15739 MakeForwardRef(), MakeNumIterations());
15740 if (!Cond.isUsable())
15741 return StmtError();
15742
15743 // Forward incr-statement:
15744 // \code{.c}
15745 // ++.forward.iv
15746 // \endcode
15747 ExprResult Incr = SemaRef.BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
15748 UO_PreInc, MakeForwardRef());
15749 if (!Incr.isUsable())
15750 return StmtError();
15751
15752 // Reverse the forward-iv:
15753 // \code{.cpp}
15754 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
15755 // \endcode
15756 auto *One = IntegerLiteral::Create(Context, llvm::APInt(IVWidth, 1), IVTy,
15757 TransformLoc);
15758 ExprResult Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub,
15759 MakeNumIterations(), One);
15760 if (!Minus.isUsable())
15761 return StmtError();
15762 Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.get(),
15763 MakeForwardRef());
15764 if (!Minus.isUsable())
15765 return StmtError();
15766 StmtResult InitReversed = new (Context) DeclStmt(
15767 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
15768 if (!InitReversed.isUsable())
15769 return StmtError();
15770 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.get(),
15771 /*DirectInit=*/false);
15772
15773 // The new loop body.
15774 SmallVector<Stmt *, 4> BodyStmts;
15775 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
15776 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
15777 BodyStmts.push_back(InitReversed.get());
15778 llvm::append_range(BodyStmts, LoopHelper.Updates);
15779 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15780 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15781 BodyStmts.push_back(Body);
15782 auto *ReversedBody =
15783 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
15784 Body->getBeginLoc(), Body->getEndLoc());
15785
15786 // Finally create the reversed For-statement.
15787 auto *ReversedFor = new (Context)
15788 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
15789 ReversedBody, LoopHelper.Init->getBeginLoc(),
15790 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15791 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt, NumLoops,
15792 ReversedFor,
15793 buildPreInits(Context, PreInits));
15794}
15795
15797 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15798 SourceLocation EndLoc) {
15799 ASTContext &Context = getASTContext();
15800 DeclContext *CurContext = SemaRef.CurContext;
15801 Scope *CurScope = SemaRef.getCurScope();
15802
15803 // Empty statement should only be possible if there already was an error.
15804 if (!AStmt)
15805 return StmtError();
15806
15807 // interchange without permutation clause swaps two loops.
15808 const OMPPermutationClause *PermutationClause =
15809 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
15810 size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2;
15811
15812 // Verify and diagnose loop nest.
15814 Stmt *Body = nullptr;
15815 SmallVector<SmallVector<Stmt *>, 2> OriginalInits;
15816 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
15817 LoopHelpers, Body, OriginalInits))
15818 return StmtError();
15819
15820 // Delay interchange to when template is completely instantiated.
15821 if (CurContext->isDependentContext())
15822 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15823 NumLoops, AStmt, nullptr, nullptr);
15824
15825 // An invalid expression in the permutation clause is set to nullptr in
15826 // ActOnOpenMPPermutationClause.
15827 if (PermutationClause &&
15828 llvm::is_contained(PermutationClause->getArgsRefs(), nullptr))
15829 return StmtError();
15830
15831 assert(LoopHelpers.size() == NumLoops &&
15832 "Expecting loop iteration space dimensionaly to match number of "
15833 "affected loops");
15834 assert(OriginalInits.size() == NumLoops &&
15835 "Expecting loop iteration space dimensionaly to match number of "
15836 "affected loops");
15837
15838 // Decode the permutation clause.
15839 SmallVector<uint64_t, 2> Permutation;
15840 if (!PermutationClause) {
15841 Permutation = {1, 0};
15842 } else {
15843 ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs();
15844 llvm::BitVector Flags(PermArgs.size());
15845 for (Expr *PermArg : PermArgs) {
15846 std::optional<llvm::APSInt> PermCstExpr =
15847 PermArg->getIntegerConstantExpr(Context);
15848 if (!PermCstExpr)
15849 continue;
15850 uint64_t PermInt = PermCstExpr->getZExtValue();
15851 assert(1 <= PermInt && PermInt <= NumLoops &&
15852 "Must be a permutation; diagnostic emitted in "
15853 "ActOnOpenMPPermutationClause");
15854 if (Flags[PermInt - 1]) {
15855 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
15856 Diag(PermArg->getExprLoc(),
15857 diag::err_omp_interchange_permutation_value_repeated)
15858 << PermInt << ExprRange;
15859 continue;
15860 }
15861 Flags[PermInt - 1] = true;
15862
15863 Permutation.push_back(PermInt - 1);
15864 }
15865
15866 if (Permutation.size() != NumLoops)
15867 return StmtError();
15868 }
15869
15870 // Nothing to transform with trivial permutation.
15871 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](auto P) {
15872 auto [Idx, Arg] = P;
15873 return Idx == Arg;
15874 }))
15875 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15876 NumLoops, AStmt, AStmt, nullptr);
15877
15878 // Find the affected loops.
15879 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15880 collectLoopStmts(AStmt, LoopStmts);
15881
15882 // Collect pre-init statements on the order before the permuation.
15883 SmallVector<Stmt *> PreInits;
15884 for (auto I : llvm::seq<int>(NumLoops)) {
15885 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15886
15887 assert(LoopHelper.Counters.size() == 1 &&
15888 "Single-dimensional loop iteration space expected");
15889
15890 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
15891 PreInits);
15892 }
15893
15894 SmallVector<VarDecl *> PermutedIndVars(NumLoops);
15895 CaptureVars CopyTransformer(SemaRef);
15896
15897 // Create the permuted loops from the inside to the outside of the
15898 // interchanged loop nest. Body of the innermost new loop is the original
15899 // innermost body.
15900 Stmt *Inner = Body;
15901 for (auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
15902 // Get the original loop that belongs to this new position.
15903 uint64_t SourceIdx = Permutation[TargetIdx];
15904 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
15905 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15906 assert(SourceHelper.Counters.size() == 1 &&
15907 "Single-dimensional loop iteration space expected");
15908 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.Counters.front());
15909
15910 // Normalized loop counter variable: From 0 to n-1, always an integer type.
15911 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(SourceHelper.IterationVarRef);
15912 QualType IVTy = IterVarRef->getType();
15913 assert(IVTy->isIntegerType() &&
15914 "Expected the logical iteration counter to be an integer");
15915
15916 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15917 SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
15918
15919 // Make a copy of the NumIterations expression for each use: By the AST
15920 // constraints, every expression object in a DeclContext must be unique.
15921 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
15922 return AssertSuccess(
15923 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
15924 };
15925
15926 // Iteration variable for the permuted loop. Reuse the one from
15927 // checkOpenMPLoop which will also be used to update the original loop
15928 // variable.
15929 SmallString<64> PermutedCntName(".permuted_");
15930 PermutedCntName.append({llvm::utostr(TargetIdx), ".iv.", OrigVarName});
15931 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15932 PermutedCntDecl->setDeclName(
15933 &SemaRef.PP.getIdentifierTable().get(PermutedCntName));
15934 PermutedIndVars[TargetIdx] = PermutedCntDecl;
15935 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
15936 return buildDeclRefExpr(SemaRef, PermutedCntDecl, IVTy, OrigVarLoc);
15937 };
15938
15939 // For init-statement:
15940 // \code
15941 // auto .permuted_{target}.iv = 0
15942 // \endcode
15943 ExprResult Zero = SemaRef.ActOnIntegerConstant(OrigVarLoc, 0);
15944 if (!Zero.isUsable())
15945 return StmtError();
15946 SemaRef.AddInitializerToDecl(PermutedCntDecl, Zero.get(),
15947 /*DirectInit=*/false);
15948 StmtResult InitStmt = new (Context)
15949 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
15950 OrigCntVar->getEndLoc());
15951 if (!InitStmt.isUsable())
15952 return StmtError();
15953
15954 // For cond-expression:
15955 // \code
15956 // .permuted_{target}.iv < MakeNumIterations()
15957 // \endcode
15958 ExprResult CondExpr =
15959 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
15960 MakePermutedRef(), MakeNumIterations());
15961 if (!CondExpr.isUsable())
15962 return StmtError();
15963
15964 // For incr-statement:
15965 // \code
15966 // ++.tile.iv
15967 // \endcode
15968 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15969 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
15970 if (!IncrStmt.isUsable())
15971 return StmtError();
15972
15973 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
15974 SourceHelper.Updates.end());
15975 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
15976 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15977 BodyParts.push_back(Inner);
15978 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15979 Inner->getBeginLoc(), Inner->getEndLoc());
15980 Inner = new (Context) ForStmt(
15981 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
15982 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
15983 SourceHelper.Inc->getEndLoc());
15984 }
15985
15986 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15987 NumLoops, AStmt, Inner,
15988 buildPreInits(Context, PreInits));
15989}
15990
15992 Stmt *AStmt,
15993 SourceLocation StartLoc,
15994 SourceLocation EndLoc) {
15995
15996 ASTContext &Context = getASTContext();
15997 DeclContext *CurrContext = SemaRef.CurContext;
15998 Scope *CurScope = SemaRef.getCurScope();
15999 CaptureVars CopyTransformer(SemaRef);
16000
16001 // Ensure the structured block is not empty
16002 if (!AStmt)
16003 return StmtError();
16004
16005 // Defer transformation in dependent contexts
16006 // The NumLoopNests argument is set to a placeholder 1 (even though
16007 // using looprange fuse could yield up to 3 top level loop nests)
16008 // because a dependent context could prevent determining its true value
16009 if (CurrContext->isDependentContext())
16010 return OMPFuseDirective::Create(Context, StartLoc, EndLoc, Clauses,
16011 /* NumLoops */ 1, AStmt, nullptr, nullptr);
16012
16013 // Validate that the potential loop sequence is transformable for fusion
16014 // Also collect the HelperExprs, Loop Stmts, Inits, and Number of loops
16015 LoopSequenceAnalysis SeqAnalysis;
16016 if (!checkTransformableLoopSequence(OMPD_fuse, AStmt, SeqAnalysis, Context))
16017 return StmtError();
16018
16019 // SeqAnalysis.LoopSeqSize exists mostly to handle dependent contexts,
16020 // otherwise it must be the same as SeqAnalysis.Loops.size().
16021 assert(SeqAnalysis.LoopSeqSize == SeqAnalysis.Loops.size() &&
16022 "Inconsistent size of the loop sequence and the number of loops "
16023 "found in the sequence");
16024
16025 // Handle clauses, which can be any of the following: [looprange, apply]
16026 const auto *LRC =
16027 OMPExecutableDirective::getSingleClause<OMPLoopRangeClause>(Clauses);
16028
16029 // The clause arguments are invalidated if any error arises
16030 // such as non-constant or non-positive arguments
16031 if (LRC && (!LRC->getFirst() || !LRC->getCount()))
16032 return StmtError();
16033
16034 // Delayed semantic check of LoopRange constraint
16035 // Evaluates the loop range arguments and returns the first and count values
16036 auto EvaluateLoopRangeArguments = [&Context](Expr *First, Expr *Count,
16037 uint64_t &FirstVal,
16038 uint64_t &CountVal) {
16039 llvm::APSInt FirstInt = First->EvaluateKnownConstInt(Context);
16040 llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Context);
16041 FirstVal = FirstInt.getZExtValue();
16042 CountVal = CountInt.getZExtValue();
16043 };
16044
16045 // OpenMP [6.0, Restrictions]
16046 // first + count - 1 must not evaluate to a value greater than the
16047 // loop sequence length of the associated canonical loop sequence.
16048 auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal,
16049 unsigned NumLoops) -> bool {
16050 return FirstVal + CountVal - 1 <= NumLoops;
16051 };
16052 uint64_t FirstVal = 1, CountVal = 0, LastVal = SeqAnalysis.LoopSeqSize;
16053
16054 // Validates the loop range after evaluating the semantic information
16055 // and ensures that the range is valid for the given loop sequence size.
16056 // Expressions are evaluated at compile time to obtain constant values.
16057 if (LRC) {
16058 EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal,
16059 CountVal);
16060 if (CountVal == 1)
16061 SemaRef.Diag(LRC->getCountLoc(), diag::warn_omp_redundant_fusion)
16062 << getOpenMPDirectiveName(OMPD_fuse);
16063
16064 if (!ValidLoopRange(FirstVal, CountVal, SeqAnalysis.LoopSeqSize)) {
16065 SemaRef.Diag(LRC->getFirstLoc(), diag::err_omp_invalid_looprange)
16066 << getOpenMPDirectiveName(OMPD_fuse) << FirstVal
16067 << (FirstVal + CountVal - 1) << SeqAnalysis.LoopSeqSize;
16068 return StmtError();
16069 }
16070
16071 LastVal = FirstVal + CountVal - 1;
16072 }
16073
16074 // Complete fusion generates a single canonical loop nest
16075 // However looprange clause may generate several loop nests
16076 unsigned NumGeneratedTopLevelLoops =
16077 LRC ? SeqAnalysis.LoopSeqSize - CountVal + 1 : 1;
16078
16079 // Emit a warning for redundant loop fusion when the sequence contains only
16080 // one loop.
16081 if (SeqAnalysis.LoopSeqSize == 1)
16082 SemaRef.Diag(AStmt->getBeginLoc(), diag::warn_omp_redundant_fusion)
16083 << getOpenMPDirectiveName(OMPD_fuse);
16084
16085 // Select the type with the largest bit width among all induction variables
16086 QualType IVType =
16087 SeqAnalysis.Loops[FirstVal - 1].HelperExprs.IterationVarRef->getType();
16088 for (unsigned I : llvm::seq<unsigned>(FirstVal, LastVal)) {
16089 QualType CurrentIVType =
16090 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef->getType();
16091 if (Context.getTypeSize(CurrentIVType) > Context.getTypeSize(IVType)) {
16092 IVType = CurrentIVType;
16093 }
16094 }
16095 uint64_t IVBitWidth = Context.getIntWidth(IVType);
16096
16097 // Create pre-init declarations for all loops lower bounds, upper bounds,
16098 // strides and num-iterations for every top level loop in the fusion
16099 SmallVector<VarDecl *, 4> LBVarDecls;
16100 SmallVector<VarDecl *, 4> STVarDecls;
16101 SmallVector<VarDecl *, 4> NIVarDecls;
16102 SmallVector<VarDecl *, 4> UBVarDecls;
16103 SmallVector<VarDecl *, 4> IVVarDecls;
16104
16105 // Helper lambda to create variables for bounds, strides, and other
16106 // expressions. Generates both the variable declaration and the corresponding
16107 // initialization statement.
16108 auto CreateHelperVarAndStmt =
16109 [&, &SemaRef = SemaRef](Expr *ExprToCopy, const std::string &BaseName,
16110 unsigned I, bool NeedsNewVD = false) {
16111 Expr *TransformedExpr =
16112 AssertSuccess(CopyTransformer.TransformExpr(ExprToCopy));
16113 if (!TransformedExpr)
16114 return std::pair<VarDecl *, StmtResult>(nullptr, StmtError());
16115
16116 auto Name = (Twine(".omp.") + BaseName + std::to_string(I)).str();
16117
16118 VarDecl *VD;
16119 if (NeedsNewVD) {
16120 VD = buildVarDecl(SemaRef, SourceLocation(), IVType, Name);
16121 SemaRef.AddInitializerToDecl(VD, TransformedExpr, false);
16122 } else {
16123 // Create a unique variable name
16124 DeclRefExpr *DRE = cast<DeclRefExpr>(TransformedExpr);
16125 VD = cast<VarDecl>(DRE->getDecl());
16126 VD->setDeclName(&SemaRef.PP.getIdentifierTable().get(Name));
16127 }
16128 // Create the corresponding declaration statement
16129 StmtResult DeclStmt = new (Context) class DeclStmt(
16131 return std::make_pair(VD, DeclStmt);
16132 };
16133
16134 // PreInits hold a sequence of variable declarations that must be executed
16135 // before the fused loop begins. These include bounds, strides, and other
16136 // helper variables required for the transformation. Other loop transforms
16137 // also contain their own preinits
16138 SmallVector<Stmt *> PreInits;
16139
16140 // Update the general preinits using the preinits generated by loop sequence
16141 // generating loop transformations. These preinits differ slightly from
16142 // single-loop transformation preinits, as they can be detached from a
16143 // specific loop inside multiple generated loop nests. This happens
16144 // because certain helper variables, like '.omp.fuse.max', are introduced to
16145 // handle fused iteration spaces and may not be directly tied to a single
16146 // original loop. The preinit structure must ensure that hidden variables
16147 // like '.omp.fuse.max' are still properly handled.
16148 // Transformations that apply this concept: Loopranged Fuse, Split
16149 llvm::append_range(PreInits, SeqAnalysis.LoopSequencePreInits);
16150
16151 // Process each single loop to generate and collect declarations
16152 // and statements for all helper expressions related to
16153 // particular single loop nests
16154
16155 // Also In the case of the fused loops, we keep track of their original
16156 // inits by appending them to their preinits statement, and in the case of
16157 // transformations, also append their preinits (which contain the original
16158 // loop initialization statement or other statements)
16159
16160 // Firstly we need to set TransformIndex to match the begining of the
16161 // looprange section
16162 unsigned int TransformIndex = 0;
16163 for (unsigned I : llvm::seq<unsigned>(FirstVal - 1)) {
16164 if (SeqAnalysis.Loops[I].isLoopTransformation())
16165 ++TransformIndex;
16166 }
16167
16168 for (unsigned int I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16169 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16170 addLoopPreInits(Context, SeqAnalysis.Loops[I].HelperExprs,
16171 SeqAnalysis.Loops[I].TheForStmt,
16172 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16173 } else if (SeqAnalysis.Loops[I].isLoopTransformation()) {
16174 // For transformed loops, insert both pre-inits and original inits.
16175 // Order matters: pre-inits may define variables used in the original
16176 // inits such as upper bounds...
16177 SmallVector<Stmt *> &TransformPreInit =
16178 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16179 llvm::append_range(PreInits, TransformPreInit);
16180
16181 addLoopPreInits(Context, SeqAnalysis.Loops[I].HelperExprs,
16182 SeqAnalysis.Loops[I].TheForStmt,
16183 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16184 }
16185 auto [UBVD, UBDStmt] =
16186 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.UB, "ub", J);
16187 auto [LBVD, LBDStmt] =
16188 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.LB, "lb", J);
16189 auto [STVD, STDStmt] =
16190 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.ST, "st", J);
16191 auto [NIVD, NIDStmt] = CreateHelperVarAndStmt(
16192 SeqAnalysis.Loops[I].HelperExprs.NumIterations, "ni", J, true);
16193 auto [IVVD, IVDStmt] = CreateHelperVarAndStmt(
16194 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef, "iv", J);
16195
16196 assert(LBVD && STVD && NIVD && IVVD &&
16197 "OpenMP Fuse Helper variables creation failed");
16198
16199 UBVarDecls.push_back(UBVD);
16200 LBVarDecls.push_back(LBVD);
16201 STVarDecls.push_back(STVD);
16202 NIVarDecls.push_back(NIVD);
16203 IVVarDecls.push_back(IVVD);
16204
16205 PreInits.push_back(LBDStmt.get());
16206 PreInits.push_back(STDStmt.get());
16207 PreInits.push_back(NIDStmt.get());
16208 PreInits.push_back(IVDStmt.get());
16209 }
16210
16211 auto MakeVarDeclRef = [&SemaRef = this->SemaRef](VarDecl *VD) {
16212 return buildDeclRefExpr(SemaRef, VD, VD->getType(), VD->getLocation(),
16213 false);
16214 };
16215
16216 // Following up the creation of the final fused loop will be performed
16217 // which has the following shape (considering the selected loops):
16218 //
16219 // for (fuse.index = 0; fuse.index < max(ni0, ni1..., nik); ++fuse.index) {
16220 // if (fuse.index < ni0){
16221 // iv0 = lb0 + st0 * fuse.index;
16222 // original.index0 = iv0
16223 // body(0);
16224 // }
16225 // if (fuse.index < ni1){
16226 // iv1 = lb1 + st1 * fuse.index;
16227 // original.index1 = iv1
16228 // body(1);
16229 // }
16230 //
16231 // ...
16232 //
16233 // if (fuse.index < nik){
16234 // ivk = lbk + stk * fuse.index;
16235 // original.indexk = ivk
16236 // body(k); Expr *InitVal = IntegerLiteral::Create(Context,
16237 // llvm::APInt(IVWidth, 0),
16238 // }
16239
16240 // 1. Create the initialized fuse index
16241 StringRef IndexName = ".omp.fuse.index";
16242 Expr *InitVal = IntegerLiteral::Create(Context, llvm::APInt(IVBitWidth, 0),
16243 IVType, SourceLocation());
16244 VarDecl *IndexDecl =
16245 buildVarDecl(SemaRef, {}, IVType, IndexName, nullptr, nullptr);
16246 SemaRef.AddInitializerToDecl(IndexDecl, InitVal, false);
16247 StmtResult InitStmt = new (Context)
16249
16250 if (!InitStmt.isUsable())
16251 return StmtError();
16252
16253 auto MakeIVRef = [&SemaRef = this->SemaRef, IndexDecl, IVType,
16254 Loc = InitVal->getExprLoc()]() {
16255 return buildDeclRefExpr(SemaRef, IndexDecl, IVType, Loc, false);
16256 };
16257
16258 // 2. Iteratively compute the max number of logical iterations Max(NI_1, NI_2,
16259 // ..., NI_k)
16260 //
16261 // This loop accumulates the maximum value across multiple expressions,
16262 // ensuring each step constructs a unique AST node for correctness. By using
16263 // intermediate temporary variables and conditional operators, we maintain
16264 // distinct nodes and avoid duplicating subtrees, For instance, max(a,b,c):
16265 // omp.temp0 = max(a, b)
16266 // omp.temp1 = max(omp.temp0, c)
16267 // omp.fuse.max = max(omp.temp1, omp.temp0)
16268
16269 ExprResult MaxExpr;
16270 // I is the range of loops in the sequence that we fuse.
16271 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16272 DeclRefExpr *NIRef = MakeVarDeclRef(NIVarDecls[J]);
16273 QualType NITy = NIRef->getType();
16274
16275 if (MaxExpr.isUnset()) {
16276 // Initialize MaxExpr with the first NI expression
16277 MaxExpr = NIRef;
16278 } else {
16279 // Create a new acummulator variable t_i = MaxExpr
16280 std::string TempName = (Twine(".omp.temp.") + Twine(J)).str();
16281 VarDecl *TempDecl =
16282 buildVarDecl(SemaRef, {}, NITy, TempName, nullptr, nullptr);
16283 TempDecl->setInit(MaxExpr.get());
16284 DeclRefExpr *TempRef =
16285 buildDeclRefExpr(SemaRef, TempDecl, NITy, SourceLocation(), false);
16286 DeclRefExpr *TempRef2 =
16287 buildDeclRefExpr(SemaRef, TempDecl, NITy, SourceLocation(), false);
16288 // Add a DeclStmt to PreInits to ensure the variable is declared.
16289 StmtResult TempStmt = new (Context)
16291
16292 if (!TempStmt.isUsable())
16293 return StmtError();
16294 PreInits.push_back(TempStmt.get());
16295
16296 // Build MaxExpr <-(MaxExpr > NIRef ? MaxExpr : NIRef)
16298 SemaRef.BuildBinOp(nullptr, SourceLocation(), BO_GT, TempRef, NIRef);
16299 // Handle any errors in Comparison creation
16300 if (!Comparison.isUsable())
16301 return StmtError();
16302
16303 DeclRefExpr *NIRef2 = MakeVarDeclRef(NIVarDecls[J]);
16304 // Update MaxExpr using a conditional expression to hold the max value
16305 MaxExpr = new (Context) ConditionalOperator(
16306 Comparison.get(), SourceLocation(), TempRef2, SourceLocation(),
16307 NIRef2->getExprStmt(), NITy, VK_LValue, OK_Ordinary);
16308
16309 if (!MaxExpr.isUsable())
16310 return StmtError();
16311 }
16312 }
16313 if (!MaxExpr.isUsable())
16314 return StmtError();
16315
16316 // 3. Declare the max variable
16317 const std::string MaxName = Twine(".omp.fuse.max").str();
16318 VarDecl *MaxDecl =
16319 buildVarDecl(SemaRef, {}, IVType, MaxName, nullptr, nullptr);
16320 MaxDecl->setInit(MaxExpr.get());
16321 DeclRefExpr *MaxRef = buildDeclRefExpr(SemaRef, MaxDecl, IVType, {}, false);
16322 StmtResult MaxStmt = new (Context)
16324
16325 if (MaxStmt.isInvalid())
16326 return StmtError();
16327 PreInits.push_back(MaxStmt.get());
16328
16329 // 4. Create condition Expr: index < n_max
16330 ExprResult CondExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_LT,
16331 MakeIVRef(), MaxRef);
16332 if (!CondExpr.isUsable())
16333 return StmtError();
16334
16335 // 5. Increment Expr: ++index
16336 ExprResult IncrExpr =
16337 SemaRef.BuildUnaryOp(CurScope, SourceLocation(), UO_PreInc, MakeIVRef());
16338 if (!IncrExpr.isUsable())
16339 return StmtError();
16340
16341 // 6. Build the Fused Loop Body
16342 // The final fused loop iterates over the maximum logical range. Inside the
16343 // loop, each original loop's index is calculated dynamically, and its body
16344 // is executed conditionally.
16345 //
16346 // Each sub-loop's body is guarded by a conditional statement to ensure
16347 // it executes only within its logical iteration range:
16348 //
16349 // if (fuse.index < ni_k){
16350 // iv_k = lb_k + st_k * fuse.index;
16351 // original.index = iv_k
16352 // body(k);
16353 // }
16354
16355 CompoundStmt *FusedBody = nullptr;
16356 SmallVector<Stmt *, 4> FusedBodyStmts;
16357 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16358 // Assingment of the original sub-loop index to compute the logical index
16359 // IV_k = LB_k + omp.fuse.index * ST_k
16360 ExprResult IdxExpr =
16361 SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Mul,
16362 MakeVarDeclRef(STVarDecls[J]), MakeIVRef());
16363 if (!IdxExpr.isUsable())
16364 return StmtError();
16365 IdxExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Add,
16366 MakeVarDeclRef(LBVarDecls[J]), IdxExpr.get());
16367
16368 if (!IdxExpr.isUsable())
16369 return StmtError();
16370 IdxExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Assign,
16371 MakeVarDeclRef(IVVarDecls[J]), IdxExpr.get());
16372 if (!IdxExpr.isUsable())
16373 return StmtError();
16374
16375 // Update the original i_k = IV_k
16376 SmallVector<Stmt *, 4> BodyStmts;
16377 BodyStmts.push_back(IdxExpr.get());
16378 llvm::append_range(BodyStmts, SeqAnalysis.Loops[I].HelperExprs.Updates);
16379
16380 // If the loop is a CXXForRangeStmt then the iterator variable is needed
16381 if (auto *SourceCXXFor =
16382 dyn_cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt))
16383 BodyStmts.push_back(SourceCXXFor->getLoopVarStmt());
16384
16385 Stmt *Body =
16386 (isa<ForStmt>(SeqAnalysis.Loops[I].TheForStmt))
16387 ? cast<ForStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody()
16388 : cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody();
16389 BodyStmts.push_back(Body);
16390
16391 CompoundStmt *CombinedBody =
16392 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
16395 SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_LT, MakeIVRef(),
16396 MakeVarDeclRef(NIVarDecls[J]));
16397
16398 if (!Condition.isUsable())
16399 return StmtError();
16400
16401 IfStmt *IfStatement = IfStmt::Create(
16402 Context, SourceLocation(), IfStatementKind::Ordinary, nullptr, nullptr,
16403 Condition.get(), SourceLocation(), SourceLocation(), CombinedBody,
16404 SourceLocation(), nullptr);
16405
16406 FusedBodyStmts.push_back(IfStatement);
16407 }
16408 FusedBody = CompoundStmt::Create(Context, FusedBodyStmts, FPOptionsOverride(),
16410
16411 // 7. Construct the final fused loop
16412 ForStmt *FusedForStmt = new (Context)
16413 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr, IncrExpr.get(),
16414 FusedBody, InitStmt.get()->getBeginLoc(), SourceLocation(),
16415 IncrExpr.get()->getEndLoc());
16416
16417 // In the case of looprange, the result of fuse won't simply
16418 // be a single loop (ForStmt), but rather a loop sequence
16419 // (CompoundStmt) of 3 parts: the pre-fusion loops, the fused loop
16420 // and the post-fusion loops, preserving its original order.
16421 //
16422 // Note: If looprange clause produces a single fused loop nest then
16423 // this compound statement wrapper is unnecessary (Therefore this
16424 // treatment is skipped)
16425
16426 Stmt *FusionStmt = FusedForStmt;
16427 if (LRC && CountVal != SeqAnalysis.LoopSeqSize) {
16428 SmallVector<Stmt *, 4> FinalLoops;
16429
16430 // Reset the transform index
16431 TransformIndex = 0;
16432
16433 // Collect all non-fused loops before and after the fused region.
16434 // Pre-fusion and post-fusion loops are inserted in order exploiting their
16435 // symmetry, along with their corresponding transformation pre-inits if
16436 // needed. The fused loop is added between the two regions.
16437 for (unsigned I : llvm::seq<unsigned>(SeqAnalysis.LoopSeqSize)) {
16438 if (I >= FirstVal - 1 && I < FirstVal + CountVal - 1) {
16439 // Update the Transformation counter to skip already treated
16440 // loop transformations
16441 if (!SeqAnalysis.Loops[I].isLoopTransformation())
16442 ++TransformIndex;
16443 continue;
16444 }
16445
16446 // No need to handle:
16447 // Regular loops: they are kept intact as-is.
16448 // Loop-sequence-generating transformations: already handled earlier.
16449 // Only TransformSingleLoop requires inserting pre-inits here
16450 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16451 const auto &TransformPreInit =
16452 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16453 if (!TransformPreInit.empty())
16454 llvm::append_range(PreInits, TransformPreInit);
16455 }
16456
16457 FinalLoops.push_back(SeqAnalysis.Loops[I].TheForStmt);
16458 }
16459
16460 FinalLoops.insert(FinalLoops.begin() + (FirstVal - 1), FusedForStmt);
16461 FusionStmt = CompoundStmt::Create(Context, FinalLoops, FPOptionsOverride(),
16463 }
16464 return OMPFuseDirective::Create(Context, StartLoc, EndLoc, Clauses,
16465 NumGeneratedTopLevelLoops, AStmt, FusionStmt,
16466 buildPreInits(Context, PreInits));
16467}
16468
16470 Expr *Expr,
16471 SourceLocation StartLoc,
16472 SourceLocation LParenLoc,
16473 SourceLocation EndLoc) {
16474 OMPClause *Res = nullptr;
16475 switch (Kind) {
16476 case OMPC_final:
16477 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
16478 break;
16479 case OMPC_safelen:
16480 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
16481 break;
16482 case OMPC_simdlen:
16483 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
16484 break;
16485 case OMPC_allocator:
16486 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
16487 break;
16488 case OMPC_collapse:
16489 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
16490 break;
16491 case OMPC_ordered:
16492 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
16493 break;
16494 case OMPC_priority:
16495 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
16496 break;
16497 case OMPC_hint:
16498 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
16499 break;
16500 case OMPC_depobj:
16501 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
16502 break;
16503 case OMPC_detach:
16504 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
16505 break;
16506 case OMPC_novariants:
16507 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
16508 break;
16509 case OMPC_nocontext:
16510 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
16511 break;
16512 case OMPC_filter:
16513 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
16514 break;
16515 case OMPC_partial:
16516 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
16517 break;
16518 case OMPC_message:
16519 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
16520 break;
16521 case OMPC_align:
16522 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
16523 break;
16524 case OMPC_ompx_dyn_cgroup_mem:
16525 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
16526 break;
16527 case OMPC_holds:
16528 Res = ActOnOpenMPHoldsClause(Expr, StartLoc, LParenLoc, EndLoc);
16529 break;
16530 case OMPC_grainsize:
16531 case OMPC_num_tasks:
16532 case OMPC_num_threads:
16533 case OMPC_device:
16534 case OMPC_if:
16535 case OMPC_default:
16536 case OMPC_proc_bind:
16537 case OMPC_schedule:
16538 case OMPC_private:
16539 case OMPC_firstprivate:
16540 case OMPC_lastprivate:
16541 case OMPC_shared:
16542 case OMPC_reduction:
16543 case OMPC_task_reduction:
16544 case OMPC_in_reduction:
16545 case OMPC_linear:
16546 case OMPC_aligned:
16547 case OMPC_copyin:
16548 case OMPC_copyprivate:
16549 case OMPC_nowait:
16550 case OMPC_untied:
16551 case OMPC_mergeable:
16552 case OMPC_threadprivate:
16553 case OMPC_groupprivate:
16554 case OMPC_sizes:
16555 case OMPC_allocate:
16556 case OMPC_flush:
16557 case OMPC_read:
16558 case OMPC_write:
16559 case OMPC_update:
16560 case OMPC_capture:
16561 case OMPC_compare:
16562 case OMPC_seq_cst:
16563 case OMPC_acq_rel:
16564 case OMPC_acquire:
16565 case OMPC_release:
16566 case OMPC_relaxed:
16567 case OMPC_depend:
16568 case OMPC_threads:
16569 case OMPC_simd:
16570 case OMPC_map:
16571 case OMPC_nogroup:
16572 case OMPC_dist_schedule:
16573 case OMPC_defaultmap:
16574 case OMPC_unknown:
16575 case OMPC_uniform:
16576 case OMPC_to:
16577 case OMPC_from:
16578 case OMPC_use_device_ptr:
16579 case OMPC_use_device_addr:
16580 case OMPC_is_device_ptr:
16581 case OMPC_unified_address:
16582 case OMPC_unified_shared_memory:
16583 case OMPC_reverse_offload:
16584 case OMPC_dynamic_allocators:
16585 case OMPC_atomic_default_mem_order:
16586 case OMPC_self_maps:
16587 case OMPC_device_type:
16588 case OMPC_match:
16589 case OMPC_nontemporal:
16590 case OMPC_order:
16591 case OMPC_at:
16592 case OMPC_severity:
16593 case OMPC_destroy:
16594 case OMPC_inclusive:
16595 case OMPC_exclusive:
16596 case OMPC_uses_allocators:
16597 case OMPC_affinity:
16598 case OMPC_when:
16599 case OMPC_bind:
16600 case OMPC_num_teams:
16601 case OMPC_thread_limit:
16602 default:
16603 llvm_unreachable("Clause is not allowed.");
16604 }
16605 return Res;
16606}
16607
16608// An OpenMP directive such as 'target parallel' has two captured regions:
16609// for the 'target' and 'parallel' respectively. This function returns
16610// the region in which to capture expressions associated with a clause.
16611// A return value of OMPD_unknown signifies that the expression should not
16612// be captured.
16614 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
16615 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
16616 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
16617 "Invalid directive with CKind-clause");
16618
16619 // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
16620 if (NameModifier != OMPD_unknown &&
16621 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
16622 return OMPD_unknown;
16623
16624 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(DKind);
16625
16626 // [5.2:341:24-30]
16627 // If the clauses have expressions on them, such as for various clauses where
16628 // the argument of the clause is an expression, or lower-bound, length, or
16629 // stride expressions inside array sections (or subscript and stride
16630 // expressions in subscript-triplet for Fortran), or linear-step or alignment
16631 // expressions, the expressions are evaluated immediately before the construct
16632 // to which the clause has been split or duplicated per the above rules
16633 // (therefore inside of the outer leaf constructs). However, the expressions
16634 // inside the num_teams and thread_limit clauses are always evaluated before
16635 // the outermost leaf construct.
16636
16637 // Process special cases first.
16638 switch (CKind) {
16639 case OMPC_if:
16640 switch (DKind) {
16641 case OMPD_teams_loop:
16642 case OMPD_target_teams_loop:
16643 // For [target] teams loop, assume capture region is 'teams' so it's
16644 // available for codegen later to use if/when necessary.
16645 return OMPD_teams;
16646 case OMPD_target_update:
16647 case OMPD_target_enter_data:
16648 case OMPD_target_exit_data:
16649 return OMPD_task;
16650 default:
16651 break;
16652 }
16653 break;
16654 case OMPC_num_teams:
16655 case OMPC_thread_limit:
16656 case OMPC_ompx_dyn_cgroup_mem:
16657 if (Leafs[0] == OMPD_target)
16658 return OMPD_target;
16659 break;
16660 case OMPC_device:
16661 if (Leafs[0] == OMPD_target ||
16662 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
16663 OMPD_target_enter_data, OMPD_target_exit_data},
16664 DKind))
16665 return OMPD_task;
16666 break;
16667 case OMPC_novariants:
16668 case OMPC_nocontext:
16669 if (DKind == OMPD_dispatch)
16670 return OMPD_task;
16671 break;
16672 case OMPC_when:
16673 if (DKind == OMPD_metadirective)
16674 return OMPD_metadirective;
16675 break;
16676 case OMPC_filter:
16677 return OMPD_unknown;
16678 default:
16679 break;
16680 }
16681
16682 // If none of the special cases above applied, and DKind is a capturing
16683 // directive, find the innermost enclosing leaf construct that allows the
16684 // clause, and returns the corresponding capture region.
16685
16686 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
16687 // Find the index in "Leafs" of the last leaf that allows the given
16688 // clause. The search will only include indexes [0, EndIdx).
16689 // EndIdx may be set to the index of the NameModifier, if present.
16690 int InnermostIdx = [&]() {
16691 for (int I = EndIdx - 1; I >= 0; --I) {
16692 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
16693 return I;
16694 }
16695 return -1;
16696 }();
16697
16698 // Find the nearest enclosing capture region.
16700 for (int I = InnermostIdx - 1; I >= 0; --I) {
16701 if (!isOpenMPCapturingDirective(Leafs[I]))
16702 continue;
16703 Regions.clear();
16704 getOpenMPCaptureRegions(Regions, Leafs[I]);
16705 if (Regions[0] != OMPD_unknown)
16706 return Regions.back();
16707 }
16708 return OMPD_unknown;
16709 };
16710
16711 if (isOpenMPCapturingDirective(DKind)) {
16712 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
16713 for (int I = 0, E = Leafs.size(); I != E; ++I) {
16714 if (Leafs[I] == Dir)
16715 return I + 1;
16716 }
16717 return 0;
16718 };
16719
16720 int End = NameModifier == OMPD_unknown ? Leafs.size()
16721 : GetLeafIndex(NameModifier);
16722 return GetEnclosingRegion(End, CKind);
16723 }
16724
16725 return OMPD_unknown;
16726}
16727
16729 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
16730 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
16731 SourceLocation ColonLoc, SourceLocation EndLoc) {
16732 Expr *ValExpr = Condition;
16733 Stmt *HelperValStmt = nullptr;
16734 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16735 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16736 !Condition->isInstantiationDependent() &&
16737 !Condition->containsUnexpandedParameterPack()) {
16738 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
16739 if (Val.isInvalid())
16740 return nullptr;
16741
16742 ValExpr = Val.get();
16743
16744 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16745 CaptureRegion = getOpenMPCaptureRegionForClause(
16746 DKind, OMPC_if, getLangOpts().OpenMP, NameModifier);
16747 if (CaptureRegion != OMPD_unknown &&
16748 !SemaRef.CurContext->isDependentContext()) {
16749 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16750 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16751 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16752 HelperValStmt = buildPreInits(getASTContext(), Captures);
16753 }
16754 }
16755
16756 return new (getASTContext())
16757 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16758 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16759}
16760
16762 SourceLocation StartLoc,
16763 SourceLocation LParenLoc,
16764 SourceLocation EndLoc) {
16765 Expr *ValExpr = Condition;
16766 Stmt *HelperValStmt = nullptr;
16767 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16768 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16769 !Condition->isInstantiationDependent() &&
16770 !Condition->containsUnexpandedParameterPack()) {
16771 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
16772 if (Val.isInvalid())
16773 return nullptr;
16774
16775 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
16776
16777 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16778 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final,
16779 getLangOpts().OpenMP);
16780 if (CaptureRegion != OMPD_unknown &&
16781 !SemaRef.CurContext->isDependentContext()) {
16782 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16783 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16784 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16785 HelperValStmt = buildPreInits(getASTContext(), Captures);
16786 }
16787 }
16788
16789 return new (getASTContext()) OMPFinalClause(
16790 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16791}
16792
16795 Expr *Op) {
16796 if (!Op)
16797 return ExprError();
16798
16799 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
16800 public:
16801 IntConvertDiagnoser()
16802 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {}
16803 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
16804 QualType T) override {
16805 return S.Diag(Loc, diag::err_omp_not_integral) << T;
16806 }
16807 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
16808 QualType T) override {
16809 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
16810 }
16811 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
16812 QualType T,
16813 QualType ConvTy) override {
16814 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
16815 }
16816 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
16817 QualType ConvTy) override {
16818 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16819 << ConvTy->isEnumeralType() << ConvTy;
16820 }
16821 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
16822 QualType T) override {
16823 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
16824 }
16825 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
16826 QualType ConvTy) override {
16827 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16828 << ConvTy->isEnumeralType() << ConvTy;
16829 }
16830 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
16831 QualType) override {
16832 llvm_unreachable("conversion functions are permitted");
16833 }
16834 } ConvertDiagnoser;
16835 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16836}
16837
16838static bool
16840 bool StrictlyPositive, bool BuildCapture = false,
16841 OpenMPDirectiveKind DKind = OMPD_unknown,
16842 OpenMPDirectiveKind *CaptureRegion = nullptr,
16843 Stmt **HelperValStmt = nullptr) {
16844 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
16845 !ValExpr->isInstantiationDependent()) {
16846 SourceLocation Loc = ValExpr->getExprLoc();
16848 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
16849 if (Value.isInvalid())
16850 return false;
16851
16852 ValExpr = Value.get();
16853 // The expression must evaluate to a non-negative integer value.
16854 if (std::optional<llvm::APSInt> Result =
16855 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
16856 if (Result->isSigned() &&
16857 !((!StrictlyPositive && Result->isNonNegative()) ||
16858 (StrictlyPositive && Result->isStrictlyPositive()))) {
16859 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
16860 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
16861 << ValExpr->getSourceRange();
16862 return false;
16863 }
16864 }
16865 if (!BuildCapture)
16866 return true;
16867 *CaptureRegion =
16868 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
16869 if (*CaptureRegion != OMPD_unknown &&
16870 !SemaRef.CurContext->isDependentContext()) {
16871 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16872 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16873 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16874 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
16875 }
16876 }
16877 return true;
16878}
16879
16880static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First,
16881 unsigned Last,
16882 ArrayRef<unsigned> Exclude = {}) {
16883 SmallString<256> Buffer;
16884 llvm::raw_svector_ostream Out(Buffer);
16885 unsigned Skipped = Exclude.size();
16886 for (unsigned I = First; I < Last; ++I) {
16887 if (llvm::is_contained(Exclude, I)) {
16888 --Skipped;
16889 continue;
16890 }
16891 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
16892 if (I + Skipped + 2 == Last)
16893 Out << " or ";
16894 else if (I + Skipped + 1 != Last)
16895 Out << ", ";
16896 }
16897 return std::string(Out.str());
16898}
16899
16901 OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads,
16902 SourceLocation StartLoc, SourceLocation LParenLoc,
16903 SourceLocation ModifierLoc, SourceLocation EndLoc) {
16904 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 60) &&
16905 "Unexpected num_threads modifier in OpenMP < 60.");
16906
16907 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTHREADS_unknown) {
16908 std::string Values = getListOfPossibleValues(OMPC_num_threads, /*First=*/0,
16910 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
16911 << Values << getOpenMPClauseNameForDiag(OMPC_num_threads);
16912 return nullptr;
16913 }
16914
16915 Expr *ValExpr = NumThreads;
16916 Stmt *HelperValStmt = nullptr;
16917
16918 // OpenMP [2.5, Restrictions]
16919 // The num_threads expression must evaluate to a positive integer value.
16920 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads,
16921 /*StrictlyPositive=*/true))
16922 return nullptr;
16923
16924 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16926 DKind, OMPC_num_threads, getLangOpts().OpenMP);
16927 if (CaptureRegion != OMPD_unknown &&
16928 !SemaRef.CurContext->isDependentContext()) {
16929 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16930 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16931 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16932 HelperValStmt = buildPreInits(getASTContext(), Captures);
16933 }
16934
16935 return new (getASTContext())
16936 OMPNumThreadsClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
16937 StartLoc, LParenLoc, ModifierLoc, EndLoc);
16938}
16939
16941 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
16942 bool SuppressExprDiags) {
16943 if (!E)
16944 return ExprError();
16945 if (E->isValueDependent() || E->isTypeDependent() ||
16947 return E;
16948
16949 llvm::APSInt Result;
16950 ExprResult ICE;
16951 if (SuppressExprDiags) {
16952 // Use a custom diagnoser that suppresses 'note' diagnostics about the
16953 // expression.
16954 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
16955 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
16957 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
16958 llvm_unreachable("Diagnostic suppressed");
16959 }
16960 } Diagnoser;
16961 ICE = SemaRef.VerifyIntegerConstantExpression(E, &Result, Diagnoser,
16963 } else {
16964 ICE =
16965 SemaRef.VerifyIntegerConstantExpression(E, &Result,
16966 /*FIXME*/ AllowFoldKind::Allow);
16967 }
16968 if (ICE.isInvalid())
16969 return ExprError();
16970
16971 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
16972 (!StrictlyPositive && !Result.isNonNegative())) {
16973 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
16974 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
16975 << E->getSourceRange();
16976 return ExprError();
16977 }
16978 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
16979 CKind == OMPC_allocate) &&
16980 !Result.isPowerOf2()) {
16981 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
16982 << E->getSourceRange();
16983 return ExprError();
16984 }
16985
16986 if (!Result.isRepresentableByInt64()) {
16987 Diag(E->getExprLoc(), diag::err_omp_large_expression_in_clause)
16989 return ExprError();
16990 }
16991
16992 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
16993 DSAStack->setAssociatedLoops(Result.getExtValue());
16994 else if (CKind == OMPC_ordered)
16995 DSAStack->setAssociatedLoops(Result.getExtValue());
16996 return ICE;
16997}
16998
16999void SemaOpenMP::setOpenMPDeviceNum(int Num) { DeviceNum = Num; }
17000
17001void SemaOpenMP::setOpenMPDeviceNumID(StringRef ID) { DeviceNumID = ID; }
17002
17003int SemaOpenMP::getOpenMPDeviceNum() const { return DeviceNum; }
17004
17006 llvm::APSInt Result;
17007 Expr::EvalResult EvalResult;
17008 // Evaluate the expression to an integer value
17009 if (!DeviceNumExpr->isValueDependent() &&
17010 DeviceNumExpr->EvaluateAsInt(EvalResult, SemaRef.Context)) {
17011 // The device expression must evaluate to a non-negative integer value.
17012 Result = EvalResult.Val.getInt();
17013 if (Result.isNonNegative()) {
17014 setOpenMPDeviceNum(Result.getZExtValue());
17015 } else {
17016 Diag(DeviceNumExpr->getExprLoc(),
17017 diag::err_omp_negative_expression_in_clause)
17018 << "device_num" << 0 << DeviceNumExpr->getSourceRange();
17019 }
17020 } else if (auto *DeclRef = dyn_cast<DeclRefExpr>(DeviceNumExpr)) {
17021 // Check if the expression is an identifier
17022 IdentifierInfo *IdInfo = DeclRef->getDecl()->getIdentifier();
17023 if (IdInfo) {
17024 setOpenMPDeviceNumID(IdInfo->getName());
17025 }
17026 } else {
17027 Diag(DeviceNumExpr->getExprLoc(), diag::err_expected_expression);
17028 }
17029}
17030
17032 SourceLocation StartLoc,
17033 SourceLocation LParenLoc,
17034 SourceLocation EndLoc) {
17035 // OpenMP [2.8.1, simd construct, Description]
17036 // The parameter of the safelen clause must be a constant
17037 // positive integer expression.
17038 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
17039 if (Safelen.isInvalid())
17040 return nullptr;
17041 return new (getASTContext())
17042 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
17043}
17044
17046 SourceLocation StartLoc,
17047 SourceLocation LParenLoc,
17048 SourceLocation EndLoc) {
17049 // OpenMP [2.8.1, simd construct, Description]
17050 // The parameter of the simdlen clause must be a constant
17051 // positive integer expression.
17052 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
17053 if (Simdlen.isInvalid())
17054 return nullptr;
17055 return new (getASTContext())
17056 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
17057}
17058
17059/// Tries to find omp_allocator_handle_t type.
17061 DSAStackTy *Stack) {
17062 if (!Stack->getOMPAllocatorHandleT().isNull())
17063 return true;
17064
17065 // Set the allocator handle type.
17066 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
17067 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
17068 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
17069 S.Diag(Loc, diag::err_omp_implied_type_not_found)
17070 << "omp_allocator_handle_t";
17071 return false;
17072 }
17073 QualType AllocatorHandleEnumTy = PT.get();
17074 AllocatorHandleEnumTy.addConst();
17075 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
17076
17077 // Fill the predefined allocator map.
17078 bool ErrorFound = false;
17079 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
17080 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
17081 StringRef Allocator =
17082 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
17083 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
17084 auto *VD = dyn_cast_or_null<ValueDecl>(
17085 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
17086 if (!VD) {
17087 ErrorFound = true;
17088 break;
17089 }
17090 QualType AllocatorType =
17092 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
17093 if (!Res.isUsable()) {
17094 ErrorFound = true;
17095 break;
17096 }
17097 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
17099 /*AllowExplicit=*/true);
17100 if (!Res.isUsable()) {
17101 ErrorFound = true;
17102 break;
17103 }
17104 Stack->setAllocator(AllocatorKind, Res.get());
17105 }
17106 if (ErrorFound) {
17107 S.Diag(Loc, diag::err_omp_implied_type_not_found)
17108 << "omp_allocator_handle_t";
17109 return false;
17110 }
17111
17112 return true;
17113}
17114
17116 SourceLocation StartLoc,
17117 SourceLocation LParenLoc,
17118 SourceLocation EndLoc) {
17119 // OpenMP [2.11.3, allocate Directive, Description]
17120 // allocator is an expression of omp_allocator_handle_t type.
17122 return nullptr;
17123
17124 ExprResult Allocator = SemaRef.DefaultLvalueConversion(A);
17125 if (Allocator.isInvalid())
17126 return nullptr;
17127 Allocator = SemaRef.PerformImplicitConversion(
17128 Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
17130 /*AllowExplicit=*/true);
17131 if (Allocator.isInvalid())
17132 return nullptr;
17133 return new (getASTContext())
17134 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
17135}
17136
17138 SourceLocation StartLoc,
17139 SourceLocation LParenLoc,
17140 SourceLocation EndLoc) {
17141 // OpenMP [2.7.1, loop construct, Description]
17142 // OpenMP [2.8.1, simd construct, Description]
17143 // OpenMP [2.9.6, distribute construct, Description]
17144 // The parameter of the collapse clause must be a constant
17145 // positive integer expression.
17146 ExprResult NumForLoopsResult =
17147 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
17148 if (NumForLoopsResult.isInvalid())
17149 return nullptr;
17150 return new (getASTContext())
17151 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
17152}
17153
17155 SourceLocation EndLoc,
17156 SourceLocation LParenLoc,
17157 Expr *NumForLoops) {
17158 // OpenMP [2.7.1, loop construct, Description]
17159 // OpenMP [2.8.1, simd construct, Description]
17160 // OpenMP [2.9.6, distribute construct, Description]
17161 // The parameter of the ordered clause must be a constant
17162 // positive integer expression if any.
17163 if (NumForLoops && LParenLoc.isValid()) {
17164 ExprResult NumForLoopsResult =
17165 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
17166 if (NumForLoopsResult.isInvalid())
17167 return nullptr;
17168 NumForLoops = NumForLoopsResult.get();
17169 } else {
17170 NumForLoops = nullptr;
17171 }
17172 auto *Clause =
17174 NumForLoops ? DSAStack->getAssociatedLoops() : 0,
17175 StartLoc, LParenLoc, EndLoc);
17176 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
17177 return Clause;
17178}
17179
17181 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
17182 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17183 OMPClause *Res = nullptr;
17184 switch (Kind) {
17185 case OMPC_proc_bind:
17186 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
17187 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17188 break;
17189 case OMPC_atomic_default_mem_order:
17191 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
17192 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17193 break;
17194 case OMPC_fail:
17195 Res = ActOnOpenMPFailClause(static_cast<OpenMPClauseKind>(Argument),
17196 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17197 break;
17198 case OMPC_update:
17199 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
17200 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17201 break;
17202 case OMPC_bind:
17203 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
17204 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17205 break;
17206 case OMPC_at:
17207 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
17208 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17209 break;
17210 case OMPC_severity:
17212 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
17213 LParenLoc, EndLoc);
17214 break;
17215 case OMPC_if:
17216 case OMPC_final:
17217 case OMPC_num_threads:
17218 case OMPC_safelen:
17219 case OMPC_simdlen:
17220 case OMPC_sizes:
17221 case OMPC_allocator:
17222 case OMPC_collapse:
17223 case OMPC_schedule:
17224 case OMPC_private:
17225 case OMPC_firstprivate:
17226 case OMPC_lastprivate:
17227 case OMPC_shared:
17228 case OMPC_reduction:
17229 case OMPC_task_reduction:
17230 case OMPC_in_reduction:
17231 case OMPC_linear:
17232 case OMPC_aligned:
17233 case OMPC_copyin:
17234 case OMPC_copyprivate:
17235 case OMPC_ordered:
17236 case OMPC_nowait:
17237 case OMPC_untied:
17238 case OMPC_mergeable:
17239 case OMPC_threadprivate:
17240 case OMPC_groupprivate:
17241 case OMPC_allocate:
17242 case OMPC_flush:
17243 case OMPC_depobj:
17244 case OMPC_read:
17245 case OMPC_write:
17246 case OMPC_capture:
17247 case OMPC_compare:
17248 case OMPC_seq_cst:
17249 case OMPC_acq_rel:
17250 case OMPC_acquire:
17251 case OMPC_release:
17252 case OMPC_relaxed:
17253 case OMPC_depend:
17254 case OMPC_device:
17255 case OMPC_threads:
17256 case OMPC_simd:
17257 case OMPC_map:
17258 case OMPC_num_teams:
17259 case OMPC_thread_limit:
17260 case OMPC_priority:
17261 case OMPC_grainsize:
17262 case OMPC_nogroup:
17263 case OMPC_num_tasks:
17264 case OMPC_hint:
17265 case OMPC_dist_schedule:
17266 case OMPC_default:
17267 case OMPC_defaultmap:
17268 case OMPC_unknown:
17269 case OMPC_uniform:
17270 case OMPC_to:
17271 case OMPC_from:
17272 case OMPC_use_device_ptr:
17273 case OMPC_use_device_addr:
17274 case OMPC_is_device_ptr:
17275 case OMPC_has_device_addr:
17276 case OMPC_unified_address:
17277 case OMPC_unified_shared_memory:
17278 case OMPC_reverse_offload:
17279 case OMPC_dynamic_allocators:
17280 case OMPC_self_maps:
17281 case OMPC_device_type:
17282 case OMPC_match:
17283 case OMPC_nontemporal:
17284 case OMPC_destroy:
17285 case OMPC_novariants:
17286 case OMPC_nocontext:
17287 case OMPC_detach:
17288 case OMPC_inclusive:
17289 case OMPC_exclusive:
17290 case OMPC_uses_allocators:
17291 case OMPC_affinity:
17292 case OMPC_when:
17293 case OMPC_message:
17294 default:
17295 llvm_unreachable("Clause is not allowed.");
17296 }
17297 return Res;
17298}
17299
17301 llvm::omp::DefaultKind M, SourceLocation MLoc,
17303 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17304 if (M == OMP_DEFAULT_unknown) {
17305 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17306 << getListOfPossibleValues(OMPC_default, /*First=*/0,
17307 /*Last=*/unsigned(OMP_DEFAULT_unknown))
17308 << getOpenMPClauseNameForDiag(OMPC_default);
17309 return nullptr;
17310 }
17311
17312 switch (M) {
17313 case OMP_DEFAULT_none:
17314 DSAStack->setDefaultDSANone(MLoc);
17315 break;
17316 case OMP_DEFAULT_shared:
17317 DSAStack->setDefaultDSAShared(MLoc);
17318 break;
17319 case OMP_DEFAULT_firstprivate:
17320 DSAStack->setDefaultDSAFirstPrivate(MLoc);
17321 break;
17322 case OMP_DEFAULT_private:
17323 DSAStack->setDefaultDSAPrivate(MLoc);
17324 break;
17325 default:
17326 llvm_unreachable("DSA unexpected in OpenMP default clause");
17327 }
17328
17329 switch (VCKind) {
17330 case OMPC_DEFAULT_VC_aggregate:
17331 DSAStack->setDefaultDSAVCAggregate(VCKindLoc);
17332 break;
17333 case OMPC_DEFAULT_VC_all:
17334 DSAStack->setDefaultDSAVCAll(VCKindLoc);
17335 break;
17336 case OMPC_DEFAULT_VC_allocatable:
17337 DSAStack->setDefaultDSAVCAllocatable(VCKindLoc);
17338 break;
17339 case OMPC_DEFAULT_VC_pointer:
17340 DSAStack->setDefaultDSAVCPointer(VCKindLoc);
17341 break;
17342 case OMPC_DEFAULT_VC_scalar:
17343 DSAStack->setDefaultDSAVCScalar(VCKindLoc);
17344 break;
17345 default:
17346 Diag(VCKindLoc, diag::err_omp_default_vc)
17347 << getOpenMPSimpleClauseTypeName(OMPC_default, unsigned(M));
17348 }
17349
17350 return new (getASTContext())
17351 OMPDefaultClause(M, MLoc, VCKind, VCKindLoc, StartLoc, LParenLoc, EndLoc);
17352}
17353
17355 SourceLocation KindKwLoc,
17356 SourceLocation StartLoc,
17357 SourceLocation LParenLoc,
17358 SourceLocation EndLoc) {
17359 if (Kind == OMP_PROC_BIND_unknown) {
17360 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17361 << getListOfPossibleValues(OMPC_proc_bind,
17362 /*First=*/unsigned(OMP_PROC_BIND_master),
17363 /*Last=*/
17364 unsigned(getLangOpts().OpenMP > 50
17365 ? OMP_PROC_BIND_primary
17366 : OMP_PROC_BIND_spread) +
17367 1)
17368 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
17369 return nullptr;
17370 }
17371 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
17372 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17373 << getListOfPossibleValues(OMPC_proc_bind,
17374 /*First=*/unsigned(OMP_PROC_BIND_master),
17375 /*Last=*/
17376 unsigned(OMP_PROC_BIND_spread) + 1)
17377 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
17378 return new (getASTContext())
17379 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17380}
17381
17384 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17386 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17388 OMPC_atomic_default_mem_order, /*First=*/0,
17390 << getOpenMPClauseNameForDiag(OMPC_atomic_default_mem_order);
17391 return nullptr;
17392 }
17394 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17395}
17396
17398 SourceLocation KindKwLoc,
17399 SourceLocation StartLoc,
17400 SourceLocation LParenLoc,
17401 SourceLocation EndLoc) {
17402 if (Kind == OMPC_AT_unknown) {
17403 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17404 << getListOfPossibleValues(OMPC_at, /*First=*/0,
17405 /*Last=*/OMPC_AT_unknown)
17406 << getOpenMPClauseNameForDiag(OMPC_at);
17407 return nullptr;
17408 }
17409 return new (getASTContext())
17410 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17411}
17412
17414 SourceLocation KindKwLoc,
17415 SourceLocation StartLoc,
17416 SourceLocation LParenLoc,
17417 SourceLocation EndLoc) {
17418 if (Kind == OMPC_SEVERITY_unknown) {
17419 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17420 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
17421 /*Last=*/OMPC_SEVERITY_unknown)
17422 << getOpenMPClauseNameForDiag(OMPC_severity);
17423 return nullptr;
17424 }
17425 return new (getASTContext())
17426 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17427}
17428
17430 SourceLocation StartLoc,
17431 SourceLocation LParenLoc,
17432 SourceLocation EndLoc) {
17433 assert(ME && "NULL expr in Message clause");
17434 QualType Type = ME->getType();
17435 if ((!Type->isPointerType() && !Type->isArrayType()) ||
17437 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
17438 << getOpenMPClauseNameForDiag(OMPC_message) << 0;
17439 return nullptr;
17440 }
17441
17442 Stmt *HelperValStmt = nullptr;
17443
17444 // Depending on whether this clause appears in an executable context or not,
17445 // we may or may not build a capture.
17446 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17447 OpenMPDirectiveKind CaptureRegion =
17448 DKind == OMPD_unknown ? OMPD_unknown
17450 DKind, OMPC_message, getLangOpts().OpenMP);
17451 if (CaptureRegion != OMPD_unknown &&
17452 !SemaRef.CurContext->isDependentContext()) {
17453 ME = SemaRef.MakeFullExpr(ME).get();
17454 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17455 ME = tryBuildCapture(SemaRef, ME, Captures).get();
17456 HelperValStmt = buildPreInits(getASTContext(), Captures);
17457 }
17458
17459 // Convert array type to pointer type if needed.
17460 ME = SemaRef.DefaultFunctionArrayLvalueConversion(ME).get();
17461
17462 return new (getASTContext()) OMPMessageClause(
17463 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17464}
17465
17468 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
17469 SourceLocation KindLoc, SourceLocation EndLoc) {
17470 if (Kind != OMPC_ORDER_concurrent ||
17471 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
17472 // Kind should be concurrent,
17473 // Modifiers introduced in OpenMP 5.1
17474 static_assert(OMPC_ORDER_unknown > 0,
17475 "OMPC_ORDER_unknown not greater than 0");
17476
17477 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17478 << getListOfPossibleValues(OMPC_order,
17479 /*First=*/0,
17480 /*Last=*/OMPC_ORDER_unknown)
17481 << getOpenMPClauseNameForDiag(OMPC_order);
17482 return nullptr;
17483 }
17484 if (getLangOpts().OpenMP >= 51 && Modifier == OMPC_ORDER_MODIFIER_unknown &&
17485 MLoc.isValid()) {
17486 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17487 << getListOfPossibleValues(OMPC_order,
17488 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
17489 /*Last=*/OMPC_ORDER_MODIFIER_last)
17490 << getOpenMPClauseNameForDiag(OMPC_order);
17491 } else if (getLangOpts().OpenMP >= 50) {
17492 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
17493 if (DSAStack->getCurScope()) {
17494 // mark the current scope with 'order' flag
17495 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
17496 DSAStack->getCurScope()->setFlags(existingFlags |
17498 }
17499 }
17500 return new (getASTContext()) OMPOrderClause(
17501 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
17502}
17503
17505 SourceLocation KindKwLoc,
17506 SourceLocation StartLoc,
17507 SourceLocation LParenLoc,
17508 SourceLocation EndLoc) {
17509 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
17510 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
17511 SmallVector<unsigned> Except = {
17512 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
17513 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
17514 if (getLangOpts().OpenMP < 51)
17515 Except.push_back(OMPC_DEPEND_inoutset);
17516 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17517 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
17518 /*Last=*/OMPC_DEPEND_unknown, Except)
17519 << getOpenMPClauseNameForDiag(OMPC_update);
17520 return nullptr;
17521 }
17522 return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc,
17523 KindKwLoc, Kind, EndLoc);
17524}
17525
17527 SourceLocation StartLoc,
17528 SourceLocation LParenLoc,
17529 SourceLocation EndLoc) {
17530 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
17531
17532 for (Expr *&SizeExpr : SanitizedSizeExprs) {
17533 // Skip if already sanitized, e.g. during a partial template instantiation.
17534 if (!SizeExpr)
17535 continue;
17536
17537 bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes,
17538 /*StrictlyPositive=*/true);
17539
17540 // isNonNegativeIntegerValue returns true for non-integral types (but still
17541 // emits error diagnostic), so check for the expected type explicitly.
17542 QualType SizeTy = SizeExpr->getType();
17543 if (!SizeTy->isIntegerType())
17544 IsValid = false;
17545
17546 // Handling in templates is tricky. There are four possibilities to
17547 // consider:
17548 //
17549 // 1a. The expression is valid and we are in a instantiated template or not
17550 // in a template:
17551 // Pass valid expression to be further analysed later in Sema.
17552 // 1b. The expression is valid and we are in a template (including partial
17553 // instantiation):
17554 // isNonNegativeIntegerValue skipped any checks so there is no
17555 // guarantee it will be correct after instantiation.
17556 // ActOnOpenMPSizesClause will be called again at instantiation when
17557 // it is not in a dependent context anymore. This may cause warnings
17558 // to be emitted multiple times.
17559 // 2a. The expression is invalid and we are in an instantiated template or
17560 // not in a template:
17561 // Invalidate the expression with a clearly wrong value (nullptr) so
17562 // later in Sema we do not have to do the same validity analysis again
17563 // or crash from unexpected data. Error diagnostics have already been
17564 // emitted.
17565 // 2b. The expression is invalid and we are in a template (including partial
17566 // instantiation):
17567 // Pass the invalid expression as-is, template instantiation may
17568 // replace unexpected types/values with valid ones. The directives
17569 // with this clause must not try to use these expressions in dependent
17570 // contexts, but delay analysis until full instantiation.
17571 if (!SizeExpr->isInstantiationDependent() && !IsValid)
17572 SizeExpr = nullptr;
17573 }
17574
17575 return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17576 SanitizedSizeExprs);
17577}
17578
17580 SourceLocation StartLoc,
17581 SourceLocation LParenLoc,
17582 SourceLocation EndLoc) {
17583 size_t NumLoops = PermExprs.size();
17584 SmallVector<Expr *> SanitizedPermExprs;
17585 llvm::append_range(SanitizedPermExprs, PermExprs);
17586
17587 for (Expr *&PermExpr : SanitizedPermExprs) {
17588 // Skip if template-dependent or already sanitized, e.g. during a partial
17589 // template instantiation.
17590 if (!PermExpr || PermExpr->isInstantiationDependent())
17591 continue;
17592
17593 llvm::APSInt PermVal;
17594 ExprResult PermEvalExpr = SemaRef.VerifyIntegerConstantExpression(
17595 PermExpr, &PermVal, AllowFoldKind::Allow);
17596 bool IsValid = PermEvalExpr.isUsable();
17597 if (IsValid)
17598 PermExpr = PermEvalExpr.get();
17599
17600 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
17601 SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
17602 PermEvalExpr.get()->getEndLoc());
17603 Diag(PermEvalExpr.get()->getExprLoc(),
17604 diag::err_omp_interchange_permutation_value_range)
17605 << NumLoops << ExprRange;
17606 IsValid = false;
17607 }
17608
17609 if (!PermExpr->isInstantiationDependent() && !IsValid)
17610 PermExpr = nullptr;
17611 }
17612
17613 return OMPPermutationClause::Create(getASTContext(), StartLoc, LParenLoc,
17614 EndLoc, SanitizedPermExprs);
17615}
17616
17618 SourceLocation EndLoc) {
17619 return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc);
17620}
17621
17623 SourceLocation StartLoc,
17624 SourceLocation LParenLoc,
17625 SourceLocation EndLoc) {
17626 if (FactorExpr) {
17627 // If an argument is specified, it must be a constant (or an unevaluated
17628 // template expression).
17630 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
17631 if (FactorResult.isInvalid())
17632 return nullptr;
17633 FactorExpr = FactorResult.get();
17634 }
17635
17636 return OMPPartialClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17637 FactorExpr);
17638}
17639
17641 Expr *First, Expr *Count, SourceLocation StartLoc, SourceLocation LParenLoc,
17642 SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc) {
17643
17644 // OpenMP [6.0, Restrictions]
17645 // First and Count must be integer expressions with positive value
17646 ExprResult FirstVal =
17648 if (FirstVal.isInvalid())
17649 First = nullptr;
17650
17651 ExprResult CountVal =
17652 VerifyPositiveIntegerConstantInClause(Count, OMPC_looprange);
17653 if (CountVal.isInvalid())
17654 Count = nullptr;
17655
17656 // OpenMP [6.0, Restrictions]
17657 // first + count - 1 must not evaluate to a value greater than the
17658 // loop sequence length of the associated canonical loop sequence.
17659 // This check must be performed afterwards due to the delayed
17660 // parsing and computation of the associated loop sequence
17661 return OMPLoopRangeClause::Create(getASTContext(), StartLoc, LParenLoc,
17662 FirstLoc, CountLoc, EndLoc, First, Count);
17663}
17664
17666 SourceLocation LParenLoc,
17667 SourceLocation EndLoc) {
17668 ExprResult AlignVal;
17669 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
17670 if (AlignVal.isInvalid())
17671 return nullptr;
17672 return OMPAlignClause::Create(getASTContext(), AlignVal.get(), StartLoc,
17673 LParenLoc, EndLoc);
17674}
17675
17678 SourceLocation StartLoc, SourceLocation LParenLoc,
17679 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
17680 SourceLocation EndLoc) {
17681 OMPClause *Res = nullptr;
17682 switch (Kind) {
17683 case OMPC_schedule:
17684 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
17685 assert(Argument.size() == NumberOfElements &&
17686 ArgumentLoc.size() == NumberOfElements);
17688 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
17689 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
17690 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
17691 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
17692 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
17693 break;
17694 case OMPC_if:
17695 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17696 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
17697 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
17698 DelimLoc, EndLoc);
17699 break;
17700 case OMPC_dist_schedule:
17702 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
17703 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
17704 break;
17705 case OMPC_default:
17706 enum { DefaultModifier, DefaultVarCategory };
17708 static_cast<llvm::omp::DefaultKind>(Argument[DefaultModifier]),
17709 ArgumentLoc[DefaultModifier],
17711 Argument[DefaultVarCategory]),
17712 ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc);
17713 break;
17714 case OMPC_defaultmap:
17715 enum { Modifier, DefaultmapKind };
17717 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
17718 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
17719 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
17720 EndLoc);
17721 break;
17722 case OMPC_order:
17723 enum { OrderModifier, OrderKind };
17725 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
17726 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
17727 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
17728 break;
17729 case OMPC_device:
17730 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17732 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
17733 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17734 break;
17735 case OMPC_grainsize:
17736 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17737 "Modifier for grainsize clause and its location are expected.");
17739 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
17740 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17741 break;
17742 case OMPC_num_tasks:
17743 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17744 "Modifier for num_tasks clause and its location are expected.");
17746 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
17747 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17748 break;
17749 case OMPC_num_threads:
17750 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17751 "Modifier for num_threads clause and its location are expected.");
17753 static_cast<OpenMPNumThreadsClauseModifier>(Argument.back()), Expr,
17754 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17755 break;
17756 case OMPC_final:
17757 case OMPC_safelen:
17758 case OMPC_simdlen:
17759 case OMPC_sizes:
17760 case OMPC_allocator:
17761 case OMPC_collapse:
17762 case OMPC_proc_bind:
17763 case OMPC_private:
17764 case OMPC_firstprivate:
17765 case OMPC_lastprivate:
17766 case OMPC_shared:
17767 case OMPC_reduction:
17768 case OMPC_task_reduction:
17769 case OMPC_in_reduction:
17770 case OMPC_linear:
17771 case OMPC_aligned:
17772 case OMPC_copyin:
17773 case OMPC_copyprivate:
17774 case OMPC_ordered:
17775 case OMPC_nowait:
17776 case OMPC_untied:
17777 case OMPC_mergeable:
17778 case OMPC_threadprivate:
17779 case OMPC_groupprivate:
17780 case OMPC_allocate:
17781 case OMPC_flush:
17782 case OMPC_depobj:
17783 case OMPC_read:
17784 case OMPC_write:
17785 case OMPC_update:
17786 case OMPC_capture:
17787 case OMPC_compare:
17788 case OMPC_seq_cst:
17789 case OMPC_acq_rel:
17790 case OMPC_acquire:
17791 case OMPC_release:
17792 case OMPC_relaxed:
17793 case OMPC_depend:
17794 case OMPC_threads:
17795 case OMPC_simd:
17796 case OMPC_map:
17797 case OMPC_num_teams:
17798 case OMPC_thread_limit:
17799 case OMPC_priority:
17800 case OMPC_nogroup:
17801 case OMPC_hint:
17802 case OMPC_unknown:
17803 case OMPC_uniform:
17804 case OMPC_to:
17805 case OMPC_from:
17806 case OMPC_use_device_ptr:
17807 case OMPC_use_device_addr:
17808 case OMPC_is_device_ptr:
17809 case OMPC_has_device_addr:
17810 case OMPC_unified_address:
17811 case OMPC_unified_shared_memory:
17812 case OMPC_reverse_offload:
17813 case OMPC_dynamic_allocators:
17814 case OMPC_atomic_default_mem_order:
17815 case OMPC_self_maps:
17816 case OMPC_device_type:
17817 case OMPC_match:
17818 case OMPC_nontemporal:
17819 case OMPC_at:
17820 case OMPC_severity:
17821 case OMPC_message:
17822 case OMPC_destroy:
17823 case OMPC_novariants:
17824 case OMPC_nocontext:
17825 case OMPC_detach:
17826 case OMPC_inclusive:
17827 case OMPC_exclusive:
17828 case OMPC_uses_allocators:
17829 case OMPC_affinity:
17830 case OMPC_when:
17831 case OMPC_bind:
17832 default:
17833 llvm_unreachable("Clause is not allowed.");
17834 }
17835 return Res;
17836}
17837
17840 SourceLocation M1Loc, SourceLocation M2Loc) {
17841 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
17842 SmallVector<unsigned, 2> Excluded;
17844 Excluded.push_back(M2);
17845 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
17846 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
17847 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
17848 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
17849 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
17850 << getListOfPossibleValues(OMPC_schedule,
17851 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
17853 Excluded)
17854 << getOpenMPClauseNameForDiag(OMPC_schedule);
17855 return true;
17856 }
17857 return false;
17858}
17859
17862 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
17863 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
17864 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
17865 if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) ||
17866 checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc))
17867 return nullptr;
17868 // OpenMP, 2.7.1, Loop Construct, Restrictions
17869 // Either the monotonic modifier or the nonmonotonic modifier can be specified
17870 // but not both.
17871 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
17872 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
17873 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
17874 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
17875 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
17876 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
17877 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
17878 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
17879 return nullptr;
17880 }
17881 if (Kind == OMPC_SCHEDULE_unknown) {
17882 std::string Values;
17883 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
17884 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
17885 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17887 Exclude);
17888 } else {
17889 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17890 /*Last=*/OMPC_SCHEDULE_unknown);
17891 }
17892 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17893 << Values << getOpenMPClauseNameForDiag(OMPC_schedule);
17894 return nullptr;
17895 }
17896 // OpenMP, 2.7.1, Loop Construct, Restrictions
17897 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
17898 // schedule(guided).
17899 // OpenMP 5.0 does not have this restriction.
17900 if (getLangOpts().OpenMP < 50 &&
17901 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
17902 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
17903 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
17904 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
17905 diag::err_omp_schedule_nonmonotonic_static);
17906 return nullptr;
17907 }
17908 Expr *ValExpr = ChunkSize;
17909 Stmt *HelperValStmt = nullptr;
17910 if (ChunkSize) {
17911 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
17912 !ChunkSize->isInstantiationDependent() &&
17913 !ChunkSize->containsUnexpandedParameterPack()) {
17914 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
17915 ExprResult Val =
17916 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
17917 if (Val.isInvalid())
17918 return nullptr;
17919
17920 ValExpr = Val.get();
17921
17922 // OpenMP [2.7.1, Restrictions]
17923 // chunk_size must be a loop invariant integer expression with a positive
17924 // value.
17925 if (std::optional<llvm::APSInt> Result =
17927 if (Result->isSigned() && !Result->isStrictlyPositive()) {
17928 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
17929 << "schedule" << 1 << ChunkSize->getSourceRange();
17930 return nullptr;
17931 }
17933 DSAStack->getCurrentDirective(), OMPC_schedule,
17934 getLangOpts().OpenMP) != OMPD_unknown &&
17935 !SemaRef.CurContext->isDependentContext()) {
17936 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17937 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17938 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17939 HelperValStmt = buildPreInits(getASTContext(), Captures);
17940 }
17941 }
17942 }
17943
17944 return new (getASTContext())
17945 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
17946 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
17947}
17948
17950 SourceLocation StartLoc,
17951 SourceLocation EndLoc) {
17952 OMPClause *Res = nullptr;
17953 switch (Kind) {
17954 case OMPC_ordered:
17955 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
17956 break;
17957 case OMPC_nowait:
17958 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
17959 break;
17960 case OMPC_untied:
17961 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
17962 break;
17963 case OMPC_mergeable:
17964 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
17965 break;
17966 case OMPC_read:
17967 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
17968 break;
17969 case OMPC_write:
17970 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
17971 break;
17972 case OMPC_update:
17973 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
17974 break;
17975 case OMPC_capture:
17976 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
17977 break;
17978 case OMPC_compare:
17979 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
17980 break;
17981 case OMPC_fail:
17982 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
17983 break;
17984 case OMPC_seq_cst:
17985 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
17986 break;
17987 case OMPC_acq_rel:
17988 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
17989 break;
17990 case OMPC_acquire:
17991 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
17992 break;
17993 case OMPC_release:
17994 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
17995 break;
17996 case OMPC_relaxed:
17997 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
17998 break;
17999 case OMPC_weak:
18000 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
18001 break;
18002 case OMPC_threads:
18003 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
18004 break;
18005 case OMPC_simd:
18006 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
18007 break;
18008 case OMPC_nogroup:
18009 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
18010 break;
18011 case OMPC_unified_address:
18012 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
18013 break;
18014 case OMPC_unified_shared_memory:
18015 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
18016 break;
18017 case OMPC_reverse_offload:
18018 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
18019 break;
18020 case OMPC_dynamic_allocators:
18021 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
18022 break;
18023 case OMPC_self_maps:
18024 Res = ActOnOpenMPSelfMapsClause(StartLoc, EndLoc);
18025 break;
18026 case OMPC_destroy:
18027 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
18028 /*LParenLoc=*/SourceLocation(),
18029 /*VarLoc=*/SourceLocation(), EndLoc);
18030 break;
18031 case OMPC_full:
18032 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
18033 break;
18034 case OMPC_partial:
18035 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
18036 break;
18037 case OMPC_ompx_bare:
18038 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
18039 break;
18040 case OMPC_if:
18041 case OMPC_final:
18042 case OMPC_num_threads:
18043 case OMPC_safelen:
18044 case OMPC_simdlen:
18045 case OMPC_sizes:
18046 case OMPC_allocator:
18047 case OMPC_collapse:
18048 case OMPC_schedule:
18049 case OMPC_private:
18050 case OMPC_firstprivate:
18051 case OMPC_lastprivate:
18052 case OMPC_shared:
18053 case OMPC_reduction:
18054 case OMPC_task_reduction:
18055 case OMPC_in_reduction:
18056 case OMPC_linear:
18057 case OMPC_aligned:
18058 case OMPC_copyin:
18059 case OMPC_copyprivate:
18060 case OMPC_default:
18061 case OMPC_proc_bind:
18062 case OMPC_threadprivate:
18063 case OMPC_groupprivate:
18064 case OMPC_allocate:
18065 case OMPC_flush:
18066 case OMPC_depobj:
18067 case OMPC_depend:
18068 case OMPC_device:
18069 case OMPC_map:
18070 case OMPC_num_teams:
18071 case OMPC_thread_limit:
18072 case OMPC_priority:
18073 case OMPC_grainsize:
18074 case OMPC_num_tasks:
18075 case OMPC_hint:
18076 case OMPC_dist_schedule:
18077 case OMPC_defaultmap:
18078 case OMPC_unknown:
18079 case OMPC_uniform:
18080 case OMPC_to:
18081 case OMPC_from:
18082 case OMPC_use_device_ptr:
18083 case OMPC_use_device_addr:
18084 case OMPC_is_device_ptr:
18085 case OMPC_has_device_addr:
18086 case OMPC_atomic_default_mem_order:
18087 case OMPC_device_type:
18088 case OMPC_match:
18089 case OMPC_nontemporal:
18090 case OMPC_order:
18091 case OMPC_at:
18092 case OMPC_severity:
18093 case OMPC_message:
18094 case OMPC_novariants:
18095 case OMPC_nocontext:
18096 case OMPC_detach:
18097 case OMPC_inclusive:
18098 case OMPC_exclusive:
18099 case OMPC_uses_allocators:
18100 case OMPC_affinity:
18101 case OMPC_when:
18102 case OMPC_ompx_dyn_cgroup_mem:
18103 default:
18104 llvm_unreachable("Clause is not allowed.");
18105 }
18106 return Res;
18107}
18108
18110 SourceLocation EndLoc) {
18111 DSAStack->setNowaitRegion();
18112 return new (getASTContext()) OMPNowaitClause(StartLoc, EndLoc);
18113}
18114
18116 SourceLocation EndLoc) {
18117 DSAStack->setUntiedRegion();
18118 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
18119}
18120
18122 SourceLocation EndLoc) {
18123 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
18124}
18125
18127 SourceLocation EndLoc) {
18128 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
18129}
18130
18132 SourceLocation EndLoc) {
18133 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
18134}
18135
18137 SourceLocation EndLoc) {
18138 return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc);
18139}
18140
18142 SourceLocation EndLoc) {
18143 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
18144}
18145
18147 SourceLocation EndLoc) {
18148 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
18149}
18150
18152 SourceLocation EndLoc) {
18153 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
18154}
18155
18157 SourceLocation KindLoc,
18158 SourceLocation StartLoc,
18159 SourceLocation LParenLoc,
18160 SourceLocation EndLoc) {
18161
18163 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
18164 return nullptr;
18165 }
18166 return new (getASTContext())
18167 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
18168}
18169
18171 SourceLocation EndLoc) {
18172 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
18173}
18174
18176 SourceLocation EndLoc) {
18177 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
18178}
18179
18181 SourceLocation EndLoc) {
18182 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
18183}
18184
18186 SourceLocation EndLoc) {
18187 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
18188}
18189
18191 SourceLocation EndLoc) {
18192 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
18193}
18194
18196 SourceLocation EndLoc) {
18197 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
18198}
18199
18201 SourceLocation EndLoc) {
18202 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
18203}
18204
18206 SourceLocation EndLoc) {
18207 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
18208}
18209
18211 SourceLocation EndLoc) {
18212 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
18213}
18214
18216 SourceLocation EndLoc) {
18217 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
18218}
18219
18220OMPClause *
18225
18227 SourceLocation EndLoc) {
18228 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
18229}
18230
18231OMPClause *
18233 SourceLocation EndLoc) {
18234 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
18235}
18236
18238 SourceLocation EndLoc) {
18239 return new (getASTContext()) OMPSelfMapsClause(StartLoc, EndLoc);
18240}
18241
18244 SourceLocation StartLoc,
18245 SourceLocation EndLoc) {
18246
18247 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18248 // At least one action-clause must appear on a directive.
18249 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
18250 unsigned OMPVersion = getLangOpts().OpenMP;
18251 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
18252 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
18253 << Expected << getOpenMPDirectiveName(OMPD_interop, OMPVersion);
18254 return StmtError();
18255 }
18256
18257 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18258 // A depend clause can only appear on the directive if a targetsync
18259 // interop-type is present or the interop-var was initialized with
18260 // the targetsync interop-type.
18261
18262 // If there is any 'init' clause diagnose if there is no 'init' clause with
18263 // interop-type of 'targetsync'. Cases involving other directives cannot be
18264 // diagnosed.
18265 const OMPDependClause *DependClause = nullptr;
18266 bool HasInitClause = false;
18267 bool IsTargetSync = false;
18268 for (const OMPClause *C : Clauses) {
18269 if (IsTargetSync)
18270 break;
18271 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
18272 HasInitClause = true;
18273 if (InitClause->getIsTargetSync())
18274 IsTargetSync = true;
18275 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
18276 DependClause = DC;
18277 }
18278 }
18279 if (DependClause && HasInitClause && !IsTargetSync) {
18280 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
18281 return StmtError();
18282 }
18283
18284 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18285 // Each interop-var may be specified for at most one action-clause of each
18286 // interop construct.
18288 for (OMPClause *C : Clauses) {
18289 OpenMPClauseKind ClauseKind = C->getClauseKind();
18290 std::pair<ValueDecl *, bool> DeclResult;
18291 SourceLocation ELoc;
18292 SourceRange ERange;
18293
18294 if (ClauseKind == OMPC_init) {
18295 auto *E = cast<OMPInitClause>(C)->getInteropVar();
18296 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18297 } else if (ClauseKind == OMPC_use) {
18298 auto *E = cast<OMPUseClause>(C)->getInteropVar();
18299 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18300 } else if (ClauseKind == OMPC_destroy) {
18301 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
18302 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18303 }
18304
18305 if (DeclResult.first) {
18306 if (!InteropVars.insert(DeclResult.first).second) {
18307 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
18308 << DeclResult.first;
18309 return StmtError();
18310 }
18311 }
18312 }
18313
18314 return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc,
18315 Clauses);
18316}
18317
18318static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
18319 SourceLocation VarLoc,
18320 OpenMPClauseKind Kind) {
18321 SourceLocation ELoc;
18322 SourceRange ERange;
18323 Expr *RefExpr = InteropVarExpr;
18324 auto Res = getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
18325 /*AllowArraySection=*/false,
18326 /*AllowAssumedSizeArray=*/false,
18327 /*DiagType=*/"omp_interop_t");
18328
18329 if (Res.second) {
18330 // It will be analyzed later.
18331 return true;
18332 }
18333
18334 if (!Res.first)
18335 return false;
18336
18337 // Interop variable should be of type omp_interop_t.
18338 bool HasError = false;
18339 QualType InteropType;
18340 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
18341 VarLoc, Sema::LookupOrdinaryName);
18342 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
18343 NamedDecl *ND = Result.getFoundDecl();
18344 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
18345 InteropType = QualType(TD->getTypeForDecl(), 0);
18346 } else {
18347 HasError = true;
18348 }
18349 } else {
18350 HasError = true;
18351 }
18352
18353 if (HasError) {
18354 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
18355 << "omp_interop_t";
18356 return false;
18357 }
18358
18359 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
18360 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
18361 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
18362 return false;
18363 }
18364
18365 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18366 // The interop-var passed to init or destroy must be non-const.
18367 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
18368 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
18369 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
18370 << /*non-const*/ 1;
18371 return false;
18372 }
18373 return true;
18374}
18375
18377 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
18378 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
18379
18380 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init))
18381 return nullptr;
18382
18383 // Check prefer_type values. These foreign-runtime-id values are either
18384 // string literals or constant integral expressions.
18385 for (const Expr *E : InteropInfo.PreferTypes) {
18386 if (E->isValueDependent() || E->isTypeDependent() ||
18388 continue;
18390 continue;
18391 if (isa<StringLiteral>(E))
18392 continue;
18393 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
18394 return nullptr;
18395 }
18396
18397 return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo,
18398 StartLoc, LParenLoc, VarLoc, EndLoc);
18399}
18400
18402 SourceLocation StartLoc,
18403 SourceLocation LParenLoc,
18404 SourceLocation VarLoc,
18405 SourceLocation EndLoc) {
18406
18407 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use))
18408 return nullptr;
18409
18410 return new (getASTContext())
18411 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18412}
18413
18415 SourceLocation StartLoc,
18416 SourceLocation LParenLoc,
18417 SourceLocation VarLoc,
18418 SourceLocation EndLoc) {
18419 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
18420 DSAStack->getCurrentDirective() == OMPD_depobj) {
18421 unsigned OMPVersion = getLangOpts().OpenMP;
18422 Diag(StartLoc, diag::err_omp_expected_clause_argument)
18423 << getOpenMPClauseNameForDiag(OMPC_destroy)
18424 << getOpenMPDirectiveName(OMPD_depobj, OMPVersion);
18425 return nullptr;
18426 }
18427 if (InteropVar &&
18428 !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy))
18429 return nullptr;
18430
18431 return new (getASTContext())
18432 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18433}
18434
18436 SourceLocation StartLoc,
18437 SourceLocation LParenLoc,
18438 SourceLocation EndLoc) {
18439 Expr *ValExpr = Condition;
18440 Stmt *HelperValStmt = nullptr;
18441 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18442 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18443 !Condition->isInstantiationDependent() &&
18444 !Condition->containsUnexpandedParameterPack()) {
18445 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
18446 if (Val.isInvalid())
18447 return nullptr;
18448
18449 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
18450
18451 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18452 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
18453 getLangOpts().OpenMP);
18454 if (CaptureRegion != OMPD_unknown &&
18455 !SemaRef.CurContext->isDependentContext()) {
18456 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18457 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18458 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18459 HelperValStmt = buildPreInits(getASTContext(), Captures);
18460 }
18461 }
18462
18463 return new (getASTContext()) OMPNovariantsClause(
18464 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18465}
18466
18468 SourceLocation StartLoc,
18469 SourceLocation LParenLoc,
18470 SourceLocation EndLoc) {
18471 Expr *ValExpr = Condition;
18472 Stmt *HelperValStmt = nullptr;
18473 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18474 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18475 !Condition->isInstantiationDependent() &&
18476 !Condition->containsUnexpandedParameterPack()) {
18477 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
18478 if (Val.isInvalid())
18479 return nullptr;
18480
18481 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
18482
18483 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18484 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext,
18485 getLangOpts().OpenMP);
18486 if (CaptureRegion != OMPD_unknown &&
18487 !SemaRef.CurContext->isDependentContext()) {
18488 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18489 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18490 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18491 HelperValStmt = buildPreInits(getASTContext(), Captures);
18492 }
18493 }
18494
18495 return new (getASTContext()) OMPNocontextClause(
18496 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18497}
18498
18500 SourceLocation StartLoc,
18501 SourceLocation LParenLoc,
18502 SourceLocation EndLoc) {
18503 Expr *ValExpr = ThreadID;
18504 Stmt *HelperValStmt = nullptr;
18505
18506 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18507 OpenMPDirectiveKind CaptureRegion =
18508 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP);
18509 if (CaptureRegion != OMPD_unknown &&
18510 !SemaRef.CurContext->isDependentContext()) {
18511 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18512 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18513 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18514 HelperValStmt = buildPreInits(getASTContext(), Captures);
18515 }
18516
18517 return new (getASTContext()) OMPFilterClause(
18518 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18519}
18520
18522 ArrayRef<Expr *> VarList,
18523 const OMPVarListLocTy &Locs,
18525 SourceLocation StartLoc = Locs.StartLoc;
18526 SourceLocation LParenLoc = Locs.LParenLoc;
18527 SourceLocation EndLoc = Locs.EndLoc;
18528 OMPClause *Res = nullptr;
18529 int ExtraModifier = Data.ExtraModifier;
18530 int OriginalSharingModifier = Data.OriginalSharingModifier;
18531 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
18532 SourceLocation ColonLoc = Data.ColonLoc;
18533 switch (Kind) {
18534 case OMPC_private:
18535 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18536 break;
18537 case OMPC_firstprivate:
18538 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18539 break;
18540 case OMPC_lastprivate:
18541 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
18542 "Unexpected lastprivate modifier.");
18544 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
18545 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
18546 break;
18547 case OMPC_shared:
18548 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
18549 break;
18550 case OMPC_reduction:
18551 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
18552 "Unexpected lastprivate modifier.");
18554 VarList,
18556 ExtraModifier, OriginalSharingModifier),
18557 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
18558 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18559 break;
18560 case OMPC_task_reduction:
18562 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18563 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18564 break;
18565 case OMPC_in_reduction:
18567 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18568 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18569 break;
18570 case OMPC_linear:
18571 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
18572 "Unexpected linear modifier.");
18574 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
18575 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
18576 ColonLoc, Data.StepModifierLoc, EndLoc);
18577 break;
18578 case OMPC_aligned:
18579 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
18580 LParenLoc, ColonLoc, EndLoc);
18581 break;
18582 case OMPC_copyin:
18583 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
18584 break;
18585 case OMPC_copyprivate:
18586 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18587 break;
18588 case OMPC_flush:
18589 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
18590 break;
18591 case OMPC_depend:
18592 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
18593 "Unexpected depend modifier.");
18595 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
18596 ColonLoc, Data.OmpAllMemoryLoc},
18597 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
18598 break;
18599 case OMPC_map:
18600 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
18601 "Unexpected map modifier.");
18603 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
18604 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
18605 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
18606 ExtraModifierLoc, ColonLoc, VarList, Locs);
18607 break;
18608 case OMPC_to:
18609 Res =
18610 ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc,
18611 Data.ReductionOrMapperIdScopeSpec,
18612 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
18613 break;
18614 case OMPC_from:
18615 Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc,
18616 Data.ReductionOrMapperIdScopeSpec,
18617 Data.ReductionOrMapperId, ColonLoc, VarList,
18618 Locs);
18619 break;
18620 case OMPC_use_device_ptr:
18621 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
18622 break;
18623 case OMPC_use_device_addr:
18624 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
18625 break;
18626 case OMPC_is_device_ptr:
18627 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
18628 break;
18629 case OMPC_has_device_addr:
18630 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
18631 break;
18632 case OMPC_allocate: {
18635 SourceLocation Modifier1Loc, Modifier2Loc;
18636 if (!Data.AllocClauseModifiers.empty()) {
18637 assert(Data.AllocClauseModifiers.size() <= 2 &&
18638 "More allocate modifiers than expected");
18639 Modifier1 = Data.AllocClauseModifiers[0];
18640 Modifier1Loc = Data.AllocClauseModifiersLoc[0];
18641 if (Data.AllocClauseModifiers.size() == 2) {
18642 Modifier2 = Data.AllocClauseModifiers[1];
18643 Modifier2Loc = Data.AllocClauseModifiersLoc[1];
18644 }
18645 }
18647 Data.DepModOrTailExpr, Data.AllocateAlignment, Modifier1, Modifier1Loc,
18648 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
18649 EndLoc);
18650 break;
18651 }
18652 case OMPC_nontemporal:
18653 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
18654 break;
18655 case OMPC_inclusive:
18656 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18657 break;
18658 case OMPC_exclusive:
18659 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18660 break;
18661 case OMPC_affinity:
18662 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
18663 Data.DepModOrTailExpr, VarList);
18664 break;
18665 case OMPC_doacross:
18667 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
18668 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
18669 break;
18670 case OMPC_num_teams:
18671 Res = ActOnOpenMPNumTeamsClause(VarList, StartLoc, LParenLoc, EndLoc);
18672 break;
18673 case OMPC_thread_limit:
18674 Res = ActOnOpenMPThreadLimitClause(VarList, StartLoc, LParenLoc, EndLoc);
18675 break;
18676 case OMPC_if:
18677 case OMPC_depobj:
18678 case OMPC_final:
18679 case OMPC_num_threads:
18680 case OMPC_safelen:
18681 case OMPC_simdlen:
18682 case OMPC_sizes:
18683 case OMPC_allocator:
18684 case OMPC_collapse:
18685 case OMPC_default:
18686 case OMPC_proc_bind:
18687 case OMPC_schedule:
18688 case OMPC_ordered:
18689 case OMPC_nowait:
18690 case OMPC_untied:
18691 case OMPC_mergeable:
18692 case OMPC_threadprivate:
18693 case OMPC_groupprivate:
18694 case OMPC_read:
18695 case OMPC_write:
18696 case OMPC_update:
18697 case OMPC_capture:
18698 case OMPC_compare:
18699 case OMPC_seq_cst:
18700 case OMPC_acq_rel:
18701 case OMPC_acquire:
18702 case OMPC_release:
18703 case OMPC_relaxed:
18704 case OMPC_device:
18705 case OMPC_threads:
18706 case OMPC_simd:
18707 case OMPC_priority:
18708 case OMPC_grainsize:
18709 case OMPC_nogroup:
18710 case OMPC_num_tasks:
18711 case OMPC_hint:
18712 case OMPC_dist_schedule:
18713 case OMPC_defaultmap:
18714 case OMPC_unknown:
18715 case OMPC_uniform:
18716 case OMPC_unified_address:
18717 case OMPC_unified_shared_memory:
18718 case OMPC_reverse_offload:
18719 case OMPC_dynamic_allocators:
18720 case OMPC_atomic_default_mem_order:
18721 case OMPC_self_maps:
18722 case OMPC_device_type:
18723 case OMPC_match:
18724 case OMPC_order:
18725 case OMPC_at:
18726 case OMPC_severity:
18727 case OMPC_message:
18728 case OMPC_destroy:
18729 case OMPC_novariants:
18730 case OMPC_nocontext:
18731 case OMPC_detach:
18732 case OMPC_uses_allocators:
18733 case OMPC_when:
18734 case OMPC_bind:
18735 default:
18736 llvm_unreachable("Clause is not allowed.");
18737 }
18738 return Res;
18739}
18740
18742 ExprObjectKind OK,
18743 SourceLocation Loc) {
18744 ExprResult Res = SemaRef.BuildDeclRefExpr(
18745 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
18746 if (!Res.isUsable())
18747 return ExprError();
18748 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
18749 Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
18750 if (!Res.isUsable())
18751 return ExprError();
18752 }
18753 if (VK != VK_LValue && Res.get()->isGLValue()) {
18754 Res = SemaRef.DefaultLvalueConversion(Res.get());
18755 if (!Res.isUsable())
18756 return ExprError();
18757 }
18758 return Res;
18759}
18760
18762 SourceLocation StartLoc,
18763 SourceLocation LParenLoc,
18764 SourceLocation EndLoc) {
18766 SmallVector<Expr *, 8> PrivateCopies;
18767 unsigned OMPVersion = getLangOpts().OpenMP;
18768 bool IsImplicitClause =
18769 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18770 for (Expr *RefExpr : VarList) {
18771 assert(RefExpr && "NULL expr in OpenMP private clause.");
18772 SourceLocation ELoc;
18773 SourceRange ERange;
18774 Expr *SimpleRefExpr = RefExpr;
18775 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
18776 if (Res.second) {
18777 // It will be analyzed later.
18778 Vars.push_back(RefExpr);
18779 PrivateCopies.push_back(nullptr);
18780 }
18781 ValueDecl *D = Res.first;
18782 if (!D)
18783 continue;
18784
18785 QualType Type = D->getType();
18786 auto *VD = dyn_cast<VarDecl>(D);
18787
18788 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18789 // A variable that appears in a private clause must not have an incomplete
18790 // type or a reference type.
18791 if (SemaRef.RequireCompleteType(ELoc, Type,
18792 diag::err_omp_private_incomplete_type))
18793 continue;
18794 Type = Type.getNonReferenceType();
18795
18796 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18797 // A variable that is privatized must not have a const-qualified type
18798 // unless it is of class type with a mutable member. This restriction does
18799 // not apply to the firstprivate clause.
18800 //
18801 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
18802 // A variable that appears in a private clause must not have a
18803 // const-qualified type unless it is of class type with a mutable member.
18804 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc))
18805 continue;
18806
18807 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18808 // in a Construct]
18809 // Variables with the predetermined data-sharing attributes may not be
18810 // listed in data-sharing attributes clauses, except for the cases
18811 // listed below. For these exceptions only, listing a predetermined
18812 // variable in a data-sharing attribute clause is allowed and overrides
18813 // the variable's predetermined data-sharing attributes.
18814 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18815 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
18816 Diag(ELoc, diag::err_omp_wrong_dsa)
18817 << getOpenMPClauseNameForDiag(DVar.CKind)
18818 << getOpenMPClauseNameForDiag(OMPC_private);
18820 continue;
18821 }
18822
18823 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18824 // Variably modified types are not supported for tasks.
18826 isOpenMPTaskingDirective(CurrDir)) {
18827 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18828 << getOpenMPClauseNameForDiag(OMPC_private) << Type
18829 << getOpenMPDirectiveName(CurrDir, OMPVersion);
18830 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
18832 Diag(D->getLocation(),
18833 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18834 << D;
18835 continue;
18836 }
18837
18838 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18839 // A list item cannot appear in both a map clause and a data-sharing
18840 // attribute clause on the same construct
18841 //
18842 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18843 // A list item cannot appear in both a map clause and a data-sharing
18844 // attribute clause on the same construct unless the construct is a
18845 // combined construct.
18846 if ((getLangOpts().OpenMP <= 45 &&
18848 CurrDir == OMPD_target) {
18849 OpenMPClauseKind ConflictKind;
18850 if (DSAStack->checkMappableExprComponentListsForDecl(
18851 VD, /*CurrentRegionOnly=*/true,
18853 OpenMPClauseKind WhereFoundClauseKind) -> bool {
18854 ConflictKind = WhereFoundClauseKind;
18855 return true;
18856 })) {
18857 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18858 << getOpenMPClauseNameForDiag(OMPC_private)
18859 << getOpenMPClauseNameForDiag(ConflictKind)
18860 << getOpenMPDirectiveName(CurrDir, OMPVersion);
18862 continue;
18863 }
18864 }
18865
18866 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
18867 // A variable of class type (or array thereof) that appears in a private
18868 // clause requires an accessible, unambiguous default constructor for the
18869 // class type.
18870 // Generate helper private variable and initialize it with the default
18871 // value. The address of the original variable is replaced by the address of
18872 // the new private variable in CodeGen. This new variable is not added to
18873 // IdResolver, so the code in the OpenMP region uses original variable for
18874 // proper diagnostics.
18875 Type = Type.getUnqualifiedType();
18876 VarDecl *VDPrivate =
18877 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
18878 D->hasAttrs() ? &D->getAttrs() : nullptr,
18879 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18880 SemaRef.ActOnUninitializedDecl(VDPrivate);
18881 if (VDPrivate->isInvalidDecl())
18882 continue;
18883 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18884 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
18885
18886 DeclRefExpr *Ref = nullptr;
18887 if (!VD && !SemaRef.CurContext->isDependentContext()) {
18888 auto *FD = dyn_cast<FieldDecl>(D);
18889 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18890 if (VD)
18892 RefExpr->getExprLoc());
18893 else
18894 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
18895 }
18896 if (!IsImplicitClause)
18897 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
18898 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
18899 ? RefExpr->IgnoreParens()
18900 : Ref);
18901 PrivateCopies.push_back(VDPrivateRefExpr);
18902 }
18903
18904 if (Vars.empty())
18905 return nullptr;
18906
18907 return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
18908 Vars, PrivateCopies);
18909}
18910
18912 SourceLocation StartLoc,
18913 SourceLocation LParenLoc,
18914 SourceLocation EndLoc) {
18916 SmallVector<Expr *, 8> PrivateCopies;
18918 SmallVector<Decl *, 4> ExprCaptures;
18919 bool IsImplicitClause =
18920 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18921 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
18922 unsigned OMPVersion = getLangOpts().OpenMP;
18923
18924 for (Expr *RefExpr : VarList) {
18925 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
18926 SourceLocation ELoc;
18927 SourceRange ERange;
18928 Expr *SimpleRefExpr = RefExpr;
18929 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
18930 if (Res.second) {
18931 // It will be analyzed later.
18932 Vars.push_back(RefExpr);
18933 PrivateCopies.push_back(nullptr);
18934 Inits.push_back(nullptr);
18935 }
18936 ValueDecl *D = Res.first;
18937 if (!D)
18938 continue;
18939
18940 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
18941 QualType Type = D->getType();
18942 auto *VD = dyn_cast<VarDecl>(D);
18943
18944 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18945 // A variable that appears in a private clause must not have an incomplete
18946 // type or a reference type.
18947 if (SemaRef.RequireCompleteType(ELoc, Type,
18948 diag::err_omp_firstprivate_incomplete_type))
18949 continue;
18950 Type = Type.getNonReferenceType();
18951
18952 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
18953 // A variable of class type (or array thereof) that appears in a private
18954 // clause requires an accessible, unambiguous copy constructor for the
18955 // class type.
18956 QualType ElemType =
18958
18959 // If an implicit firstprivate variable found it was checked already.
18960 DSAStackTy::DSAVarData TopDVar;
18961 if (!IsImplicitClause) {
18962 DSAStackTy::DSAVarData DVar =
18963 DSAStack->getTopDSA(D, /*FromParent=*/false);
18964 TopDVar = DVar;
18965 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18966 bool IsConstant = ElemType.isConstant(getASTContext());
18967 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
18968 // A list item that specifies a given variable may not appear in more
18969 // than one clause on the same directive, except that a variable may be
18970 // specified in both firstprivate and lastprivate clauses.
18971 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18972 // A list item may appear in a firstprivate or lastprivate clause but not
18973 // both.
18974 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
18975 (isOpenMPDistributeDirective(CurrDir) ||
18976 DVar.CKind != OMPC_lastprivate) &&
18977 DVar.RefExpr) {
18978 Diag(ELoc, diag::err_omp_wrong_dsa)
18979 << getOpenMPClauseNameForDiag(DVar.CKind)
18980 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
18982 continue;
18983 }
18984
18985 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18986 // in a Construct]
18987 // Variables with the predetermined data-sharing attributes may not be
18988 // listed in data-sharing attributes clauses, except for the cases
18989 // listed below. For these exceptions only, listing a predetermined
18990 // variable in a data-sharing attribute clause is allowed and overrides
18991 // the variable's predetermined data-sharing attributes.
18992 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18993 // in a Construct, C/C++, p.2]
18994 // Variables with const-qualified type having no mutable member may be
18995 // listed in a firstprivate clause, even if they are static data members.
18996 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
18997 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
18998 Diag(ELoc, diag::err_omp_wrong_dsa)
18999 << getOpenMPClauseNameForDiag(DVar.CKind)
19000 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
19002 continue;
19003 }
19004
19005 // OpenMP [2.9.3.4, Restrictions, p.2]
19006 // A list item that is private within a parallel region must not appear
19007 // in a firstprivate clause on a worksharing construct if any of the
19008 // worksharing regions arising from the worksharing construct ever bind
19009 // to any of the parallel regions arising from the parallel construct.
19010 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
19011 // A list item that is private within a teams region must not appear in a
19012 // firstprivate clause on a distribute construct if any of the distribute
19013 // regions arising from the distribute construct ever bind to any of the
19014 // teams regions arising from the teams construct.
19015 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
19016 // A list item that appears in a reduction clause of a teams construct
19017 // must not appear in a firstprivate clause on a distribute construct if
19018 // any of the distribute regions arising from the distribute construct
19019 // ever bind to any of the teams regions arising from the teams construct.
19020 if ((isOpenMPWorksharingDirective(CurrDir) ||
19021 isOpenMPDistributeDirective(CurrDir)) &&
19022 !isOpenMPParallelDirective(CurrDir) &&
19023 !isOpenMPTeamsDirective(CurrDir)) {
19024 DVar = DSAStack->getImplicitDSA(D, true);
19025 if (DVar.CKind != OMPC_shared &&
19026 (isOpenMPParallelDirective(DVar.DKind) ||
19027 isOpenMPTeamsDirective(DVar.DKind) ||
19028 DVar.DKind == OMPD_unknown)) {
19029 Diag(ELoc, diag::err_omp_required_access)
19030 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
19031 << getOpenMPClauseNameForDiag(OMPC_shared);
19033 continue;
19034 }
19035 }
19036 // OpenMP [2.9.3.4, Restrictions, p.3]
19037 // A list item that appears in a reduction clause of a parallel construct
19038 // must not appear in a firstprivate clause on a worksharing or task
19039 // construct if any of the worksharing or task regions arising from the
19040 // worksharing or task construct ever bind to any of the parallel regions
19041 // arising from the parallel construct.
19042 // OpenMP [2.9.3.4, Restrictions, p.4]
19043 // A list item that appears in a reduction clause in worksharing
19044 // construct must not appear in a firstprivate clause in a task construct
19045 // encountered during execution of any of the worksharing regions arising
19046 // from the worksharing construct.
19047 if (isOpenMPTaskingDirective(CurrDir)) {
19048 DVar = DSAStack->hasInnermostDSA(
19049 D,
19050 [](OpenMPClauseKind C, bool AppliedToPointee) {
19051 return C == OMPC_reduction && !AppliedToPointee;
19052 },
19053 [](OpenMPDirectiveKind K) {
19054 return isOpenMPParallelDirective(K) ||
19057 },
19058 /*FromParent=*/true);
19059 if (DVar.CKind == OMPC_reduction &&
19060 (isOpenMPParallelDirective(DVar.DKind) ||
19061 isOpenMPWorksharingDirective(DVar.DKind) ||
19062 isOpenMPTeamsDirective(DVar.DKind))) {
19063 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
19064 << getOpenMPDirectiveName(DVar.DKind, OMPVersion);
19066 continue;
19067 }
19068 }
19069
19070 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
19071 // A list item cannot appear in both a map clause and a data-sharing
19072 // attribute clause on the same construct
19073 //
19074 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
19075 // A list item cannot appear in both a map clause and a data-sharing
19076 // attribute clause on the same construct unless the construct is a
19077 // combined construct.
19078 if ((getLangOpts().OpenMP <= 45 &&
19080 CurrDir == OMPD_target) {
19081 OpenMPClauseKind ConflictKind;
19082 if (DSAStack->checkMappableExprComponentListsForDecl(
19083 VD, /*CurrentRegionOnly=*/true,
19084 [&ConflictKind](
19086 OpenMPClauseKind WhereFoundClauseKind) {
19087 ConflictKind = WhereFoundClauseKind;
19088 return true;
19089 })) {
19090 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
19091 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
19092 << getOpenMPClauseNameForDiag(ConflictKind)
19093 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
19094 OMPVersion);
19096 continue;
19097 }
19098 }
19099 }
19100
19101 // Variably modified types are not supported for tasks.
19103 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
19104 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19105 << getOpenMPClauseNameForDiag(OMPC_firstprivate) << Type
19106 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
19107 OMPVersion);
19108 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19110 Diag(D->getLocation(),
19111 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19112 << D;
19113 continue;
19114 }
19115
19116 Type = Type.getUnqualifiedType();
19117 VarDecl *VDPrivate =
19118 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
19119 D->hasAttrs() ? &D->getAttrs() : nullptr,
19120 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19121 // Generate helper private variable and initialize it with the value of the
19122 // original variable. The address of the original variable is replaced by
19123 // the address of the new private variable in the CodeGen. This new variable
19124 // is not added to IdResolver, so the code in the OpenMP region uses
19125 // original variable for proper diagnostics and variable capturing.
19126 Expr *VDInitRefExpr = nullptr;
19127 // For arrays generate initializer for single element and replace it by the
19128 // original array element in CodeGen.
19129 if (Type->isArrayType()) {
19130 VarDecl *VDInit =
19131 buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName());
19132 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc);
19133 Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get();
19134 ElemType = ElemType.getUnqualifiedType();
19135 VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(),
19136 ElemType, ".firstprivate.temp");
19137 InitializedEntity Entity =
19140
19141 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
19142 ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init);
19143 if (Result.isInvalid())
19144 VDPrivate->setInvalidDecl();
19145 else
19146 VDPrivate->setInit(Result.getAs<Expr>());
19147 // Remove temp variable declaration.
19148 getASTContext().Deallocate(VDInitTemp);
19149 } else {
19150 VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type,
19151 ".firstprivate.temp");
19152 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(),
19153 RefExpr->getExprLoc());
19154 SemaRef.AddInitializerToDecl(
19155 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
19156 /*DirectInit=*/false);
19157 }
19158 if (VDPrivate->isInvalidDecl()) {
19159 if (IsImplicitClause) {
19160 Diag(RefExpr->getExprLoc(),
19161 diag::note_omp_task_predetermined_firstprivate_here);
19162 }
19163 continue;
19164 }
19165 SemaRef.CurContext->addDecl(VDPrivate);
19166 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
19167 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(),
19168 RefExpr->getExprLoc());
19169 DeclRefExpr *Ref = nullptr;
19170 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19171 if (TopDVar.CKind == OMPC_lastprivate) {
19172 Ref = TopDVar.PrivateCopy;
19173 } else {
19174 auto *FD = dyn_cast<FieldDecl>(D);
19175 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
19176 if (VD)
19177 Ref =
19179 RefExpr->getExprLoc());
19180 else
19181 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19182 if (VD || !isOpenMPCapturedDecl(D))
19183 ExprCaptures.push_back(Ref->getDecl());
19184 }
19185 }
19186 if (!IsImplicitClause)
19187 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
19188 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19189 ? RefExpr->IgnoreParens()
19190 : Ref);
19191 PrivateCopies.push_back(VDPrivateRefExpr);
19192 Inits.push_back(VDInitRefExpr);
19193 }
19194
19195 if (Vars.empty())
19196 return nullptr;
19197
19199 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
19200 buildPreInits(getASTContext(), ExprCaptures));
19201}
19202
19205 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
19206 SourceLocation LParenLoc, SourceLocation EndLoc) {
19207 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
19208 assert(ColonLoc.isValid() && "Colon location must be valid.");
19209 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
19210 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
19211 /*Last=*/OMPC_LASTPRIVATE_unknown)
19212 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
19213 return nullptr;
19214 }
19215
19217 SmallVector<Expr *, 8> SrcExprs;
19218 SmallVector<Expr *, 8> DstExprs;
19219 SmallVector<Expr *, 8> AssignmentOps;
19220 SmallVector<Decl *, 4> ExprCaptures;
19221 SmallVector<Expr *, 4> ExprPostUpdates;
19222 for (Expr *RefExpr : VarList) {
19223 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
19224 SourceLocation ELoc;
19225 SourceRange ERange;
19226 Expr *SimpleRefExpr = RefExpr;
19227 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19228 if (Res.second) {
19229 // It will be analyzed later.
19230 Vars.push_back(RefExpr);
19231 SrcExprs.push_back(nullptr);
19232 DstExprs.push_back(nullptr);
19233 AssignmentOps.push_back(nullptr);
19234 }
19235 ValueDecl *D = Res.first;
19236 if (!D)
19237 continue;
19238
19239 QualType Type = D->getType();
19240 auto *VD = dyn_cast<VarDecl>(D);
19241
19242 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
19243 // A variable that appears in a lastprivate clause must not have an
19244 // incomplete type or a reference type.
19245 if (SemaRef.RequireCompleteType(ELoc, Type,
19246 diag::err_omp_lastprivate_incomplete_type))
19247 continue;
19248 Type = Type.getNonReferenceType();
19249
19250 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19251 // A variable that is privatized must not have a const-qualified type
19252 // unless it is of class type with a mutable member. This restriction does
19253 // not apply to the firstprivate clause.
19254 //
19255 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
19256 // A variable that appears in a lastprivate clause must not have a
19257 // const-qualified type unless it is of class type with a mutable member.
19258 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc))
19259 continue;
19260
19261 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
19262 // A list item that appears in a lastprivate clause with the conditional
19263 // modifier must be a scalar variable.
19264 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
19265 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
19266 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19268 Diag(D->getLocation(),
19269 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19270 << D;
19271 continue;
19272 }
19273
19274 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19275 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19276 // in a Construct]
19277 // Variables with the predetermined data-sharing attributes may not be
19278 // listed in data-sharing attributes clauses, except for the cases
19279 // listed below.
19280 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
19281 // A list item may appear in a firstprivate or lastprivate clause but not
19282 // both.
19283 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19284 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
19285 (isOpenMPDistributeDirective(CurrDir) ||
19286 DVar.CKind != OMPC_firstprivate) &&
19287 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
19288 Diag(ELoc, diag::err_omp_wrong_dsa)
19289 << getOpenMPClauseNameForDiag(DVar.CKind)
19290 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
19292 continue;
19293 }
19294
19295 // OpenMP [2.14.3.5, Restrictions, p.2]
19296 // A list item that is private within a parallel region, or that appears in
19297 // the reduction clause of a parallel construct, must not appear in a
19298 // lastprivate clause on a worksharing construct if any of the corresponding
19299 // worksharing regions ever binds to any of the corresponding parallel
19300 // regions.
19301 DSAStackTy::DSAVarData TopDVar = DVar;
19302 if (isOpenMPWorksharingDirective(CurrDir) &&
19303 !isOpenMPParallelDirective(CurrDir) &&
19304 !isOpenMPTeamsDirective(CurrDir)) {
19305 DVar = DSAStack->getImplicitDSA(D, true);
19306 if (DVar.CKind != OMPC_shared) {
19307 Diag(ELoc, diag::err_omp_required_access)
19308 << getOpenMPClauseNameForDiag(OMPC_lastprivate)
19309 << getOpenMPClauseNameForDiag(OMPC_shared);
19311 continue;
19312 }
19313 }
19314
19315 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
19316 // A variable of class type (or array thereof) that appears in a
19317 // lastprivate clause requires an accessible, unambiguous default
19318 // constructor for the class type, unless the list item is also specified
19319 // in a firstprivate clause.
19320 // A variable of class type (or array thereof) that appears in a
19321 // lastprivate clause requires an accessible, unambiguous copy assignment
19322 // operator for the class type.
19324 VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(),
19325 Type.getUnqualifiedType(), ".lastprivate.src",
19326 D->hasAttrs() ? &D->getAttrs() : nullptr);
19327 DeclRefExpr *PseudoSrcExpr =
19328 buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc);
19329 VarDecl *DstVD =
19330 buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst",
19331 D->hasAttrs() ? &D->getAttrs() : nullptr);
19332 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
19333 // For arrays generate assignment operation for single element and replace
19334 // it by the original array element in CodeGen.
19335 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
19336 PseudoDstExpr, PseudoSrcExpr);
19337 if (AssignmentOp.isInvalid())
19338 continue;
19339 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
19340 /*DiscardedValue=*/false);
19341 if (AssignmentOp.isInvalid())
19342 continue;
19343
19344 DeclRefExpr *Ref = nullptr;
19345 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19346 if (TopDVar.CKind == OMPC_firstprivate) {
19347 Ref = TopDVar.PrivateCopy;
19348 } else {
19349 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19350 if (!isOpenMPCapturedDecl(D))
19351 ExprCaptures.push_back(Ref->getDecl());
19352 }
19353 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
19354 (!isOpenMPCapturedDecl(D) &&
19355 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
19356 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
19357 if (!RefRes.isUsable())
19358 continue;
19359 ExprResult PostUpdateRes =
19360 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
19361 SimpleRefExpr, RefRes.get());
19362 if (!PostUpdateRes.isUsable())
19363 continue;
19364 ExprPostUpdates.push_back(
19365 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
19366 }
19367 }
19368 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
19369 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19370 ? RefExpr->IgnoreParens()
19371 : Ref);
19372 SrcExprs.push_back(PseudoSrcExpr);
19373 DstExprs.push_back(PseudoDstExpr);
19374 AssignmentOps.push_back(AssignmentOp.get());
19375 }
19376
19377 if (Vars.empty())
19378 return nullptr;
19379
19381 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
19382 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
19383 buildPreInits(getASTContext(), ExprCaptures),
19384 buildPostUpdate(SemaRef, ExprPostUpdates));
19385}
19386
19388 SourceLocation StartLoc,
19389 SourceLocation LParenLoc,
19390 SourceLocation EndLoc) {
19392 for (Expr *RefExpr : VarList) {
19393 assert(RefExpr && "NULL expr in OpenMP shared clause.");
19394 SourceLocation ELoc;
19395 SourceRange ERange;
19396 Expr *SimpleRefExpr = RefExpr;
19397 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19398 if (Res.second) {
19399 // It will be analyzed later.
19400 Vars.push_back(RefExpr);
19401 }
19402 ValueDecl *D = Res.first;
19403 if (!D)
19404 continue;
19405
19406 auto *VD = dyn_cast<VarDecl>(D);
19407 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19408 // in a Construct]
19409 // Variables with the predetermined data-sharing attributes may not be
19410 // listed in data-sharing attributes clauses, except for the cases
19411 // listed below. For these exceptions only, listing a predetermined
19412 // variable in a data-sharing attribute clause is allowed and overrides
19413 // the variable's predetermined data-sharing attributes.
19414 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19415 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
19416 DVar.RefExpr) {
19417 Diag(ELoc, diag::err_omp_wrong_dsa)
19418 << getOpenMPClauseNameForDiag(DVar.CKind)
19419 << getOpenMPClauseNameForDiag(OMPC_shared);
19421 continue;
19422 }
19423
19424 DeclRefExpr *Ref = nullptr;
19425 if (!VD && isOpenMPCapturedDecl(D) &&
19426 !SemaRef.CurContext->isDependentContext())
19427 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19428 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
19429 Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext())
19430 ? RefExpr->IgnoreParens()
19431 : Ref);
19432 }
19433
19434 if (Vars.empty())
19435 return nullptr;
19436
19437 return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19438 Vars);
19439}
19440
19441namespace {
19442class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
19443 DSAStackTy *Stack;
19444
19445public:
19446 bool VisitDeclRefExpr(DeclRefExpr *E) {
19447 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
19448 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
19449 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
19450 return false;
19451 if (DVar.CKind != OMPC_unknown)
19452 return true;
19453 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
19454 VD,
19455 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
19456 return isOpenMPPrivate(C) && !AppliedToPointee;
19457 },
19458 [](OpenMPDirectiveKind) { return true; },
19459 /*FromParent=*/true);
19460 return DVarPrivate.CKind != OMPC_unknown;
19461 }
19462 return false;
19463 }
19464 bool VisitStmt(Stmt *S) {
19465 for (Stmt *Child : S->children()) {
19466 if (Child && Visit(Child))
19467 return true;
19468 }
19469 return false;
19470 }
19471 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
19472};
19473} // namespace
19474
19475namespace {
19476// Transform MemberExpression for specified FieldDecl of current class to
19477// DeclRefExpr to specified OMPCapturedExprDecl.
19478class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
19479 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
19480 ValueDecl *Field = nullptr;
19481 DeclRefExpr *CapturedExpr = nullptr;
19482
19483public:
19484 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
19485 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
19486
19487 ExprResult TransformMemberExpr(MemberExpr *E) {
19489 E->getMemberDecl() == Field) {
19490 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
19491 return CapturedExpr;
19492 }
19493 return BaseTransform::TransformMemberExpr(E);
19494 }
19495 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
19496};
19497} // namespace
19498
19499template <typename T, typename U>
19501 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
19502 for (U &Set : Lookups) {
19503 for (auto *D : Set) {
19504 if (T Res = Gen(cast<ValueDecl>(D)))
19505 return Res;
19506 }
19507 }
19508 return T();
19509}
19510
19512 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
19513
19514 for (auto *RD : D->redecls()) {
19515 // Don't bother with extra checks if we already know this one isn't visible.
19516 if (RD == D)
19517 continue;
19518
19519 auto ND = cast<NamedDecl>(RD);
19520 if (LookupResult::isVisible(SemaRef, ND))
19521 return ND;
19522 }
19523
19524 return nullptr;
19525}
19526
19527static void
19529 SourceLocation Loc, QualType Ty,
19531 // Find all of the associated namespaces and classes based on the
19532 // arguments we have.
19533 Sema::AssociatedNamespaceSet AssociatedNamespaces;
19534 Sema::AssociatedClassSet AssociatedClasses;
19535 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
19536 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
19537 AssociatedClasses);
19538
19539 // C++ [basic.lookup.argdep]p3:
19540 // Let X be the lookup set produced by unqualified lookup (3.4.1)
19541 // and let Y be the lookup set produced by argument dependent
19542 // lookup (defined as follows). If X contains [...] then Y is
19543 // empty. Otherwise Y is the set of declarations found in the
19544 // namespaces associated with the argument types as described
19545 // below. The set of declarations found by the lookup of the name
19546 // is the union of X and Y.
19547 //
19548 // Here, we compute Y and add its members to the overloaded
19549 // candidate set.
19550 for (auto *NS : AssociatedNamespaces) {
19551 // When considering an associated namespace, the lookup is the
19552 // same as the lookup performed when the associated namespace is
19553 // used as a qualifier (3.4.3.2) except that:
19554 //
19555 // -- Any using-directives in the associated namespace are
19556 // ignored.
19557 //
19558 // -- Any namespace-scope friend functions declared in
19559 // associated classes are visible within their respective
19560 // namespaces even if they are not visible during an ordinary
19561 // lookup (11.4).
19562 DeclContext::lookup_result R = NS->lookup(Id.getName());
19563 for (auto *D : R) {
19564 auto *Underlying = D;
19565 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19566 Underlying = USD->getTargetDecl();
19567
19568 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
19569 !isa<OMPDeclareMapperDecl>(Underlying))
19570 continue;
19571
19572 if (!SemaRef.isVisible(D)) {
19573 D = findAcceptableDecl(SemaRef, D);
19574 if (!D)
19575 continue;
19576 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19577 Underlying = USD->getTargetDecl();
19578 }
19579 Lookups.emplace_back();
19580 Lookups.back().addDecl(Underlying);
19581 }
19582 }
19583}
19584
19585static ExprResult
19587 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
19588 const DeclarationNameInfo &ReductionId, QualType Ty,
19589 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
19590 if (ReductionIdScopeSpec.isInvalid())
19591 return ExprError();
19592 SmallVector<UnresolvedSet<8>, 4> Lookups;
19593 if (S) {
19594 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19595 Lookup.suppressDiagnostics();
19596 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec,
19597 /*ObjectType=*/QualType())) {
19598 NamedDecl *D = Lookup.getRepresentativeDecl();
19599 do {
19600 S = S->getParent();
19601 } while (S && !S->isDeclScope(D));
19602 if (S)
19603 S = S->getParent();
19604 Lookups.emplace_back();
19605 Lookups.back().append(Lookup.begin(), Lookup.end());
19606 Lookup.clear();
19607 }
19608 } else if (auto *ULE =
19609 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
19610 Lookups.push_back(UnresolvedSet<8>());
19611 Decl *PrevD = nullptr;
19612 for (NamedDecl *D : ULE->decls()) {
19613 if (D == PrevD)
19614 Lookups.push_back(UnresolvedSet<8>());
19615 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
19616 Lookups.back().addDecl(DRD);
19617 PrevD = D;
19618 }
19619 }
19620 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
19624 return !D->isInvalidDecl() &&
19625 (D->getType()->isDependentType() ||
19626 D->getType()->isInstantiationDependentType() ||
19627 D->getType()->containsUnexpandedParameterPack());
19628 })) {
19629 UnresolvedSet<8> ResSet;
19630 for (const UnresolvedSet<8> &Set : Lookups) {
19631 if (Set.empty())
19632 continue;
19633 ResSet.append(Set.begin(), Set.end());
19634 // The last item marks the end of all declarations at the specified scope.
19635 ResSet.addDecl(Set[Set.size() - 1]);
19636 }
19638 SemaRef.Context, /*NamingClass=*/nullptr,
19639 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
19640 /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false,
19641 /*KnownInstantiationDependent=*/false);
19642 }
19643 // Lookup inside the classes.
19644 // C++ [over.match.oper]p3:
19645 // For a unary operator @ with an operand of a type whose
19646 // cv-unqualified version is T1, and for a binary operator @ with
19647 // a left operand of a type whose cv-unqualified version is T1 and
19648 // a right operand of a type whose cv-unqualified version is T2,
19649 // three sets of candidate functions, designated member
19650 // candidates, non-member candidates and built-in candidates, are
19651 // constructed as follows:
19652 // -- If T1 is a complete class type or a class currently being
19653 // defined, the set of member candidates is the result of the
19654 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
19655 // the set of member candidates is empty.
19656 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19657 Lookup.suppressDiagnostics();
19658 if (Ty->isRecordType()) {
19659 // Complete the type if it can be completed.
19660 // If the type is neither complete nor being defined, bail out now.
19661 bool IsComplete = SemaRef.isCompleteType(Loc, Ty);
19662 auto *RD = Ty->castAsRecordDecl();
19663 if (IsComplete || RD->isBeingDefined()) {
19664 Lookup.clear();
19665 SemaRef.LookupQualifiedName(Lookup, RD);
19666 if (Lookup.empty()) {
19667 Lookups.emplace_back();
19668 Lookups.back().append(Lookup.begin(), Lookup.end());
19669 }
19670 }
19671 }
19672 // Perform ADL.
19673 if (SemaRef.getLangOpts().CPlusPlus)
19674 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
19676 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
19677 if (!D->isInvalidDecl() &&
19678 SemaRef.Context.hasSameType(D->getType(), Ty))
19679 return D;
19680 return nullptr;
19681 }))
19682 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
19683 VK_LValue, Loc);
19684 if (SemaRef.getLangOpts().CPlusPlus) {
19686 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
19687 if (!D->isInvalidDecl() &&
19688 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
19690 SemaRef.getASTContext()))
19691 return D;
19692 return nullptr;
19693 })) {
19694 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
19695 /*DetectVirtual=*/false);
19696 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
19697 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
19698 VD->getType().getUnqualifiedType()))) {
19699 if (SemaRef.CheckBaseClassAccess(
19700 Loc, VD->getType(), Ty, Paths.front(),
19701 /*DiagID=*/0) != Sema::AR_inaccessible) {
19702 SemaRef.BuildBasePathArray(Paths, BasePath);
19703 return SemaRef.BuildDeclRefExpr(
19704 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc);
19705 }
19706 }
19707 }
19708 }
19709 }
19710 if (ReductionIdScopeSpec.isSet()) {
19711 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
19712 << Ty << Range;
19713 return ExprError();
19714 }
19715 return ExprEmpty();
19716}
19717
19718namespace {
19719/// Data for the reduction-based clauses.
19720struct ReductionData {
19721 /// List of original reduction items.
19722 SmallVector<Expr *, 8> Vars;
19723 /// List of private copies of the reduction items.
19724 SmallVector<Expr *, 8> Privates;
19725 /// LHS expressions for the reduction_op expressions.
19726 SmallVector<Expr *, 8> LHSs;
19727 /// RHS expressions for the reduction_op expressions.
19728 SmallVector<Expr *, 8> RHSs;
19729 /// Reduction operation expression.
19730 SmallVector<Expr *, 8> ReductionOps;
19731 /// inscan copy operation expressions.
19732 SmallVector<Expr *, 8> InscanCopyOps;
19733 /// inscan copy temp array expressions for prefix sums.
19734 SmallVector<Expr *, 8> InscanCopyArrayTemps;
19735 /// inscan copy temp array element expressions for prefix sums.
19736 SmallVector<Expr *, 8> InscanCopyArrayElems;
19737 /// Taskgroup descriptors for the corresponding reduction items in
19738 /// in_reduction clauses.
19739 SmallVector<Expr *, 8> TaskgroupDescriptors;
19740 /// List of captures for clause.
19741 SmallVector<Decl *, 4> ExprCaptures;
19742 /// List of postupdate expressions.
19743 SmallVector<Expr *, 4> ExprPostUpdates;
19744 /// Reduction modifier.
19745 unsigned RedModifier = 0;
19746 /// Original modifier.
19747 unsigned OrigSharingModifier = 0;
19748 /// Private Variable Reduction
19749 SmallVector<bool, 8> IsPrivateVarReduction;
19750 ReductionData() = delete;
19751 /// Reserves required memory for the reduction data.
19752 ReductionData(unsigned Size, unsigned Modifier = 0, unsigned OrgModifier = 0)
19753 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
19754 Vars.reserve(Size);
19755 Privates.reserve(Size);
19756 LHSs.reserve(Size);
19757 RHSs.reserve(Size);
19758 ReductionOps.reserve(Size);
19759 IsPrivateVarReduction.reserve(Size);
19760 if (RedModifier == OMPC_REDUCTION_inscan) {
19761 InscanCopyOps.reserve(Size);
19762 InscanCopyArrayTemps.reserve(Size);
19763 InscanCopyArrayElems.reserve(Size);
19764 }
19765 TaskgroupDescriptors.reserve(Size);
19766 ExprCaptures.reserve(Size);
19767 ExprPostUpdates.reserve(Size);
19768 }
19769 /// Stores reduction item and reduction operation only (required for dependent
19770 /// reduction item).
19771 void push(Expr *Item, Expr *ReductionOp) {
19772 Vars.emplace_back(Item);
19773 Privates.emplace_back(nullptr);
19774 LHSs.emplace_back(nullptr);
19775 RHSs.emplace_back(nullptr);
19776 ReductionOps.emplace_back(ReductionOp);
19777 IsPrivateVarReduction.emplace_back(false);
19778 TaskgroupDescriptors.emplace_back(nullptr);
19779 if (RedModifier == OMPC_REDUCTION_inscan) {
19780 InscanCopyOps.push_back(nullptr);
19781 InscanCopyArrayTemps.push_back(nullptr);
19782 InscanCopyArrayElems.push_back(nullptr);
19783 }
19784 }
19785 /// Stores reduction data.
19786 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
19787 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
19788 Expr *CopyArrayElem, bool IsPrivate) {
19789 Vars.emplace_back(Item);
19790 Privates.emplace_back(Private);
19791 LHSs.emplace_back(LHS);
19792 RHSs.emplace_back(RHS);
19793 ReductionOps.emplace_back(ReductionOp);
19794 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
19795 if (RedModifier == OMPC_REDUCTION_inscan) {
19796 InscanCopyOps.push_back(CopyOp);
19797 InscanCopyArrayTemps.push_back(CopyArrayTemp);
19798 InscanCopyArrayElems.push_back(CopyArrayElem);
19799 } else {
19800 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
19801 CopyArrayElem == nullptr &&
19802 "Copy operation must be used for inscan reductions only.");
19803 }
19804 IsPrivateVarReduction.emplace_back(IsPrivate);
19805 }
19806};
19807} // namespace
19808
19810 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
19811 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
19812 const Expr *Length = OASE->getLength();
19813 if (Length == nullptr) {
19814 // For array sections of the form [1:] or [:], we would need to analyze
19815 // the lower bound...
19816 if (OASE->getColonLocFirst().isValid())
19817 return false;
19818
19819 // This is an array subscript which has implicit length 1!
19820 SingleElement = true;
19821 ArraySizes.push_back(llvm::APSInt::get(1));
19822 } else {
19823 Expr::EvalResult Result;
19824 if (!Length->EvaluateAsInt(Result, Context))
19825 return false;
19826
19827 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19828 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
19829 ArraySizes.push_back(ConstantLengthValue);
19830 }
19831
19832 // Get the base of this array section and walk up from there.
19833 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
19834
19835 // We require length = 1 for all array sections except the right-most to
19836 // guarantee that the memory region is contiguous and has no holes in it.
19837 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) {
19838 Length = TempOASE->getLength();
19839 if (Length == nullptr) {
19840 // For array sections of the form [1:] or [:], we would need to analyze
19841 // the lower bound...
19842 if (OASE->getColonLocFirst().isValid())
19843 return false;
19844
19845 // This is an array subscript which has implicit length 1!
19846 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
19847 ArraySizes.push_back(ConstantOne);
19848 } else {
19849 Expr::EvalResult Result;
19850 if (!Length->EvaluateAsInt(Result, Context))
19851 return false;
19852
19853 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19854 if (ConstantLengthValue.getSExtValue() != 1)
19855 return false;
19856
19857 ArraySizes.push_back(ConstantLengthValue);
19858 }
19859 Base = TempOASE->getBase()->IgnoreParenImpCasts();
19860 }
19861
19862 // If we have a single element, we don't need to add the implicit lengths.
19863 if (!SingleElement) {
19864 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
19865 // Has implicit length 1!
19866 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
19867 ArraySizes.push_back(ConstantOne);
19868 Base = TempASE->getBase()->IgnoreParenImpCasts();
19869 }
19870 }
19871
19872 // This array section can be privatized as a single value or as a constant
19873 // sized array.
19874 return true;
19875}
19876
19877static BinaryOperatorKind
19879 if (BOK == BO_Add)
19880 return BO_AddAssign;
19881 if (BOK == BO_Mul)
19882 return BO_MulAssign;
19883 if (BOK == BO_And)
19884 return BO_AndAssign;
19885 if (BOK == BO_Or)
19886 return BO_OrAssign;
19887 if (BOK == BO_Xor)
19888 return BO_XorAssign;
19889 return BOK;
19890}
19891
19893 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
19894 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19895 SourceLocation ColonLoc, SourceLocation EndLoc,
19896 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19897 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
19898 DeclarationName DN = ReductionId.getName();
19900 BinaryOperatorKind BOK = BO_Comma;
19901
19902 ASTContext &Context = S.Context;
19903 // OpenMP [2.14.3.6, reduction clause]
19904 // C
19905 // reduction-identifier is either an identifier or one of the following
19906 // operators: +, -, *, &, |, ^, && and ||
19907 // C++
19908 // reduction-identifier is either an id-expression or one of the following
19909 // operators: +, -, *, &, |, ^, && and ||
19910 switch (OOK) {
19911 case OO_Plus:
19912 BOK = BO_Add;
19913 break;
19914 case OO_Minus:
19915 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
19916 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
19917 // reduction identifier.
19918 if (S.LangOpts.OpenMP > 52)
19919 BOK = BO_Comma;
19920 else
19921 BOK = BO_Add;
19922 break;
19923 case OO_Star:
19924 BOK = BO_Mul;
19925 break;
19926 case OO_Amp:
19927 BOK = BO_And;
19928 break;
19929 case OO_Pipe:
19930 BOK = BO_Or;
19931 break;
19932 case OO_Caret:
19933 BOK = BO_Xor;
19934 break;
19935 case OO_AmpAmp:
19936 BOK = BO_LAnd;
19937 break;
19938 case OO_PipePipe:
19939 BOK = BO_LOr;
19940 break;
19941 case OO_New:
19942 case OO_Delete:
19943 case OO_Array_New:
19944 case OO_Array_Delete:
19945 case OO_Slash:
19946 case OO_Percent:
19947 case OO_Tilde:
19948 case OO_Exclaim:
19949 case OO_Equal:
19950 case OO_Less:
19951 case OO_Greater:
19952 case OO_LessEqual:
19953 case OO_GreaterEqual:
19954 case OO_PlusEqual:
19955 case OO_MinusEqual:
19956 case OO_StarEqual:
19957 case OO_SlashEqual:
19958 case OO_PercentEqual:
19959 case OO_CaretEqual:
19960 case OO_AmpEqual:
19961 case OO_PipeEqual:
19962 case OO_LessLess:
19963 case OO_GreaterGreater:
19964 case OO_LessLessEqual:
19965 case OO_GreaterGreaterEqual:
19966 case OO_EqualEqual:
19967 case OO_ExclaimEqual:
19968 case OO_Spaceship:
19969 case OO_PlusPlus:
19970 case OO_MinusMinus:
19971 case OO_Comma:
19972 case OO_ArrowStar:
19973 case OO_Arrow:
19974 case OO_Call:
19975 case OO_Subscript:
19976 case OO_Conditional:
19977 case OO_Coawait:
19979 llvm_unreachable("Unexpected reduction identifier");
19980 case OO_None:
19981 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
19982 if (II->isStr("max"))
19983 BOK = BO_GT;
19984 else if (II->isStr("min"))
19985 BOK = BO_LT;
19986 }
19987 break;
19988 }
19989
19990 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
19991 // A reduction clause with the minus (-) operator was deprecated
19992 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
19993 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
19994
19995 SourceRange ReductionIdRange;
19996 if (ReductionIdScopeSpec.isValid())
19997 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
19998 else
19999 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
20000 ReductionIdRange.setEnd(ReductionId.getEndLoc());
20001
20002 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
20003 bool FirstIter = true;
20004 for (Expr *RefExpr : VarList) {
20005 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
20006 // OpenMP [2.1, C/C++]
20007 // A list item is a variable or array section, subject to the restrictions
20008 // specified in Section 2.4 on page 42 and in each of the sections
20009 // describing clauses and directives for which a list appears.
20010 // OpenMP [2.14.3.3, Restrictions, p.1]
20011 // A variable that is part of another variable (as an array or
20012 // structure element) cannot appear in a private clause.
20013 if (!FirstIter && IR != ER)
20014 ++IR;
20015 FirstIter = false;
20016 SourceLocation ELoc;
20017 SourceRange ERange;
20018 bool IsPrivate = false;
20019 Expr *SimpleRefExpr = RefExpr;
20020 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
20021 /*AllowArraySection=*/true);
20022 if (Res.second) {
20023 // Try to find 'declare reduction' corresponding construct before using
20024 // builtin/overloaded operators.
20025 QualType Type = Context.DependentTy;
20026 CXXCastPath BasePath;
20027 ExprResult DeclareReductionRef = buildDeclareReductionRef(
20028 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20029 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
20030 Expr *ReductionOp = nullptr;
20031 if (S.CurContext->isDependentContext() &&
20032 (DeclareReductionRef.isUnset() ||
20033 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
20034 ReductionOp = DeclareReductionRef.get();
20035 // It will be analyzed later.
20036 RD.push(RefExpr, ReductionOp);
20037 }
20038 ValueDecl *D = Res.first;
20039 if (!D)
20040 continue;
20041
20042 Expr *TaskgroupDescriptor = nullptr;
20043 QualType Type;
20044 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
20045 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
20046 if (ASE) {
20047 Type = ASE->getType().getNonReferenceType();
20048 } else if (OASE) {
20049 QualType BaseType =
20051 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20052 Type = ATy->getElementType();
20053 else
20054 Type = BaseType->getPointeeType();
20055 Type = Type.getNonReferenceType();
20056 } else {
20057 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
20058 }
20059 auto *VD = dyn_cast<VarDecl>(D);
20060
20061 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
20062 // A variable that appears in a private clause must not have an incomplete
20063 // type or a reference type.
20064 if (S.RequireCompleteType(ELoc, D->getType(),
20065 diag::err_omp_reduction_incomplete_type))
20066 continue;
20067 // OpenMP [2.14.3.6, reduction clause, Restrictions]
20068 // A list item that appears in a reduction clause must not be
20069 // const-qualified.
20070 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
20071 /*AcceptIfMutable=*/false, ASE || OASE))
20072 continue;
20073
20074 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
20075 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
20076 // If a list-item is a reference type then it must bind to the same object
20077 // for all threads of the team.
20078 if (!ASE && !OASE) {
20079 if (VD) {
20080 VarDecl *VDDef = VD->getDefinition();
20081 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
20082 DSARefChecker Check(Stack);
20083 if (Check.Visit(VDDef->getInit())) {
20084 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
20085 << getOpenMPClauseNameForDiag(ClauseKind) << ERange;
20086 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
20087 continue;
20088 }
20089 }
20090 }
20091
20092 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
20093 // in a Construct]
20094 // Variables with the predetermined data-sharing attributes may not be
20095 // listed in data-sharing attributes clauses, except for the cases
20096 // listed below. For these exceptions only, listing a predetermined
20097 // variable in a data-sharing attribute clause is allowed and overrides
20098 // the variable's predetermined data-sharing attributes.
20099 // OpenMP [2.14.3.6, Restrictions, p.3]
20100 // Any number of reduction clauses can be specified on the directive,
20101 // but a list item can appear only once in the reduction clauses for that
20102 // directive.
20103 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
20104 if (DVar.CKind == OMPC_reduction) {
20105 S.Diag(ELoc, diag::err_omp_once_referenced)
20106 << getOpenMPClauseNameForDiag(ClauseKind);
20107 if (DVar.RefExpr)
20108 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
20109 continue;
20110 }
20111 if (DVar.CKind != OMPC_unknown) {
20112 S.Diag(ELoc, diag::err_omp_wrong_dsa)
20113 << getOpenMPClauseNameForDiag(DVar.CKind)
20114 << getOpenMPClauseNameForDiag(OMPC_reduction);
20115 reportOriginalDsa(S, Stack, D, DVar);
20116 continue;
20117 }
20118
20119 // OpenMP [2.14.3.6, Restrictions, p.1]
20120 // A list item that appears in a reduction clause of a worksharing
20121 // construct must be shared in the parallel regions to which any of the
20122 // worksharing regions arising from the worksharing construct bind.
20123
20124 if (S.getLangOpts().OpenMP <= 52 &&
20126 !isOpenMPParallelDirective(CurrDir) &&
20127 !isOpenMPTeamsDirective(CurrDir)) {
20128 DVar = Stack->getImplicitDSA(D, true);
20129 if (DVar.CKind != OMPC_shared) {
20130 S.Diag(ELoc, diag::err_omp_required_access)
20131 << getOpenMPClauseNameForDiag(OMPC_reduction)
20132 << getOpenMPClauseNameForDiag(OMPC_shared);
20133 reportOriginalDsa(S, Stack, D, DVar);
20134 continue;
20135 }
20136 } else if (isOpenMPWorksharingDirective(CurrDir) &&
20137 !isOpenMPParallelDirective(CurrDir) &&
20138 !isOpenMPTeamsDirective(CurrDir)) {
20139 // OpenMP 6.0 [ 7.6.10 ]
20140 // Support Reduction over private variables with reduction clause.
20141 // A list item in a reduction clause can now be private in the enclosing
20142 // context. For orphaned constructs it is assumed to be shared unless
20143 // the original(private) modifier appears in the clause.
20144 DVar = Stack->getImplicitDSA(D, true);
20145 // Determine if the variable should be considered private
20146 IsPrivate = DVar.CKind != OMPC_shared;
20147 bool IsOrphaned = false;
20148 OpenMPDirectiveKind ParentDir = Stack->getParentDirective();
20149 IsOrphaned = ParentDir == OMPD_unknown;
20150 if ((IsOrphaned &&
20151 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
20152 IsPrivate = true;
20153 }
20154 } else {
20155 // Threadprivates cannot be shared between threads, so dignose if the base
20156 // is a threadprivate variable.
20157 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
20158 if (DVar.CKind == OMPC_threadprivate) {
20159 S.Diag(ELoc, diag::err_omp_wrong_dsa)
20160 << getOpenMPClauseNameForDiag(DVar.CKind)
20161 << getOpenMPClauseNameForDiag(OMPC_reduction);
20162 reportOriginalDsa(S, Stack, D, DVar);
20163 continue;
20164 }
20165 }
20166
20167 // Try to find 'declare reduction' corresponding construct before using
20168 // builtin/overloaded operators.
20169 CXXCastPath BasePath;
20170 ExprResult DeclareReductionRef = buildDeclareReductionRef(
20171 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20172 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
20173 if (DeclareReductionRef.isInvalid())
20174 continue;
20175 if (S.CurContext->isDependentContext() &&
20176 (DeclareReductionRef.isUnset() ||
20177 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
20178 RD.push(RefExpr, DeclareReductionRef.get());
20179 continue;
20180 }
20181 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
20182 // Not allowed reduction identifier is found.
20183 if (S.LangOpts.OpenMP > 52)
20184 S.Diag(ReductionId.getBeginLoc(),
20185 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
20186 << Type << ReductionIdRange;
20187 else
20188 S.Diag(ReductionId.getBeginLoc(),
20189 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
20190 << Type << ReductionIdRange;
20191 continue;
20192 }
20193
20194 // OpenMP [2.14.3.6, reduction clause, Restrictions]
20195 // The type of a list item that appears in a reduction clause must be valid
20196 // for the reduction-identifier. For a max or min reduction in C, the type
20197 // of the list item must be an allowed arithmetic data type: char, int,
20198 // float, double, or _Bool, possibly modified with long, short, signed, or
20199 // unsigned. For a max or min reduction in C++, the type of the list item
20200 // must be an allowed arithmetic data type: char, wchar_t, int, float,
20201 // double, or bool, possibly modified with long, short, signed, or unsigned.
20202 if (DeclareReductionRef.isUnset()) {
20203 if ((BOK == BO_GT || BOK == BO_LT) &&
20204 !(Type->isScalarType() ||
20205 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
20206 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
20207 << getOpenMPClauseNameForDiag(ClauseKind)
20208 << S.getLangOpts().CPlusPlus;
20209 if (!ASE && !OASE) {
20210 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20212 S.Diag(D->getLocation(),
20213 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20214 << D;
20215 }
20216 continue;
20217 }
20218 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
20219 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
20220 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
20221 << getOpenMPClauseNameForDiag(ClauseKind);
20222 if (!ASE && !OASE) {
20223 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20225 S.Diag(D->getLocation(),
20226 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20227 << D;
20228 }
20229 continue;
20230 }
20231 }
20232
20233 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
20234 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
20235 D->hasAttrs() ? &D->getAttrs() : nullptr);
20236 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
20237 D->hasAttrs() ? &D->getAttrs() : nullptr);
20238 QualType PrivateTy = Type;
20239
20240 // Try if we can determine constant lengths for all array sections and avoid
20241 // the VLA.
20242 bool ConstantLengthOASE = false;
20243 if (OASE) {
20244 bool SingleElement;
20246 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
20247 Context, OASE, SingleElement, ArraySizes);
20248
20249 // If we don't have a single element, we must emit a constant array type.
20250 if (ConstantLengthOASE && !SingleElement) {
20251 for (llvm::APSInt &Size : ArraySizes)
20252 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
20254 /*IndexTypeQuals=*/0);
20255 }
20256 }
20257
20258 if ((OASE && !ConstantLengthOASE) ||
20259 (!OASE && !ASE &&
20261 if (!Context.getTargetInfo().isVLASupported()) {
20262 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
20263 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20264 S.Diag(ELoc, diag::note_vla_unsupported);
20265 continue;
20266 } else {
20267 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20268 S.targetDiag(ELoc, diag::note_vla_unsupported);
20269 }
20270 }
20271 // For arrays/array sections only:
20272 // Create pseudo array type for private copy. The size for this array will
20273 // be generated during codegen.
20274 // For array subscripts or single variables Private Ty is the same as Type
20275 // (type of the variable or single array element).
20276 PrivateTy = Context.getVariableArrayType(
20277 Type,
20278 new (Context)
20279 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
20280 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0);
20281 } else if (!ASE && !OASE &&
20282 Context.getAsArrayType(D->getType().getNonReferenceType())) {
20283 PrivateTy = D->getType().getNonReferenceType();
20284 }
20285 // Private copy.
20286 VarDecl *PrivateVD =
20287 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
20288 D->hasAttrs() ? &D->getAttrs() : nullptr,
20289 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
20290 // Add initializer for private variable.
20291 Expr *Init = nullptr;
20292 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
20293 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
20294 if (DeclareReductionRef.isUsable()) {
20295 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
20296 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
20297 if (DRD->getInitializer()) {
20298 Init = DRDRef;
20299 RHSVD->setInit(DRDRef);
20301 }
20302 } else {
20303 switch (BOK) {
20304 case BO_Add:
20305 case BO_Xor:
20306 case BO_Or:
20307 case BO_LOr:
20308 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
20310 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
20311 break;
20312 case BO_Mul:
20313 case BO_LAnd:
20314 if (Type->isScalarType() || Type->isAnyComplexType()) {
20315 // '*' and '&&' reduction ops - initializer is '1'.
20316 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
20317 }
20318 break;
20319 case BO_And: {
20320 // '&' reduction op - initializer is '~0'.
20321 QualType OrigType = Type;
20322 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
20323 Type = ComplexTy->getElementType();
20324 if (Type->isRealFloatingType()) {
20325 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
20326 Context.getFloatTypeSemantics(Type));
20327 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
20328 Type, ELoc);
20329 } else if (Type->isScalarType()) {
20330 uint64_t Size = Context.getTypeSize(Type);
20331 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
20332 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
20333 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
20334 }
20335 if (Init && OrigType->isAnyComplexType()) {
20336 // Init = 0xFFFF + 0xFFFFi;
20337 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
20338 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
20339 }
20340 Type = OrigType;
20341 break;
20342 }
20343 case BO_LT:
20344 case BO_GT: {
20345 // 'min' reduction op - initializer is 'Largest representable number in
20346 // the reduction list item type'.
20347 // 'max' reduction op - initializer is 'Least representable number in
20348 // the reduction list item type'.
20349 if (Type->isIntegerType() || Type->isPointerType()) {
20350 bool IsSigned = Type->hasSignedIntegerRepresentation();
20351 uint64_t Size = Context.getTypeSize(Type);
20352 QualType IntTy =
20353 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
20354 llvm::APInt InitValue =
20355 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
20356 : llvm::APInt::getMinValue(Size)
20357 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
20358 : llvm::APInt::getMaxValue(Size);
20359 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
20360 if (Type->isPointerType()) {
20361 // Cast to pointer type.
20363 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
20364 if (CastExpr.isInvalid())
20365 continue;
20366 Init = CastExpr.get();
20367 }
20368 } else if (Type->isRealFloatingType()) {
20369 llvm::APFloat InitValue = llvm::APFloat::getLargest(
20370 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
20371 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
20372 Type, ELoc);
20373 }
20374 break;
20375 }
20376 case BO_PtrMemD:
20377 case BO_PtrMemI:
20378 case BO_MulAssign:
20379 case BO_Div:
20380 case BO_Rem:
20381 case BO_Sub:
20382 case BO_Shl:
20383 case BO_Shr:
20384 case BO_LE:
20385 case BO_GE:
20386 case BO_EQ:
20387 case BO_NE:
20388 case BO_Cmp:
20389 case BO_AndAssign:
20390 case BO_XorAssign:
20391 case BO_OrAssign:
20392 case BO_Assign:
20393 case BO_AddAssign:
20394 case BO_SubAssign:
20395 case BO_DivAssign:
20396 case BO_RemAssign:
20397 case BO_ShlAssign:
20398 case BO_ShrAssign:
20399 case BO_Comma:
20400 llvm_unreachable("Unexpected reduction operation");
20401 }
20402 }
20403 if (Init && DeclareReductionRef.isUnset()) {
20404 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
20405 // Store initializer for single element in private copy. Will be used
20406 // during codegen.
20407 PrivateVD->setInit(RHSVD->getInit());
20408 PrivateVD->setInitStyle(RHSVD->getInitStyle());
20409 } else if (!Init) {
20410 S.ActOnUninitializedDecl(RHSVD);
20411 // Store initializer for single element in private copy. Will be used
20412 // during codegen.
20413 PrivateVD->setInit(RHSVD->getInit());
20414 PrivateVD->setInitStyle(RHSVD->getInitStyle());
20415 }
20416 if (RHSVD->isInvalidDecl())
20417 continue;
20418 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
20419 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
20420 << Type << ReductionIdRange;
20421 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20423 S.Diag(D->getLocation(),
20424 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20425 << D;
20426 continue;
20427 }
20428 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
20429 ExprResult ReductionOp;
20430 if (DeclareReductionRef.isUsable()) {
20431 QualType RedTy = DeclareReductionRef.get()->getType();
20432 QualType PtrRedTy = Context.getPointerType(RedTy);
20433 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
20434 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
20435 if (!BasePath.empty()) {
20436 LHS = S.DefaultLvalueConversion(LHS.get());
20437 RHS = S.DefaultLvalueConversion(RHS.get());
20439 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
20440 LHS.get()->getValueKind(), FPOptionsOverride());
20442 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
20443 RHS.get()->getValueKind(), FPOptionsOverride());
20444 }
20446 QualType Params[] = {PtrRedTy, PtrRedTy};
20447 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
20448 auto *OVE = new (Context) OpaqueValueExpr(
20449 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
20450 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
20451 Expr *Args[] = {LHS.get(), RHS.get()};
20452 ReductionOp =
20453 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
20455 } else {
20457 if (Type->isRecordType() && CombBOK != BOK) {
20459 ReductionOp =
20460 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20461 CombBOK, LHSDRE, RHSDRE);
20462 }
20463 if (!ReductionOp.isUsable()) {
20464 ReductionOp =
20465 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
20466 LHSDRE, RHSDRE);
20467 if (ReductionOp.isUsable()) {
20468 if (BOK != BO_LT && BOK != BO_GT) {
20469 ReductionOp =
20470 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20471 BO_Assign, LHSDRE, ReductionOp.get());
20472 } else {
20473 auto *ConditionalOp = new (Context)
20474 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
20475 RHSDRE, Type, VK_LValue, OK_Ordinary);
20476 ReductionOp =
20477 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20478 BO_Assign, LHSDRE, ConditionalOp);
20479 }
20480 }
20481 }
20482 if (ReductionOp.isUsable())
20483 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
20484 /*DiscardedValue=*/false);
20485 if (!ReductionOp.isUsable())
20486 continue;
20487 }
20488
20489 // Add copy operations for inscan reductions.
20490 // LHS = RHS;
20491 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
20492 if (ClauseKind == OMPC_reduction &&
20493 RD.RedModifier == OMPC_REDUCTION_inscan) {
20494 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
20495 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
20496 RHS.get());
20497 if (!CopyOpRes.isUsable())
20498 continue;
20499 CopyOpRes =
20500 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
20501 if (!CopyOpRes.isUsable())
20502 continue;
20503 // For simd directive and simd-based directives in simd mode no need to
20504 // construct temp array, need just a single temp element.
20505 if (Stack->getCurrentDirective() == OMPD_simd ||
20506 (S.getLangOpts().OpenMPSimd &&
20507 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
20508 VarDecl *TempArrayVD =
20509 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
20510 D->hasAttrs() ? &D->getAttrs() : nullptr);
20511 // Add a constructor to the temp decl.
20512 S.ActOnUninitializedDecl(TempArrayVD);
20513 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
20514 } else {
20515 // Build temp array for prefix sum.
20516 auto *Dim = new (S.Context)
20519 PrivateTy, Dim, ArraySizeModifier::Normal,
20520 /*IndexTypeQuals=*/0);
20521 VarDecl *TempArrayVD =
20522 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
20523 D->hasAttrs() ? &D->getAttrs() : nullptr);
20524 // Add a constructor to the temp decl.
20525 S.ActOnUninitializedDecl(TempArrayVD);
20526 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
20527 TempArrayElem =
20528 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
20529 auto *Idx = new (S.Context)
20531 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
20532 ELoc, Idx, ELoc);
20533 }
20534 }
20535
20536 // OpenMP [2.15.4.6, Restrictions, p.2]
20537 // A list item that appears in an in_reduction clause of a task construct
20538 // must appear in a task_reduction clause of a construct associated with a
20539 // taskgroup region that includes the participating task in its taskgroup
20540 // set. The construct associated with the innermost region that meets this
20541 // condition must specify the same reduction-identifier as the in_reduction
20542 // clause.
20543 if (ClauseKind == OMPC_in_reduction) {
20544 SourceRange ParentSR;
20545 BinaryOperatorKind ParentBOK;
20546 const Expr *ParentReductionOp = nullptr;
20547 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
20548 DSAStackTy::DSAVarData ParentBOKDSA =
20549 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
20550 ParentBOKTD);
20551 DSAStackTy::DSAVarData ParentReductionOpDSA =
20552 Stack->getTopMostTaskgroupReductionData(
20553 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
20554 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
20555 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
20556 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
20557 (DeclareReductionRef.isUsable() && IsParentBOK) ||
20558 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
20559 bool EmitError = true;
20560 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
20561 llvm::FoldingSetNodeID RedId, ParentRedId;
20562 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
20563 DeclareReductionRef.get()->Profile(RedId, Context,
20564 /*Canonical=*/true);
20565 EmitError = RedId != ParentRedId;
20566 }
20567 if (EmitError) {
20568 S.Diag(ReductionId.getBeginLoc(),
20569 diag::err_omp_reduction_identifier_mismatch)
20570 << ReductionIdRange << RefExpr->getSourceRange();
20571 S.Diag(ParentSR.getBegin(),
20572 diag::note_omp_previous_reduction_identifier)
20573 << ParentSR
20574 << (IsParentBOK ? ParentBOKDSA.RefExpr
20575 : ParentReductionOpDSA.RefExpr)
20576 ->getSourceRange();
20577 continue;
20578 }
20579 }
20580 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
20581 }
20582
20583 DeclRefExpr *Ref = nullptr;
20584 Expr *VarsExpr = RefExpr->IgnoreParens();
20585 if (!VD && !S.CurContext->isDependentContext()) {
20586 if (ASE || OASE) {
20587 TransformExprToCaptures RebuildToCapture(S, D);
20588 VarsExpr =
20589 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
20590 Ref = RebuildToCapture.getCapturedExpr();
20591 } else {
20592 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
20593 }
20594 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
20595 RD.ExprCaptures.emplace_back(Ref->getDecl());
20596 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20597 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
20598 if (!RefRes.isUsable())
20599 continue;
20600 ExprResult PostUpdateRes =
20601 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
20602 RefRes.get());
20603 if (!PostUpdateRes.isUsable())
20604 continue;
20605 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
20606 Stack->getCurrentDirective() == OMPD_taskgroup) {
20607 S.Diag(RefExpr->getExprLoc(),
20608 diag::err_omp_reduction_non_addressable_expression)
20609 << RefExpr->getSourceRange();
20610 continue;
20611 }
20612 RD.ExprPostUpdates.emplace_back(
20613 S.IgnoredValueConversions(PostUpdateRes.get()).get());
20614 }
20615 }
20616 }
20617 // All reduction items are still marked as reduction (to do not increase
20618 // code base size).
20619 unsigned Modifier = RD.RedModifier;
20620 // Consider task_reductions as reductions with task modifier. Required for
20621 // correct analysis of in_reduction clauses.
20622 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
20623 Modifier = OMPC_REDUCTION_task;
20624 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
20625 ASE || OASE);
20626 if (Modifier == OMPC_REDUCTION_task &&
20627 (CurrDir == OMPD_taskgroup ||
20628 ((isOpenMPParallelDirective(CurrDir) ||
20629 isOpenMPWorksharingDirective(CurrDir)) &&
20630 !isOpenMPSimdDirective(CurrDir)))) {
20631 if (DeclareReductionRef.isUsable())
20632 Stack->addTaskgroupReductionData(D, ReductionIdRange,
20633 DeclareReductionRef.get());
20634 else
20635 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
20636 }
20637 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
20638 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
20639 TempArrayElem.get(), IsPrivate);
20640 }
20641 return RD.Vars.empty();
20642}
20643
20645 ArrayRef<Expr *> VarList,
20647 SourceLocation StartLoc, SourceLocation LParenLoc,
20648 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
20649 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20650 ArrayRef<Expr *> UnresolvedReductions) {
20652 static_cast<OpenMPReductionClauseModifier>(Modifiers.ExtraModifier);
20653 OpenMPOriginalSharingModifier OriginalSharingModifier =
20654 static_cast<OpenMPOriginalSharingModifier>(
20655 Modifiers.OriginalSharingModifier);
20656 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
20657 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
20658 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
20659 /*Last=*/OMPC_REDUCTION_unknown)
20660 << getOpenMPClauseNameForDiag(OMPC_reduction);
20661 return nullptr;
20662 }
20663 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
20664 // A reduction clause with the inscan reduction-modifier may only appear on a
20665 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
20666 // construct, a parallel worksharing-loop construct or a parallel
20667 // worksharing-loop SIMD construct.
20668 if (Modifier == OMPC_REDUCTION_inscan &&
20669 (DSAStack->getCurrentDirective() != OMPD_for &&
20670 DSAStack->getCurrentDirective() != OMPD_for_simd &&
20671 DSAStack->getCurrentDirective() != OMPD_simd &&
20672 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
20673 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
20674 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
20675 return nullptr;
20676 }
20677 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
20678 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
20679 StartLoc, LParenLoc, ColonLoc, EndLoc,
20680 ReductionIdScopeSpec, ReductionId,
20681 UnresolvedReductions, RD))
20682 return nullptr;
20683
20685 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
20686 Modifier, RD.Vars,
20687 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20688 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
20689 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
20690 buildPreInits(getASTContext(), RD.ExprCaptures),
20691 buildPostUpdate(SemaRef, RD.ExprPostUpdates), RD.IsPrivateVarReduction,
20692 OriginalSharingModifier);
20693}
20694
20696 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20697 SourceLocation ColonLoc, SourceLocation EndLoc,
20698 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20699 ArrayRef<Expr *> UnresolvedReductions) {
20700 ReductionData RD(VarList.size());
20701 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction,
20702 VarList, StartLoc, LParenLoc, ColonLoc,
20703 EndLoc, ReductionIdScopeSpec, ReductionId,
20704 UnresolvedReductions, RD))
20705 return nullptr;
20706
20708 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20709 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20710 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
20711 buildPreInits(getASTContext(), RD.ExprCaptures),
20712 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
20713}
20714
20716 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20717 SourceLocation ColonLoc, SourceLocation EndLoc,
20718 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20719 ArrayRef<Expr *> UnresolvedReductions) {
20720 ReductionData RD(VarList.size());
20721 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList,
20722 StartLoc, LParenLoc, ColonLoc, EndLoc,
20723 ReductionIdScopeSpec, ReductionId,
20724 UnresolvedReductions, RD))
20725 return nullptr;
20726
20728 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20729 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20730 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
20731 buildPreInits(getASTContext(), RD.ExprCaptures),
20732 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
20733}
20734
20736 SourceLocation LinLoc) {
20737 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
20738 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
20739 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
20740 << getLangOpts().CPlusPlus;
20741 return true;
20742 }
20743 return false;
20744}
20745
20747 OpenMPLinearClauseKind LinKind,
20748 QualType Type, bool IsDeclareSimd) {
20749 const auto *VD = dyn_cast_or_null<VarDecl>(D);
20750 // A variable must not have an incomplete type or a reference type.
20751 if (SemaRef.RequireCompleteType(ELoc, Type,
20752 diag::err_omp_linear_incomplete_type))
20753 return true;
20754 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
20755 !Type->isReferenceType()) {
20756 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
20757 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
20758 return true;
20759 }
20760 Type = Type.getNonReferenceType();
20761
20762 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
20763 // A variable that is privatized must not have a const-qualified type
20764 // unless it is of class type with a mutable member. This restriction does
20765 // not apply to the firstprivate clause, nor to the linear clause on
20766 // declarative directives (like declare simd).
20767 if (!IsDeclareSimd &&
20768 rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc))
20769 return true;
20770
20771 // A list item must be of integral or pointer type.
20772 Type = Type.getUnqualifiedType().getCanonicalType();
20773 const auto *Ty = Type.getTypePtrOrNull();
20774 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
20775 !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) {
20776 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
20777 if (D) {
20778 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20780 Diag(D->getLocation(),
20781 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20782 << D;
20783 }
20784 return true;
20785 }
20786 return false;
20787}
20788
20790 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
20791 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
20792 SourceLocation LinLoc, SourceLocation ColonLoc,
20793 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
20795 SmallVector<Expr *, 8> Privates;
20797 SmallVector<Decl *, 4> ExprCaptures;
20798 SmallVector<Expr *, 4> ExprPostUpdates;
20799 // OpenMP 5.2 [Section 5.4.6, linear clause]
20800 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
20801 // 'ref'
20802 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
20803 getLangOpts().OpenMP >= 52)
20804 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
20805 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
20806 LinKind = OMPC_LINEAR_val;
20807 for (Expr *RefExpr : VarList) {
20808 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20809 SourceLocation ELoc;
20810 SourceRange ERange;
20811 Expr *SimpleRefExpr = RefExpr;
20812 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20813 if (Res.second) {
20814 // It will be analyzed later.
20815 Vars.push_back(RefExpr);
20816 Privates.push_back(nullptr);
20817 Inits.push_back(nullptr);
20818 }
20819 ValueDecl *D = Res.first;
20820 if (!D)
20821 continue;
20822
20823 QualType Type = D->getType();
20824 auto *VD = dyn_cast<VarDecl>(D);
20825
20826 // OpenMP [2.14.3.7, linear clause]
20827 // A list-item cannot appear in more than one linear clause.
20828 // A list-item that appears in a linear clause cannot appear in any
20829 // other data-sharing attribute clause.
20830 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
20831 if (DVar.RefExpr) {
20832 Diag(ELoc, diag::err_omp_wrong_dsa)
20833 << getOpenMPClauseNameForDiag(DVar.CKind)
20834 << getOpenMPClauseNameForDiag(OMPC_linear);
20836 continue;
20837 }
20838
20839 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
20840 continue;
20841 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20842
20843 // Build private copy of original var.
20844 VarDecl *Private =
20845 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
20846 D->hasAttrs() ? &D->getAttrs() : nullptr,
20847 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
20848 DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc);
20849 // Build var to save initial value.
20850 VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start");
20851 Expr *InitExpr;
20852 DeclRefExpr *Ref = nullptr;
20853 if (!VD && !SemaRef.CurContext->isDependentContext()) {
20854 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
20855 if (!isOpenMPCapturedDecl(D)) {
20856 ExprCaptures.push_back(Ref->getDecl());
20857 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20858 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
20859 if (!RefRes.isUsable())
20860 continue;
20861 ExprResult PostUpdateRes =
20862 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
20863 SimpleRefExpr, RefRes.get());
20864 if (!PostUpdateRes.isUsable())
20865 continue;
20866 ExprPostUpdates.push_back(
20867 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
20868 }
20869 }
20870 }
20871 if (LinKind == OMPC_LINEAR_uval)
20872 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
20873 else
20874 InitExpr = VD ? SimpleRefExpr : Ref;
20875 SemaRef.AddInitializerToDecl(
20876 Init, SemaRef.DefaultLvalueConversion(InitExpr).get(),
20877 /*DirectInit=*/false);
20878 DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc);
20879
20880 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
20881 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
20882 ? RefExpr->IgnoreParens()
20883 : Ref);
20884 Privates.push_back(PrivateRef);
20885 Inits.push_back(InitRef);
20886 }
20887
20888 if (Vars.empty())
20889 return nullptr;
20890
20891 Expr *StepExpr = Step;
20892 Expr *CalcStepExpr = nullptr;
20893 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
20894 !Step->isInstantiationDependent() &&
20896 SourceLocation StepLoc = Step->getBeginLoc();
20898 if (Val.isInvalid())
20899 return nullptr;
20900 StepExpr = Val.get();
20901
20902 // Build var to save the step value.
20903 VarDecl *SaveVar =
20904 buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step");
20905 ExprResult SaveRef =
20906 buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc);
20907 ExprResult CalcStep = SemaRef.BuildBinOp(
20908 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr);
20909 CalcStep =
20910 SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue=*/false);
20911
20912 // Warn about zero linear step (it would be probably better specified as
20913 // making corresponding variables 'const').
20914 if (std::optional<llvm::APSInt> Result =
20916 if (!Result->isNegative() && !Result->isStrictlyPositive())
20917 Diag(StepLoc, diag::warn_omp_linear_step_zero)
20918 << Vars[0] << (Vars.size() > 1);
20919 } else if (CalcStep.isUsable()) {
20920 // Calculate the step beforehand instead of doing this on each iteration.
20921 // (This is not used if the number of iterations may be kfold-ed).
20922 CalcStepExpr = CalcStep.get();
20923 }
20924 }
20925
20926 return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind,
20927 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
20928 Vars, Privates, Inits, StepExpr, CalcStepExpr,
20929 buildPreInits(getASTContext(), ExprCaptures),
20930 buildPostUpdate(SemaRef, ExprPostUpdates));
20931}
20932
20934 Expr *NumIterations, Sema &SemaRef,
20935 Scope *S, DSAStackTy *Stack) {
20936 // Walk the vars and build update/final expressions for the CodeGen.
20937 SmallVector<Expr *, 8> Updates;
20939 SmallVector<Expr *, 8> UsedExprs;
20940 Expr *Step = Clause.getStep();
20941 Expr *CalcStep = Clause.getCalcStep();
20942 // OpenMP [2.14.3.7, linear clause]
20943 // If linear-step is not specified it is assumed to be 1.
20944 if (!Step)
20945 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
20946 else if (CalcStep)
20947 Step = cast<BinaryOperator>(CalcStep)->getLHS();
20948 bool HasErrors = false;
20949 auto CurInit = Clause.inits().begin();
20950 auto CurPrivate = Clause.privates().begin();
20951 OpenMPLinearClauseKind LinKind = Clause.getModifier();
20952 for (Expr *RefExpr : Clause.varlist()) {
20953 SourceLocation ELoc;
20954 SourceRange ERange;
20955 Expr *SimpleRefExpr = RefExpr;
20956 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20957 ValueDecl *D = Res.first;
20958 if (Res.second || !D) {
20959 Updates.push_back(nullptr);
20960 Finals.push_back(nullptr);
20961 HasErrors = true;
20962 continue;
20963 }
20964 auto &&Info = Stack->isLoopControlVariable(D);
20965 // OpenMP [2.15.11, distribute simd Construct]
20966 // A list item may not appear in a linear clause, unless it is the loop
20967 // iteration variable.
20968 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
20969 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
20970 SemaRef.Diag(ELoc,
20971 diag::err_omp_linear_distribute_var_non_loop_iteration);
20972 Updates.push_back(nullptr);
20973 Finals.push_back(nullptr);
20974 HasErrors = true;
20975 continue;
20976 }
20977 Expr *InitExpr = *CurInit;
20978
20979 // Build privatized reference to the current linear var.
20980 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
20981 Expr *CapturedRef;
20982 if (LinKind == OMPC_LINEAR_uval)
20983 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
20984 else
20985 CapturedRef =
20986 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
20987 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
20988 /*RefersToCapture=*/true);
20989
20990 // Build update: Var = InitExpr + IV * Step
20992 if (!Info.first)
20994 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
20995 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
20996 else
20997 Update = *CurPrivate;
20998 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
20999 /*DiscardedValue=*/false);
21000
21001 // Build final: Var = PrivCopy;
21002 ExprResult Final;
21003 if (!Info.first)
21004 Final = SemaRef.BuildBinOp(
21005 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
21006 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
21007 else
21008 Final = *CurPrivate;
21009 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
21010 /*DiscardedValue=*/false);
21011
21012 if (!Update.isUsable() || !Final.isUsable()) {
21013 Updates.push_back(nullptr);
21014 Finals.push_back(nullptr);
21015 UsedExprs.push_back(nullptr);
21016 HasErrors = true;
21017 } else {
21018 Updates.push_back(Update.get());
21019 Finals.push_back(Final.get());
21020 if (!Info.first)
21021 UsedExprs.push_back(SimpleRefExpr);
21022 }
21023 ++CurInit;
21024 ++CurPrivate;
21025 }
21026 if (Expr *S = Clause.getStep())
21027 UsedExprs.push_back(S);
21028 // Fill the remaining part with the nullptr.
21029 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
21030 Clause.setUpdates(Updates);
21031 Clause.setFinals(Finals);
21032 Clause.setUsedExprs(UsedExprs);
21033 return HasErrors;
21034}
21035
21037 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
21038 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
21040 for (Expr *RefExpr : VarList) {
21041 assert(RefExpr && "NULL expr in OpenMP aligned clause.");
21042 SourceLocation ELoc;
21043 SourceRange ERange;
21044 Expr *SimpleRefExpr = RefExpr;
21045 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21046 if (Res.second) {
21047 // It will be analyzed later.
21048 Vars.push_back(RefExpr);
21049 }
21050 ValueDecl *D = Res.first;
21051 if (!D)
21052 continue;
21053
21054 QualType QType = D->getType();
21055 auto *VD = dyn_cast<VarDecl>(D);
21056
21057 // OpenMP [2.8.1, simd construct, Restrictions]
21058 // The type of list items appearing in the aligned clause must be
21059 // array, pointer, reference to array, or reference to pointer.
21061 const Type *Ty = QType.getTypePtrOrNull();
21062 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
21063 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
21064 << QType << getLangOpts().CPlusPlus << ERange;
21065 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21067 Diag(D->getLocation(),
21068 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21069 << D;
21070 continue;
21071 }
21072
21073 // OpenMP [2.8.1, simd construct, Restrictions]
21074 // A list-item cannot appear in more than one aligned clause.
21075 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
21076 Diag(ELoc, diag::err_omp_used_in_clause_twice)
21077 << 0 << getOpenMPClauseNameForDiag(OMPC_aligned) << ERange;
21078 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
21079 << getOpenMPClauseNameForDiag(OMPC_aligned);
21080 continue;
21081 }
21082
21083 DeclRefExpr *Ref = nullptr;
21084 if (!VD && isOpenMPCapturedDecl(D))
21085 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
21086 Vars.push_back(SemaRef
21087 .DefaultFunctionArrayConversion(
21088 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
21089 .get());
21090 }
21091
21092 // OpenMP [2.8.1, simd construct, Description]
21093 // The parameter of the aligned clause, alignment, must be a constant
21094 // positive integer expression.
21095 // If no optional parameter is specified, implementation-defined default
21096 // alignments for SIMD instructions on the target platforms are assumed.
21097 if (Alignment != nullptr) {
21098 ExprResult AlignResult =
21099 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
21100 if (AlignResult.isInvalid())
21101 return nullptr;
21102 Alignment = AlignResult.get();
21103 }
21104 if (Vars.empty())
21105 return nullptr;
21106
21107 return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc,
21108 ColonLoc, EndLoc, Vars, Alignment);
21109}
21110
21112 SourceLocation StartLoc,
21113 SourceLocation LParenLoc,
21114 SourceLocation EndLoc) {
21116 SmallVector<Expr *, 8> SrcExprs;
21117 SmallVector<Expr *, 8> DstExprs;
21118 SmallVector<Expr *, 8> AssignmentOps;
21119 for (Expr *RefExpr : VarList) {
21120 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
21121 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21122 // It will be analyzed later.
21123 Vars.push_back(RefExpr);
21124 SrcExprs.push_back(nullptr);
21125 DstExprs.push_back(nullptr);
21126 AssignmentOps.push_back(nullptr);
21127 continue;
21128 }
21129
21130 SourceLocation ELoc = RefExpr->getExprLoc();
21131 // OpenMP [2.1, C/C++]
21132 // A list item is a variable name.
21133 // OpenMP [2.14.4.1, Restrictions, p.1]
21134 // A list item that appears in a copyin clause must be threadprivate.
21135 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
21136 if (!DE || !isa<VarDecl>(DE->getDecl())) {
21137 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
21138 << 0 << RefExpr->getSourceRange();
21139 continue;
21140 }
21141
21142 Decl *D = DE->getDecl();
21143 auto *VD = cast<VarDecl>(D);
21144
21145 QualType Type = VD->getType();
21147 // It will be analyzed later.
21148 Vars.push_back(DE);
21149 SrcExprs.push_back(nullptr);
21150 DstExprs.push_back(nullptr);
21151 AssignmentOps.push_back(nullptr);
21152 continue;
21153 }
21154
21155 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
21156 // A list item that appears in a copyin clause must be threadprivate.
21157 if (!DSAStack->isThreadPrivate(VD)) {
21158 unsigned OMPVersion = getLangOpts().OpenMP;
21159 Diag(ELoc, diag::err_omp_required_access)
21160 << getOpenMPClauseNameForDiag(OMPC_copyin)
21161 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion);
21162 continue;
21163 }
21164
21165 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
21166 // A variable of class type (or array thereof) that appears in a
21167 // copyin clause requires an accessible, unambiguous copy assignment
21168 // operator for the class type.
21169 QualType ElemType =
21171 VarDecl *SrcVD =
21172 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
21173 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
21174 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
21175 SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
21176 VarDecl *DstVD =
21177 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst",
21178 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
21179 DeclRefExpr *PseudoDstExpr =
21180 buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc());
21181 // For arrays generate assignment operation for single element and replace
21182 // it by the original array element in CodeGen.
21183 ExprResult AssignmentOp =
21184 SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
21185 PseudoDstExpr, PseudoSrcExpr);
21186 if (AssignmentOp.isInvalid())
21187 continue;
21188 AssignmentOp =
21189 SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
21190 /*DiscardedValue=*/false);
21191 if (AssignmentOp.isInvalid())
21192 continue;
21193
21194 DSAStack->addDSA(VD, DE, OMPC_copyin);
21195 Vars.push_back(DE);
21196 SrcExprs.push_back(PseudoSrcExpr);
21197 DstExprs.push_back(PseudoDstExpr);
21198 AssignmentOps.push_back(AssignmentOp.get());
21199 }
21200
21201 if (Vars.empty())
21202 return nullptr;
21203
21204 return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21205 Vars, SrcExprs, DstExprs, AssignmentOps);
21206}
21207
21209 SourceLocation StartLoc,
21210 SourceLocation LParenLoc,
21211 SourceLocation EndLoc) {
21213 SmallVector<Expr *, 8> SrcExprs;
21214 SmallVector<Expr *, 8> DstExprs;
21215 SmallVector<Expr *, 8> AssignmentOps;
21216 for (Expr *RefExpr : VarList) {
21217 assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");
21218 SourceLocation ELoc;
21219 SourceRange ERange;
21220 Expr *SimpleRefExpr = RefExpr;
21221 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21222 if (Res.second) {
21223 // It will be analyzed later.
21224 Vars.push_back(RefExpr);
21225 SrcExprs.push_back(nullptr);
21226 DstExprs.push_back(nullptr);
21227 AssignmentOps.push_back(nullptr);
21228 }
21229 ValueDecl *D = Res.first;
21230 if (!D)
21231 continue;
21232
21233 QualType Type = D->getType();
21234 auto *VD = dyn_cast<VarDecl>(D);
21235
21236 // OpenMP [2.14.4.2, Restrictions, p.2]
21237 // A list item that appears in a copyprivate clause may not appear in a
21238 // private or firstprivate clause on the single construct.
21239 if (!VD || !DSAStack->isThreadPrivate(VD)) {
21240 DSAStackTy::DSAVarData DVar =
21241 DSAStack->getTopDSA(D, /*FromParent=*/false);
21242 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
21243 DVar.RefExpr) {
21244 Diag(ELoc, diag::err_omp_wrong_dsa)
21245 << getOpenMPClauseNameForDiag(DVar.CKind)
21246 << getOpenMPClauseNameForDiag(OMPC_copyprivate);
21248 continue;
21249 }
21250
21251 // OpenMP [2.11.4.2, Restrictions, p.1]
21252 // All list items that appear in a copyprivate clause must be either
21253 // threadprivate or private in the enclosing context.
21254 if (DVar.CKind == OMPC_unknown) {
21255 DVar = DSAStack->getImplicitDSA(D, false);
21256 if (DVar.CKind == OMPC_shared) {
21257 Diag(ELoc, diag::err_omp_required_access)
21258 << getOpenMPClauseNameForDiag(OMPC_copyprivate)
21259 << "threadprivate or private in the enclosing context";
21261 continue;
21262 }
21263 }
21264 }
21265
21266 // Variably modified types are not supported.
21268 unsigned OMPVersion = getLangOpts().OpenMP;
21269 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
21270 << getOpenMPClauseNameForDiag(OMPC_copyprivate) << Type
21271 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
21272 OMPVersion);
21273 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21275 Diag(D->getLocation(),
21276 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21277 << D;
21278 continue;
21279 }
21280
21281 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
21282 // A variable of class type (or array thereof) that appears in a
21283 // copyin clause requires an accessible, unambiguous copy assignment
21284 // operator for the class type.
21286 .getBaseElementType(Type.getNonReferenceType())
21288 VarDecl *SrcVD =
21289 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
21290 D->hasAttrs() ? &D->getAttrs() : nullptr);
21291 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc);
21292 VarDecl *DstVD =
21293 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
21294 D->hasAttrs() ? &D->getAttrs() : nullptr);
21295 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
21296 ExprResult AssignmentOp = SemaRef.BuildBinOp(
21297 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
21298 if (AssignmentOp.isInvalid())
21299 continue;
21300 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
21301 /*DiscardedValue=*/false);
21302 if (AssignmentOp.isInvalid())
21303 continue;
21304
21305 // No need to mark vars as copyprivate, they are already threadprivate or
21306 // implicitly private.
21307 assert(VD || isOpenMPCapturedDecl(D));
21308 Vars.push_back(
21309 VD ? RefExpr->IgnoreParens()
21310 : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false));
21311 SrcExprs.push_back(PseudoSrcExpr);
21312 DstExprs.push_back(PseudoDstExpr);
21313 AssignmentOps.push_back(AssignmentOp.get());
21314 }
21315
21316 if (Vars.empty())
21317 return nullptr;
21318
21319 return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc,
21320 EndLoc, Vars, SrcExprs, DstExprs,
21321 AssignmentOps);
21322}
21323
21325 SourceLocation StartLoc,
21326 SourceLocation LParenLoc,
21327 SourceLocation EndLoc) {
21328 if (VarList.empty())
21329 return nullptr;
21330
21331 return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21332 VarList);
21333}
21334
21335/// Tries to find omp_depend_t. type.
21336static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
21337 bool Diagnose = true) {
21338 QualType OMPDependT = Stack->getOMPDependT();
21339 if (!OMPDependT.isNull())
21340 return true;
21341 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
21342 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
21343 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
21344 if (Diagnose)
21345 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
21346 return false;
21347 }
21348 Stack->setOMPDependT(PT.get());
21349 return true;
21350}
21351
21353 SourceLocation StartLoc,
21354 SourceLocation LParenLoc,
21355 SourceLocation EndLoc) {
21356 if (!Depobj)
21357 return nullptr;
21358
21359 bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack);
21360
21361 // OpenMP 5.0, 2.17.10.1 depobj Construct
21362 // depobj is an lvalue expression of type omp_depend_t.
21363 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
21364 !Depobj->isInstantiationDependent() &&
21366 (OMPDependTFound && !getASTContext().typesAreCompatible(
21367 DSAStack->getOMPDependT(), Depobj->getType(),
21368 /*CompareUnqualified=*/true))) {
21369 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21370 << 0 << Depobj->getType() << Depobj->getSourceRange();
21371 }
21372
21373 if (!Depobj->isLValue()) {
21374 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21375 << 1 << Depobj->getSourceRange();
21376 }
21377
21378 return OMPDepobjClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21379 Depobj);
21380}
21381
21382namespace {
21383// Utility struct that gathers the related info for doacross clause.
21384struct DoacrossDataInfoTy {
21385 // The list of expressions.
21387 // The OperatorOffset for doacross loop.
21388 DSAStackTy::OperatorOffsetTy OpsOffs;
21389 // The depended loop count.
21390 llvm::APSInt TotalDepCount;
21391};
21392} // namespace
21393static DoacrossDataInfoTy
21395 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
21396 SourceLocation EndLoc) {
21397
21399 DSAStackTy::OperatorOffsetTy OpsOffs;
21400 llvm::APSInt DepCounter(/*BitWidth=*/32);
21401 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
21402
21403 if (const Expr *OrderedCountExpr =
21404 Stack->getParentOrderedRegionParam().first) {
21405 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
21406 TotalDepCount.setIsUnsigned(/*Val=*/true);
21407 }
21408
21409 for (Expr *RefExpr : VarList) {
21410 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
21411 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21412 // It will be analyzed later.
21413 Vars.push_back(RefExpr);
21414 continue;
21415 }
21416
21417 SourceLocation ELoc = RefExpr->getExprLoc();
21418 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
21419 if (!IsSource) {
21420 if (Stack->getParentOrderedRegionParam().first &&
21421 DepCounter >= TotalDepCount) {
21422 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
21423 continue;
21424 }
21425 ++DepCounter;
21426 // OpenMP [2.13.9, Summary]
21427 // depend(dependence-type : vec), where dependence-type is:
21428 // 'sink' and where vec is the iteration vector, which has the form:
21429 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
21430 // where n is the value specified by the ordered clause in the loop
21431 // directive, xi denotes the loop iteration variable of the i-th nested
21432 // loop associated with the loop directive, and di is a constant
21433 // non-negative integer.
21434 if (SemaRef.CurContext->isDependentContext()) {
21435 // It will be analyzed later.
21436 Vars.push_back(RefExpr);
21437 continue;
21438 }
21439 SimpleExpr = SimpleExpr->IgnoreImplicit();
21441 SourceLocation OOLoc;
21442 Expr *LHS = SimpleExpr;
21443 Expr *RHS = nullptr;
21444 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
21445 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
21446 OOLoc = BO->getOperatorLoc();
21447 LHS = BO->getLHS()->IgnoreParenImpCasts();
21448 RHS = BO->getRHS()->IgnoreParenImpCasts();
21449 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
21450 OOK = OCE->getOperator();
21451 OOLoc = OCE->getOperatorLoc();
21452 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
21453 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
21454 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
21455 OOK = MCE->getMethodDecl()
21456 ->getNameInfo()
21457 .getName()
21458 .getCXXOverloadedOperator();
21459 OOLoc = MCE->getCallee()->getExprLoc();
21460 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
21461 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
21462 }
21463 SourceLocation ELoc;
21464 SourceRange ERange;
21465 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
21466 if (Res.second) {
21467 // It will be analyzed later.
21468 Vars.push_back(RefExpr);
21469 }
21470 ValueDecl *D = Res.first;
21471 if (!D)
21472 continue;
21473
21474 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
21475 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
21476 continue;
21477 }
21478 if (RHS) {
21479 ExprResult RHSRes =
21481 RHS, OMPC_depend, /*StrictlyPositive=*/false);
21482 if (RHSRes.isInvalid())
21483 continue;
21484 }
21485 if (!SemaRef.CurContext->isDependentContext() &&
21486 Stack->getParentOrderedRegionParam().first &&
21487 DepCounter != Stack->isParentLoopControlVariable(D).first) {
21488 const ValueDecl *VD =
21489 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
21490 if (VD)
21491 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21492 << 1 << VD;
21493 else
21494 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21495 << 0;
21496 continue;
21497 }
21498 OpsOffs.emplace_back(RHS, OOK);
21499 }
21500 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21501 }
21502 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
21503 TotalDepCount > VarList.size() &&
21504 Stack->getParentOrderedRegionParam().first &&
21505 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
21506 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
21507 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
21508 }
21509 return {Vars, OpsOffs, TotalDepCount};
21510}
21511
21513 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
21514 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
21515 SourceLocation EndLoc) {
21516 OpenMPDependClauseKind DepKind = Data.DepKind;
21517 SourceLocation DepLoc = Data.DepLoc;
21518 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
21519 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
21520 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21521 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_depend);
21522 return nullptr;
21523 }
21524 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
21525 DepKind == OMPC_DEPEND_mutexinoutset) {
21526 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
21527 return nullptr;
21528 }
21529 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
21530 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21531 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
21532 DepKind == OMPC_DEPEND_sink ||
21533 ((getLangOpts().OpenMP < 50 ||
21534 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21535 DepKind == OMPC_DEPEND_depobj))) {
21536 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
21537 OMPC_DEPEND_outallmemory,
21538 OMPC_DEPEND_inoutallmemory};
21539 if (getLangOpts().OpenMP < 50 ||
21540 DSAStack->getCurrentDirective() == OMPD_depobj)
21541 Except.push_back(OMPC_DEPEND_depobj);
21542 if (getLangOpts().OpenMP < 51)
21543 Except.push_back(OMPC_DEPEND_inoutset);
21544 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
21545 ? "depend modifier(iterator) or "
21546 : "";
21547 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21548 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
21549 /*Last=*/OMPC_DEPEND_unknown,
21550 Except)
21551 << getOpenMPClauseNameForDiag(OMPC_depend);
21552 return nullptr;
21553 }
21554 if (DepModifier &&
21555 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
21556 Diag(DepModifier->getExprLoc(),
21557 diag::err_omp_depend_sink_source_with_modifier);
21558 return nullptr;
21559 }
21560 if (DepModifier &&
21561 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
21562 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
21563
21565 DSAStackTy::OperatorOffsetTy OpsOffs;
21566 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
21567
21568 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
21569 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
21570 SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
21571 Vars = VarOffset.Vars;
21572 OpsOffs = VarOffset.OpsOffs;
21573 TotalDepCount = VarOffset.TotalDepCount;
21574 } else {
21575 for (Expr *RefExpr : VarList) {
21576 assert(RefExpr && "NULL expr in OpenMP depend clause.");
21577 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21578 // It will be analyzed later.
21579 Vars.push_back(RefExpr);
21580 continue;
21581 }
21582
21583 SourceLocation ELoc = RefExpr->getExprLoc();
21584 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
21585 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
21586 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
21587 if (OMPDependTFound)
21588 OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack,
21589 DepKind == OMPC_DEPEND_depobj);
21590 if (DepKind == OMPC_DEPEND_depobj) {
21591 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21592 // List items used in depend clauses with the depobj dependence type
21593 // must be expressions of the omp_depend_t type.
21594 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21595 !RefExpr->isInstantiationDependent() &&
21596 !RefExpr->containsUnexpandedParameterPack() &&
21597 (OMPDependTFound &&
21598 !getASTContext().hasSameUnqualifiedType(
21599 DSAStack->getOMPDependT(), RefExpr->getType()))) {
21600 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21601 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
21602 continue;
21603 }
21604 if (!RefExpr->isLValue()) {
21605 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21606 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
21607 continue;
21608 }
21609 } else {
21610 // OpenMP 5.0 [2.17.11, Restrictions]
21611 // List items used in depend clauses cannot be zero-length array
21612 // sections.
21613 QualType ExprTy = RefExpr->getType().getNonReferenceType();
21614 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
21615 if (OASE) {
21616 QualType BaseType =
21618 if (BaseType.isNull())
21619 return nullptr;
21620 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21621 ExprTy = ATy->getElementType();
21622 else
21623 ExprTy = BaseType->getPointeeType();
21624 if (BaseType.isNull() || ExprTy.isNull())
21625 return nullptr;
21626 ExprTy = ExprTy.getNonReferenceType();
21627 const Expr *Length = OASE->getLength();
21629 if (Length && !Length->isValueDependent() &&
21630 Length->EvaluateAsInt(Result, getASTContext()) &&
21631 Result.Val.getInt().isZero()) {
21632 Diag(ELoc,
21633 diag::err_omp_depend_zero_length_array_section_not_allowed)
21634 << SimpleExpr->getSourceRange();
21635 continue;
21636 }
21637 }
21638
21639 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21640 // List items used in depend clauses with the in, out, inout,
21641 // inoutset, or mutexinoutset dependence types cannot be
21642 // expressions of the omp_depend_t type.
21643 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21644 !RefExpr->isInstantiationDependent() &&
21645 !RefExpr->containsUnexpandedParameterPack() &&
21646 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
21647 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
21648 ExprTy.getTypePtr()))) {
21649 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21650 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21651 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21652 << RefExpr->getSourceRange();
21653 continue;
21654 }
21655
21656 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
21657 if (ASE && !ASE->getBase()->isTypeDependent() &&
21658 !ASE->getBase()
21659 ->getType()
21660 .getNonReferenceType()
21661 ->isPointerType() &&
21662 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
21663 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21664 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21665 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21666 << RefExpr->getSourceRange();
21667 continue;
21668 }
21669
21670 ExprResult Res;
21671 {
21673 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
21674 RefExpr->IgnoreParenImpCasts());
21675 }
21676 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
21678 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21679 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21680 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21681 << RefExpr->getSourceRange();
21682 continue;
21683 }
21684 }
21685 }
21686 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21687 }
21688 }
21689
21690 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
21691 DepKind != OMPC_DEPEND_outallmemory &&
21692 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
21693 return nullptr;
21694
21695 auto *C = OMPDependClause::Create(
21696 getASTContext(), StartLoc, LParenLoc, EndLoc,
21697 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
21698 TotalDepCount.getZExtValue());
21699 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
21700 DSAStack->isParentOrderedRegion())
21701 DSAStack->addDoacrossDependClause(C, OpsOffs);
21702 return C;
21703}
21704
21707 SourceLocation LParenLoc, SourceLocation ModifierLoc,
21708 SourceLocation EndLoc) {
21709 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
21710 "Unexpected device modifier in OpenMP < 50.");
21711
21712 bool ErrorFound = false;
21713 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
21714 std::string Values =
21715 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
21716 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21717 << Values << getOpenMPClauseNameForDiag(OMPC_device);
21718 ErrorFound = true;
21719 }
21720
21721 Expr *ValExpr = Device;
21722 Stmt *HelperValStmt = nullptr;
21723
21724 // OpenMP [2.9.1, Restrictions]
21725 // The device expression must evaluate to a non-negative integer value.
21726 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device,
21727 /*StrictlyPositive=*/false) ||
21728 ErrorFound;
21729 if (ErrorFound)
21730 return nullptr;
21731
21732 // OpenMP 5.0 [2.12.5, Restrictions]
21733 // In case of ancestor device-modifier, a requires directive with
21734 // the reverse_offload clause must be specified.
21735 if (Modifier == OMPC_DEVICE_ancestor) {
21736 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
21737 SemaRef.targetDiag(
21738 StartLoc,
21739 diag::err_omp_device_ancestor_without_requires_reverse_offload);
21740 ErrorFound = true;
21741 }
21742 }
21743
21744 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
21745 OpenMPDirectiveKind CaptureRegion =
21746 getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP);
21747 if (CaptureRegion != OMPD_unknown &&
21748 !SemaRef.CurContext->isDependentContext()) {
21749 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
21750 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21751 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
21752 HelperValStmt = buildPreInits(getASTContext(), Captures);
21753 }
21754
21755 return new (getASTContext())
21756 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
21757 LParenLoc, ModifierLoc, EndLoc);
21758}
21759
21761 DSAStackTy *Stack, QualType QTy,
21762 bool FullCheck = true) {
21763 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
21764 return false;
21765 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
21766 !QTy.isTriviallyCopyableType(SemaRef.Context))
21767 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
21768 return true;
21769}
21770
21771/// Return true if it can be proven that the provided array expression
21772/// (array section or array subscript) does NOT specify the whole size of the
21773/// array whose base type is \a BaseQTy.
21775 const Expr *E,
21776 QualType BaseQTy) {
21777 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21778
21779 // If this is an array subscript, it refers to the whole size if the size of
21780 // the dimension is constant and equals 1. Also, an array section assumes the
21781 // format of an array subscript if no colon is used.
21782 if (isa<ArraySubscriptExpr>(E) ||
21783 (OASE && OASE->getColonLocFirst().isInvalid())) {
21784 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21785 return ATy->getSExtSize() != 1;
21786 // Size can't be evaluated statically.
21787 return false;
21788 }
21789
21790 assert(OASE && "Expecting array section if not an array subscript.");
21791 const Expr *LowerBound = OASE->getLowerBound();
21792 const Expr *Length = OASE->getLength();
21793
21794 // If there is a lower bound that does not evaluates to zero, we are not
21795 // covering the whole dimension.
21796 if (LowerBound) {
21797 Expr::EvalResult Result;
21798 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
21799 return false; // Can't get the integer value as a constant.
21800
21801 llvm::APSInt ConstLowerBound = Result.Val.getInt();
21802 if (ConstLowerBound.getSExtValue())
21803 return true;
21804 }
21805
21806 // If we don't have a length we covering the whole dimension.
21807 if (!Length)
21808 return false;
21809
21810 // If the base is a pointer, we don't have a way to get the size of the
21811 // pointee.
21812 if (BaseQTy->isPointerType())
21813 return false;
21814
21815 // We can only check if the length is the same as the size of the dimension
21816 // if we have a constant array.
21817 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
21818 if (!CATy)
21819 return false;
21820
21821 Expr::EvalResult Result;
21822 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21823 return false; // Can't get the integer value as a constant.
21824
21825 llvm::APSInt ConstLength = Result.Val.getInt();
21826 return CATy->getSExtSize() != ConstLength.getSExtValue();
21827}
21828
21829// Return true if it can be proven that the provided array expression (array
21830// section or array subscript) does NOT specify a single element of the array
21831// whose base type is \a BaseQTy.
21833 const Expr *E,
21834 QualType BaseQTy) {
21835 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21836
21837 // An array subscript always refer to a single element. Also, an array section
21838 // assumes the format of an array subscript if no colon is used.
21839 if (isa<ArraySubscriptExpr>(E) ||
21840 (OASE && OASE->getColonLocFirst().isInvalid()))
21841 return false;
21842
21843 assert(OASE && "Expecting array section if not an array subscript.");
21844 const Expr *Length = OASE->getLength();
21845
21846 // If we don't have a length we have to check if the array has unitary size
21847 // for this dimension. Also, we should always expect a length if the base type
21848 // is pointer.
21849 if (!Length) {
21850 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21851 return ATy->getSExtSize() != 1;
21852 // We cannot assume anything.
21853 return false;
21854 }
21855
21856 // Check if the length evaluates to 1.
21857 Expr::EvalResult Result;
21858 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21859 return false; // Can't get the integer value as a constant.
21860
21861 llvm::APSInt ConstLength = Result.Val.getInt();
21862 return ConstLength.getSExtValue() != 1;
21863}
21864
21865// The base of elements of list in a map clause have to be either:
21866// - a reference to variable or field.
21867// - a member expression.
21868// - an array expression.
21869//
21870// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
21871// reference to 'r'.
21872//
21873// If we have:
21874//
21875// struct SS {
21876// Bla S;
21877// foo() {
21878// #pragma omp target map (S.Arr[:12]);
21879// }
21880// }
21881//
21882// We want to retrieve the member expression 'this->S';
21883
21884// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
21885// If a list item is an array section, it must specify contiguous storage.
21886//
21887// For this restriction it is sufficient that we make sure only references
21888// to variables or fields and array expressions, and that no array sections
21889// exist except in the rightmost expression (unless they cover the whole
21890// dimension of the array). E.g. these would be invalid:
21891//
21892// r.ArrS[3:5].Arr[6:7]
21893//
21894// r.ArrS[3:5].x
21895//
21896// but these would be valid:
21897// r.ArrS[3].Arr[6:7]
21898//
21899// r.ArrS[3].x
21900namespace {
21901class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
21902 Sema &SemaRef;
21903 OpenMPClauseKind CKind = OMPC_unknown;
21904 OpenMPDirectiveKind DKind = OMPD_unknown;
21906 bool IsNonContiguous = false;
21907 bool NoDiagnose = false;
21908 const Expr *RelevantExpr = nullptr;
21909 bool AllowUnitySizeArraySection = true;
21910 bool AllowWholeSizeArraySection = true;
21911 bool AllowAnotherPtr = true;
21912 SourceLocation ELoc;
21913 SourceRange ERange;
21914
21915 void emitErrorMsg() {
21916 // If nothing else worked, this is not a valid map clause expression.
21917 if (SemaRef.getLangOpts().OpenMP < 50) {
21918 SemaRef.Diag(ELoc,
21919 diag::err_omp_expected_named_var_member_or_array_expression)
21920 << ERange;
21921 } else {
21922 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21923 << getOpenMPClauseNameForDiag(CKind) << ERange;
21924 }
21925 }
21926
21927public:
21928 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
21929 if (!isa<VarDecl>(DRE->getDecl())) {
21930 emitErrorMsg();
21931 return false;
21932 }
21933 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21934 RelevantExpr = DRE;
21935 // Record the component.
21936 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
21937 return true;
21938 }
21939
21940 bool VisitMemberExpr(MemberExpr *ME) {
21941 Expr *E = ME;
21942 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
21943
21944 if (isa<CXXThisExpr>(BaseE)) {
21945 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21946 // We found a base expression: this->Val.
21947 RelevantExpr = ME;
21948 } else {
21949 E = BaseE;
21950 }
21951
21952 if (!isa<FieldDecl>(ME->getMemberDecl())) {
21953 if (!NoDiagnose) {
21954 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
21955 << ME->getSourceRange();
21956 return false;
21957 }
21958 if (RelevantExpr)
21959 return false;
21960 return Visit(E);
21961 }
21962
21963 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
21964
21965 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
21966 // A bit-field cannot appear in a map clause.
21967 //
21968 if (FD->isBitField()) {
21969 if (!NoDiagnose) {
21970 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
21971 << ME->getSourceRange() << getOpenMPClauseNameForDiag(CKind);
21972 return false;
21973 }
21974 if (RelevantExpr)
21975 return false;
21976 return Visit(E);
21977 }
21978
21979 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21980 // If the type of a list item is a reference to a type T then the type
21981 // will be considered to be T for all purposes of this clause.
21982 QualType CurType = BaseE->getType().getNonReferenceType();
21983
21984 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
21985 // A list item cannot be a variable that is a member of a structure with
21986 // a union type.
21987 //
21988 if (CurType->isUnionType()) {
21989 if (!NoDiagnose) {
21990 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
21991 << ME->getSourceRange();
21992 return false;
21993 }
21994 return RelevantExpr || Visit(E);
21995 }
21996
21997 // If we got a member expression, we should not expect any array section
21998 // before that:
21999 //
22000 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
22001 // If a list item is an element of a structure, only the rightmost symbol
22002 // of the variable reference can be an array section.
22003 //
22004 AllowUnitySizeArraySection = false;
22005 AllowWholeSizeArraySection = false;
22006
22007 // Record the component.
22008 Components.emplace_back(ME, FD, IsNonContiguous);
22009 return RelevantExpr || Visit(E);
22010 }
22011
22012 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
22013 Expr *E = AE->getBase()->IgnoreParenImpCasts();
22014
22015 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
22016 if (!NoDiagnose) {
22017 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22018 << 0 << AE->getSourceRange();
22019 return false;
22020 }
22021 return RelevantExpr || Visit(E);
22022 }
22023
22024 // If we got an array subscript that express the whole dimension we
22025 // can have any array expressions before. If it only expressing part of
22026 // the dimension, we can only have unitary-size array expressions.
22028 AllowWholeSizeArraySection = false;
22029
22030 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
22031 Expr::EvalResult Result;
22032 if (!AE->getIdx()->isValueDependent() &&
22033 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
22034 !Result.Val.getInt().isZero()) {
22035 SemaRef.Diag(AE->getIdx()->getExprLoc(),
22036 diag::err_omp_invalid_map_this_expr);
22037 SemaRef.Diag(AE->getIdx()->getExprLoc(),
22038 diag::note_omp_invalid_subscript_on_this_ptr_map);
22039 }
22040 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22041 RelevantExpr = TE;
22042 }
22043
22044 // Record the component - we don't have any declaration associated.
22045 Components.emplace_back(AE, nullptr, IsNonContiguous);
22046
22047 return RelevantExpr || Visit(E);
22048 }
22049
22050 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
22051 // After OMP 5.0 Array section in reduction clause will be implicitly
22052 // mapped
22053 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
22054 "Array sections cannot be implicitly mapped.");
22055 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
22056 QualType CurType =
22058
22059 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22060 // If the type of a list item is a reference to a type T then the type
22061 // will be considered to be T for all purposes of this clause.
22062 if (CurType->isReferenceType())
22063 CurType = CurType->getPointeeType();
22064
22065 bool IsPointer = CurType->isAnyPointerType();
22066
22067 if (!IsPointer && !CurType->isArrayType()) {
22068 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22069 << 0 << OASE->getSourceRange();
22070 return false;
22071 }
22072
22073 bool NotWhole =
22074 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
22075 bool NotUnity =
22076 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
22077
22078 if (AllowWholeSizeArraySection) {
22079 // Any array section is currently allowed. Allowing a whole size array
22080 // section implies allowing a unity array section as well.
22081 //
22082 // If this array section refers to the whole dimension we can still
22083 // accept other array sections before this one, except if the base is a
22084 // pointer. Otherwise, only unitary sections are accepted.
22085 if (NotWhole || IsPointer)
22086 AllowWholeSizeArraySection = false;
22087 } else if (DKind == OMPD_target_update &&
22088 SemaRef.getLangOpts().OpenMP >= 50) {
22089 if (IsPointer && !AllowAnotherPtr)
22090 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
22091 << /*array of unknown bound */ 1;
22092 else
22093 IsNonContiguous = true;
22094 } else if (AllowUnitySizeArraySection && NotUnity) {
22095 // A unity or whole array section is not allowed and that is not
22096 // compatible with the properties of the current array section.
22097 if (NoDiagnose)
22098 return false;
22099 SemaRef.Diag(ELoc,
22100 diag::err_array_section_does_not_specify_contiguous_storage)
22101 << OASE->getSourceRange();
22102 return false;
22103 }
22104
22105 if (IsPointer)
22106 AllowAnotherPtr = false;
22107
22108 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
22109 Expr::EvalResult ResultR;
22110 Expr::EvalResult ResultL;
22111 if (!OASE->getLength()->isValueDependent() &&
22112 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
22113 !ResultR.Val.getInt().isOne()) {
22114 SemaRef.Diag(OASE->getLength()->getExprLoc(),
22115 diag::err_omp_invalid_map_this_expr);
22116 SemaRef.Diag(OASE->getLength()->getExprLoc(),
22117 diag::note_omp_invalid_length_on_this_ptr_mapping);
22118 }
22119 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
22120 OASE->getLowerBound()->EvaluateAsInt(ResultL,
22121 SemaRef.getASTContext()) &&
22122 !ResultL.Val.getInt().isZero()) {
22123 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
22124 diag::err_omp_invalid_map_this_expr);
22125 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
22126 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
22127 }
22128 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22129 RelevantExpr = TE;
22130 }
22131
22132 // Record the component - we don't have any declaration associated.
22133 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
22134 return RelevantExpr || Visit(E);
22135 }
22136 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
22137 Expr *Base = E->getBase();
22138
22139 // Record the component - we don't have any declaration associated.
22140 Components.emplace_back(E, nullptr, IsNonContiguous);
22141
22142 return Visit(Base->IgnoreParenImpCasts());
22143 }
22144
22145 bool VisitUnaryOperator(UnaryOperator *UO) {
22146 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
22147 UO->getOpcode() != UO_Deref) {
22148 emitErrorMsg();
22149 return false;
22150 }
22151 if (!RelevantExpr) {
22152 // Record the component if haven't found base decl.
22153 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
22154 }
22155 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
22156 }
22157 bool VisitBinaryOperator(BinaryOperator *BO) {
22158 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
22159 emitErrorMsg();
22160 return false;
22161 }
22162
22163 // Pointer arithmetic is the only thing we expect to happen here so after we
22164 // make sure the binary operator is a pointer type, the only thing we need
22165 // to do is to visit the subtree that has the same type as root (so that we
22166 // know the other subtree is just an offset)
22167 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
22168 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
22169 Components.emplace_back(BO, nullptr, false);
22170 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
22171 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
22172 "Either LHS or RHS have base decl inside");
22173 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
22174 return RelevantExpr || Visit(LE);
22175 return RelevantExpr || Visit(RE);
22176 }
22177 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
22178 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22179 RelevantExpr = CTE;
22180 Components.emplace_back(CTE, nullptr, IsNonContiguous);
22181 return true;
22182 }
22183 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
22184 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22185 Components.emplace_back(COCE, nullptr, IsNonContiguous);
22186 return true;
22187 }
22188 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
22189 Expr *Source = E->getSourceExpr();
22190 if (!Source) {
22191 emitErrorMsg();
22192 return false;
22193 }
22194 return Visit(Source);
22195 }
22196 bool VisitStmt(Stmt *) {
22197 emitErrorMsg();
22198 return false;
22199 }
22200 const Expr *getFoundBase() const { return RelevantExpr; }
22201 explicit MapBaseChecker(
22202 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
22204 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
22205 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
22206 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
22207};
22208} // namespace
22209
22210/// Return the expression of the base of the mappable expression or null if it
22211/// cannot be determined and do all the necessary checks to see if the
22212/// expression is valid as a standalone mappable expression. In the process,
22213/// record all the components of the expression.
22215 Sema &SemaRef, Expr *E,
22217 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
22218 SourceLocation ELoc = E->getExprLoc();
22219 SourceRange ERange = E->getSourceRange();
22220 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
22221 ERange);
22222 if (Checker.Visit(E->IgnoreParens())) {
22223 // Check if the highest dimension array section has length specified
22224 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
22225 (CKind == OMPC_to || CKind == OMPC_from)) {
22226 auto CI = CurComponents.rbegin();
22227 auto CE = CurComponents.rend();
22228 for (; CI != CE; ++CI) {
22229 const auto *OASE =
22230 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
22231 if (!OASE)
22232 continue;
22233 if (OASE && OASE->getLength())
22234 break;
22235 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
22236 << ERange;
22237 }
22238 }
22239 return Checker.getFoundBase();
22240 }
22241 return nullptr;
22242}
22243
22244// Return true if expression E associated with value VD has conflicts with other
22245// map information.
22247 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
22248 bool CurrentRegionOnly,
22250 OpenMPClauseKind CKind) {
22251 assert(VD && E);
22252 SourceLocation ELoc = E->getExprLoc();
22253 SourceRange ERange = E->getSourceRange();
22254
22255 // In order to easily check the conflicts we need to match each component of
22256 // the expression under test with the components of the expressions that are
22257 // already in the stack.
22258
22259 assert(!CurComponents.empty() && "Map clause expression with no components!");
22260 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
22261 "Map clause expression with unexpected base!");
22262
22263 // Variables to help detecting enclosing problems in data environment nests.
22264 bool IsEnclosedByDataEnvironmentExpr = false;
22265 const Expr *EnclosingExpr = nullptr;
22266
22267 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
22268 VD, CurrentRegionOnly,
22269 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
22270 ERange, CKind, &EnclosingExpr,
22272 StackComponents,
22273 OpenMPClauseKind Kind) {
22274 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
22275 return false;
22276 assert(!StackComponents.empty() &&
22277 "Map clause expression with no components!");
22278 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
22279 "Map clause expression with unexpected base!");
22280 (void)VD;
22281
22282 // The whole expression in the stack.
22283 const Expr *RE = StackComponents.front().getAssociatedExpression();
22284
22285 // Expressions must start from the same base. Here we detect at which
22286 // point both expressions diverge from each other and see if we can
22287 // detect if the memory referred to both expressions is contiguous and
22288 // do not overlap.
22289 auto CI = CurComponents.rbegin();
22290 auto CE = CurComponents.rend();
22291 auto SI = StackComponents.rbegin();
22292 auto SE = StackComponents.rend();
22293 for (; CI != CE && SI != SE; ++CI, ++SI) {
22294
22295 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
22296 // At most one list item can be an array item derived from a given
22297 // variable in map clauses of the same construct.
22298 if (CurrentRegionOnly &&
22299 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
22300 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
22301 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
22302 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
22303 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
22304 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
22305 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
22306 diag::err_omp_multiple_array_items_in_map_clause)
22307 << CI->getAssociatedExpression()->getSourceRange();
22308 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
22309 diag::note_used_here)
22310 << SI->getAssociatedExpression()->getSourceRange();
22311 return true;
22312 }
22313
22314 // Do both expressions have the same kind?
22315 if (CI->getAssociatedExpression()->getStmtClass() !=
22316 SI->getAssociatedExpression()->getStmtClass())
22317 break;
22318
22319 // Are we dealing with different variables/fields?
22320 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
22321 break;
22322 }
22323 // Check if the extra components of the expressions in the enclosing
22324 // data environment are redundant for the current base declaration.
22325 // If they are, the maps completely overlap, which is legal.
22326 for (; SI != SE; ++SI) {
22327 QualType Type;
22328 if (const auto *ASE =
22329 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
22330 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
22331 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
22332 SI->getAssociatedExpression())) {
22333 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
22335 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
22336 SI->getAssociatedExpression())) {
22337 Type = OASE->getBase()->getType()->getPointeeType();
22338 }
22339 if (Type.isNull() || Type->isAnyPointerType() ||
22341 SemaRef, SI->getAssociatedExpression(), Type))
22342 break;
22343 }
22344
22345 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
22346 // List items of map clauses in the same construct must not share
22347 // original storage.
22348 //
22349 // If the expressions are exactly the same or one is a subset of the
22350 // other, it means they are sharing storage.
22351 if (CI == CE && SI == SE) {
22352 if (CurrentRegionOnly) {
22353 if (CKind == OMPC_map) {
22354 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22355 } else {
22356 assert(CKind == OMPC_to || CKind == OMPC_from);
22357 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22358 << ERange;
22359 }
22360 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22361 << RE->getSourceRange();
22362 return true;
22363 }
22364 // If we find the same expression in the enclosing data environment,
22365 // that is legal.
22366 IsEnclosedByDataEnvironmentExpr = true;
22367 return false;
22368 }
22369
22370 QualType DerivedType =
22371 std::prev(CI)->getAssociatedDeclaration()->getType();
22372 SourceLocation DerivedLoc =
22373 std::prev(CI)->getAssociatedExpression()->getExprLoc();
22374
22375 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22376 // If the type of a list item is a reference to a type T then the type
22377 // will be considered to be T for all purposes of this clause.
22378 DerivedType = DerivedType.getNonReferenceType();
22379
22380 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
22381 // A variable for which the type is pointer and an array section
22382 // derived from that variable must not appear as list items of map
22383 // clauses of the same construct.
22384 //
22385 // Also, cover one of the cases in:
22386 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
22387 // If any part of the original storage of a list item has corresponding
22388 // storage in the device data environment, all of the original storage
22389 // must have corresponding storage in the device data environment.
22390 //
22391 if (DerivedType->isAnyPointerType()) {
22392 if (CI == CE || SI == SE) {
22393 SemaRef.Diag(
22394 DerivedLoc,
22395 diag::err_omp_pointer_mapped_along_with_derived_section)
22396 << DerivedLoc;
22397 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22398 << RE->getSourceRange();
22399 return true;
22400 }
22401 if (CI->getAssociatedExpression()->getStmtClass() !=
22402 SI->getAssociatedExpression()->getStmtClass() ||
22403 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
22404 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
22405 assert(CI != CE && SI != SE);
22406 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
22407 << DerivedLoc;
22408 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22409 << RE->getSourceRange();
22410 return true;
22411 }
22412 }
22413
22414 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
22415 // List items of map clauses in the same construct must not share
22416 // original storage.
22417 //
22418 // An expression is a subset of the other.
22419 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
22420 if (CKind == OMPC_map) {
22421 if (CI != CE || SI != SE) {
22422 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
22423 // a pointer.
22424 auto Begin =
22425 CI != CE ? CurComponents.begin() : StackComponents.begin();
22426 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
22427 auto It = Begin;
22428 while (It != End && !It->getAssociatedDeclaration())
22429 std::advance(It, 1);
22430 assert(It != End &&
22431 "Expected at least one component with the declaration.");
22432 if (It != Begin && It->getAssociatedDeclaration()
22433 ->getType()
22434 .getCanonicalType()
22435 ->isAnyPointerType()) {
22436 IsEnclosedByDataEnvironmentExpr = false;
22437 EnclosingExpr = nullptr;
22438 return false;
22439 }
22440 }
22441 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22442 } else {
22443 assert(CKind == OMPC_to || CKind == OMPC_from);
22444 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22445 << ERange;
22446 }
22447 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22448 << RE->getSourceRange();
22449 return true;
22450 }
22451
22452 // The current expression uses the same base as other expression in the
22453 // data environment but does not contain it completely.
22454 if (!CurrentRegionOnly && SI != SE)
22455 EnclosingExpr = RE;
22456
22457 // The current expression is a subset of the expression in the data
22458 // environment.
22459 IsEnclosedByDataEnvironmentExpr |=
22460 (!CurrentRegionOnly && CI != CE && SI == SE);
22461
22462 return false;
22463 });
22464
22465 if (CurrentRegionOnly)
22466 return FoundError;
22467
22468 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
22469 // If any part of the original storage of a list item has corresponding
22470 // storage in the device data environment, all of the original storage must
22471 // have corresponding storage in the device data environment.
22472 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
22473 // If a list item is an element of a structure, and a different element of
22474 // the structure has a corresponding list item in the device data environment
22475 // prior to a task encountering the construct associated with the map clause,
22476 // then the list item must also have a corresponding list item in the device
22477 // data environment prior to the task encountering the construct.
22478 //
22479 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
22480 SemaRef.Diag(ELoc,
22481 diag::err_omp_original_storage_is_shared_and_does_not_contain)
22482 << ERange;
22483 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
22484 << EnclosingExpr->getSourceRange();
22485 return true;
22486 }
22487
22488 return FoundError;
22489}
22490
22491// Look up the user-defined mapper given the mapper name and mapped type, and
22492// build a reference to it.
22494 CXXScopeSpec &MapperIdScopeSpec,
22495 const DeclarationNameInfo &MapperId,
22496 QualType Type,
22497 Expr *UnresolvedMapper) {
22498 if (MapperIdScopeSpec.isInvalid())
22499 return ExprError();
22500 // Get the actual type for the array type.
22501 if (Type->isArrayType()) {
22502 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
22504 }
22505 // Find all user-defined mappers with the given MapperId.
22506 SmallVector<UnresolvedSet<8>, 4> Lookups;
22507 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
22508 Lookup.suppressDiagnostics();
22509 if (S) {
22510 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
22511 /*ObjectType=*/QualType())) {
22512 NamedDecl *D = Lookup.getRepresentativeDecl();
22513 while (S && !S->isDeclScope(D))
22514 S = S->getParent();
22515 if (S)
22516 S = S->getParent();
22517 Lookups.emplace_back();
22518 Lookups.back().append(Lookup.begin(), Lookup.end());
22519 Lookup.clear();
22520 }
22521 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
22522 // Extract the user-defined mappers with the given MapperId.
22523 Lookups.push_back(UnresolvedSet<8>());
22524 for (NamedDecl *D : ULE->decls()) {
22525 auto *DMD = cast<OMPDeclareMapperDecl>(D);
22526 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
22527 Lookups.back().addDecl(DMD);
22528 }
22529 }
22530 // Defer the lookup for dependent types. The results will be passed through
22531 // UnresolvedMapper on instantiation.
22532 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
22536 return !D->isInvalidDecl() &&
22537 (D->getType()->isDependentType() ||
22538 D->getType()->isInstantiationDependentType() ||
22539 D->getType()->containsUnexpandedParameterPack());
22540 })) {
22541 UnresolvedSet<8> URS;
22542 for (const UnresolvedSet<8> &Set : Lookups) {
22543 if (Set.empty())
22544 continue;
22545 URS.append(Set.begin(), Set.end());
22546 }
22548 SemaRef.Context, /*NamingClass=*/nullptr,
22549 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
22550 /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false,
22551 /*KnownInstantiationDependent=*/false);
22552 }
22553 SourceLocation Loc = MapperId.getLoc();
22554 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22555 // The type must be of struct, union or class type in C and C++
22557 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
22558 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
22559 return ExprError();
22560 }
22561 // Perform argument dependent lookup.
22562 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
22563 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
22564 // Return the first user-defined mapper with the desired type.
22566 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
22567 if (!D->isInvalidDecl() &&
22568 SemaRef.Context.hasSameType(D->getType(), Type))
22569 return D;
22570 return nullptr;
22571 }))
22572 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
22573 // Find the first user-defined mapper with a type derived from the desired
22574 // type.
22576 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
22577 if (!D->isInvalidDecl() &&
22578 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
22579 !Type.isMoreQualifiedThan(D->getType(),
22580 SemaRef.getASTContext()))
22581 return D;
22582 return nullptr;
22583 })) {
22584 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
22585 /*DetectVirtual=*/false);
22586 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
22587 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
22588 VD->getType().getUnqualifiedType()))) {
22589 if (SemaRef.CheckBaseClassAccess(
22590 Loc, VD->getType(), Type, Paths.front(),
22591 /*DiagID=*/0) != Sema::AR_inaccessible) {
22592 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
22593 }
22594 }
22595 }
22596 }
22597 // Report error if a mapper is specified, but cannot be found.
22598 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
22599 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
22600 << Type << MapperId.getName();
22601 return ExprError();
22602 }
22603 return ExprEmpty();
22604}
22605
22606namespace {
22607// Utility struct that gathers all the related lists associated with a mappable
22608// expression.
22609struct MappableVarListInfo {
22610 // The list of expressions.
22611 ArrayRef<Expr *> VarList;
22612 // The list of processed expressions.
22613 SmallVector<Expr *, 16> ProcessedVarList;
22614 // The mappble components for each expression.
22616 // The base declaration of the variable.
22617 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
22618 // The reference to the user-defined mapper associated with every expression.
22619 SmallVector<Expr *, 16> UDMapperList;
22620
22621 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
22622 // We have a list of components and base declarations for each entry in the
22623 // variable list.
22624 VarComponents.reserve(VarList.size());
22625 VarBaseDeclarations.reserve(VarList.size());
22626 }
22627};
22628} // namespace
22629
22631 DSAStackTy *Stack,
22633
22634 const RecordDecl *RD = BaseType->getAsRecordDecl();
22635 SourceRange Range = RD->getSourceRange();
22636 DeclarationNameInfo ImplicitName;
22637 // Dummy variable _s for Mapper.
22638 VarDecl *VD = buildVarDecl(S, Range.getEnd(), BaseType, "_s");
22639 DeclRefExpr *MapperVarRef =
22640 buildDeclRefExpr(S, VD, BaseType, SourceLocation());
22641
22642 // Create implicit map clause for mapper.
22644 for (auto *FD : RD->fields()) {
22645 Expr *BE = S.BuildMemberExpr(
22646 MapperVarRef, /*IsArrow=*/false, Range.getBegin(),
22647 NestedNameSpecifierLoc(), Range.getBegin(), FD,
22649 /*HadMultipleCandidates=*/false,
22651 FD->getType(), VK_LValue, OK_Ordinary);
22652 SExprs.push_back(BE);
22653 }
22654 CXXScopeSpec MapperIdScopeSpec;
22655 DeclarationNameInfo MapperId;
22656 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
22657
22658 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
22659 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec,
22660 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
22661 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), SExprs,
22662 OMPVarListLocTy());
22663 Maps.push_back(MapClause);
22664 return MapperVarRef;
22665}
22666
22668 DSAStackTy *Stack) {
22669
22670 // Build impilicit map for mapper
22672 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
22673
22674 const RecordDecl *RD = BaseType->getAsRecordDecl();
22675 // AST context is RD's ParentASTContext().
22676 ASTContext &Ctx = RD->getParentASTContext();
22677 // DeclContext is RD's DeclContext.
22678 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
22679
22680 // Create implicit default mapper for "RD".
22681 DeclarationName MapperId;
22682 auto &DeclNames = Ctx.DeclarationNames;
22683 MapperId = DeclNames.getIdentifier(&Ctx.Idents.get("default"));
22684 auto *DMD = OMPDeclareMapperDecl::Create(Ctx, DCT, SourceLocation(), MapperId,
22685 BaseType, MapperId, Maps, nullptr);
22686 Scope *Scope = S.getScopeForContext(DCT);
22687 if (Scope)
22688 S.PushOnScopeChains(DMD, Scope, /*AddToContext=*/false);
22689 DCT->addDecl(DMD);
22690 DMD->setAccess(clang::AS_none);
22691 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22692 VD->setDeclContext(DMD);
22693 VD->setLexicalDeclContext(DMD);
22694 DMD->addDecl(VD);
22695 DMD->setMapperVarRef(MapperVarRef);
22696 FieldDecl *FD = *RD->field_begin();
22697 // create mapper refence.
22699 DMD, false, SourceLocation(), BaseType, VK_LValue);
22700}
22701
22702// Look up the user-defined mapper given the mapper name and mapper type,
22703// return true if found one.
22704static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
22705 CXXScopeSpec &MapperIdScopeSpec,
22706 const DeclarationNameInfo &MapperId,
22707 QualType Type) {
22708 // Find all user-defined mappers with the given MapperId.
22709 SmallVector<UnresolvedSet<8>, 4> Lookups;
22710 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
22711 Lookup.suppressDiagnostics();
22712 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
22713 /*ObjectType=*/QualType())) {
22714 NamedDecl *D = Lookup.getRepresentativeDecl();
22715 while (S && !S->isDeclScope(D))
22716 S = S->getParent();
22717 if (S)
22718 S = S->getParent();
22719 Lookups.emplace_back();
22720 Lookups.back().append(Lookup.begin(), Lookup.end());
22721 Lookup.clear();
22722 }
22723 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
22727 return !D->isInvalidDecl() &&
22728 (D->getType()->isDependentType() ||
22729 D->getType()->isInstantiationDependentType() ||
22730 D->getType()->containsUnexpandedParameterPack());
22731 }))
22732 return false;
22733 // Perform argument dependent lookup.
22734 SourceLocation Loc = MapperId.getLoc();
22735 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
22736 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
22738 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
22739 if (!D->isInvalidDecl() &&
22740 SemaRef.Context.hasSameType(D->getType(), Type))
22741 return D;
22742 return nullptr;
22743 }))
22744 return true;
22745 // Find the first user-defined mapper with a type derived from the desired
22746 // type.
22748 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
22749 if (!D->isInvalidDecl() &&
22750 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
22751 !Type.isMoreQualifiedThan(D->getType(), SemaRef.getASTContext()))
22752 return D;
22753 return nullptr;
22754 });
22755 if (!VD)
22756 return false;
22757 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
22758 /*DetectVirtual=*/false);
22759 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
22760 bool IsAmbiguous = !Paths.isAmbiguous(
22762 if (IsAmbiguous)
22763 return false;
22764 if (SemaRef.CheckBaseClassAccess(Loc, VD->getType(), Type, Paths.front(),
22765 /*DiagID=*/0) != Sema::AR_inaccessible)
22766 return true;
22767 }
22768 return false;
22769}
22770
22771static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
22772 QualType CanonType, const Expr *E) {
22773
22774 // DFS over data members in structures/classes.
22776 {CanonType, nullptr});
22777 llvm::DenseMap<const Type *, bool> Visited;
22778 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
22779 while (!Types.empty()) {
22780 auto [BaseType, CurFD] = Types.pop_back_val();
22781 while (ParentChain.back().second == 0)
22782 ParentChain.pop_back();
22783 --ParentChain.back().second;
22784 if (BaseType.isNull())
22785 continue;
22786 // Only structs/classes are allowed to have mappers.
22787 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
22788 if (!RD)
22789 continue;
22790 auto It = Visited.find(BaseType.getTypePtr());
22791 if (It == Visited.end()) {
22792 // Try to find the associated user-defined mapper.
22793 CXXScopeSpec MapperIdScopeSpec;
22794 DeclarationNameInfo DefaultMapperId;
22796 &S.Context.Idents.get("default")));
22797 DefaultMapperId.setLoc(E->getExprLoc());
22798 bool HasUDMapper =
22799 hasUserDefinedMapper(S, Stack->getCurScope(), MapperIdScopeSpec,
22800 DefaultMapperId, BaseType);
22801 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
22802 }
22803 // Found default mapper.
22804 if (It->second)
22805 return true;
22806 // Check for the "default" mapper for data members.
22807 bool FirstIter = true;
22808 for (FieldDecl *FD : RD->fields()) {
22809 if (!FD)
22810 continue;
22811 QualType FieldTy = FD->getType();
22812 if (FieldTy.isNull() ||
22813 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
22814 continue;
22815 if (FirstIter) {
22816 FirstIter = false;
22817 ParentChain.emplace_back(CurFD, 1);
22818 } else {
22819 ++ParentChain.back().second;
22820 }
22821 Types.emplace_back(FieldTy, FD);
22822 }
22823 }
22824 return false;
22825}
22826
22827// Check the validity of the provided variable list for the provided clause kind
22828// \a CKind. In the check process the valid expressions, mappable expression
22829// components, variables, and user-defined mappers are extracted and used to
22830// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
22831// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
22832// and \a MapperId are expected to be valid if the clause kind is 'map'.
22834 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
22835 MappableVarListInfo &MVLI, SourceLocation StartLoc,
22836 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
22837 ArrayRef<Expr *> UnresolvedMappers,
22839 ArrayRef<OpenMPMapModifierKind> Modifiers = {},
22840 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
22841 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
22842 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
22843 "Unexpected clause kind with mappable expressions!");
22844 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
22845
22846 // If the identifier of user-defined mapper is not specified, it is "default".
22847 // We do not change the actual name in this clause to distinguish whether a
22848 // mapper is specified explicitly, i.e., it is not explicitly specified when
22849 // MapperId.getName() is empty.
22850 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
22851 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
22852 MapperId.setName(DeclNames.getIdentifier(
22853 &SemaRef.getASTContext().Idents.get("default")));
22854 MapperId.setLoc(StartLoc);
22855 }
22856
22857 // Iterators to find the current unresolved mapper expression.
22858 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
22859 bool UpdateUMIt = false;
22860 Expr *UnresolvedMapper = nullptr;
22861
22862 bool HasHoldModifier =
22863 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
22864
22865 // Keep track of the mappable components and base declarations in this clause.
22866 // Each entry in the list is going to have a list of components associated. We
22867 // record each set of the components so that we can build the clause later on.
22868 // In the end we should have the same amount of declarations and component
22869 // lists.
22870
22871 for (Expr *RE : MVLI.VarList) {
22872 assert(RE && "Null expr in omp to/from/map clause");
22873 SourceLocation ELoc = RE->getExprLoc();
22874
22875 // Find the current unresolved mapper expression.
22876 if (UpdateUMIt && UMIt != UMEnd) {
22877 UMIt++;
22878 assert(
22879 UMIt != UMEnd &&
22880 "Expect the size of UnresolvedMappers to match with that of VarList");
22881 }
22882 UpdateUMIt = true;
22883 if (UMIt != UMEnd)
22884 UnresolvedMapper = *UMIt;
22885
22886 const Expr *VE = RE->IgnoreParenLValueCasts();
22887
22888 if (VE->isValueDependent() || VE->isTypeDependent() ||
22889 VE->isInstantiationDependent() ||
22890 VE->containsUnexpandedParameterPack()) {
22891 // Try to find the associated user-defined mapper.
22893 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22894 VE->getType().getCanonicalType(), UnresolvedMapper);
22895 if (ER.isInvalid())
22896 continue;
22897 MVLI.UDMapperList.push_back(ER.get());
22898 // We can only analyze this information once the missing information is
22899 // resolved.
22900 MVLI.ProcessedVarList.push_back(RE);
22901 continue;
22902 }
22903
22905
22906 if (!RE->isLValue()) {
22907 if (SemaRef.getLangOpts().OpenMP < 50) {
22908 SemaRef.Diag(
22909 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
22910 << RE->getSourceRange();
22911 } else {
22912 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22913 << getOpenMPClauseNameForDiag(CKind) << RE->getSourceRange();
22914 }
22915 continue;
22916 }
22917
22919 ValueDecl *CurDeclaration = nullptr;
22920
22921 // Obtain the array or member expression bases if required. Also, fill the
22922 // components array with all the components identified in the process.
22923 const Expr *BE =
22924 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
22925 DSAS->getCurrentDirective(), NoDiagnose);
22926 if (!BE)
22927 continue;
22928
22929 assert(!CurComponents.empty() &&
22930 "Invalid mappable expression information.");
22931
22932 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
22933 // Add store "this" pointer to class in DSAStackTy for future checking
22934 DSAS->addMappedClassesQualTypes(TE->getType());
22935 // Try to find the associated user-defined mapper.
22937 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22938 VE->getType().getCanonicalType(), UnresolvedMapper);
22939 if (ER.isInvalid())
22940 continue;
22941 MVLI.UDMapperList.push_back(ER.get());
22942 // Skip restriction checking for variable or field declarations
22943 MVLI.ProcessedVarList.push_back(RE);
22944 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22945 MVLI.VarComponents.back().append(CurComponents.begin(),
22946 CurComponents.end());
22947 MVLI.VarBaseDeclarations.push_back(nullptr);
22948 continue;
22949 }
22950
22951 // For the following checks, we rely on the base declaration which is
22952 // expected to be associated with the last component. The declaration is
22953 // expected to be a variable or a field (if 'this' is being mapped).
22954 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
22955 assert(CurDeclaration && "Null decl on map clause.");
22956 assert(
22957 CurDeclaration->isCanonicalDecl() &&
22958 "Expecting components to have associated only canonical declarations.");
22959
22960 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
22961 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
22962
22963 assert((VD || FD) && "Only variables or fields are expected here!");
22964 (void)FD;
22965
22966 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
22967 // threadprivate variables cannot appear in a map clause.
22968 // OpenMP 4.5 [2.10.5, target update Construct]
22969 // threadprivate variables cannot appear in a from clause.
22970 if (VD && DSAS->isThreadPrivate(VD)) {
22971 if (NoDiagnose)
22972 continue;
22973 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
22974 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
22976 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
22977 continue;
22978 }
22979
22980 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22981 // A list item cannot appear in both a map clause and a data-sharing
22982 // attribute clause on the same construct.
22983
22984 // Check conflicts with other map clause expressions. We check the conflicts
22985 // with the current construct separately from the enclosing data
22986 // environment, because the restrictions are different. We only have to
22987 // check conflicts across regions for the map clauses.
22988 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
22989 /*CurrentRegionOnly=*/true, CurComponents, CKind))
22990 break;
22991 if (CKind == OMPC_map &&
22992 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
22993 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
22994 /*CurrentRegionOnly=*/false, CurComponents, CKind))
22995 break;
22996
22997 // OpenMP 4.5 [2.10.5, target update Construct]
22998 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22999 // If the type of a list item is a reference to a type T then the type will
23000 // be considered to be T for all purposes of this clause.
23001 auto I = llvm::find_if(
23002 CurComponents,
23004 return MC.getAssociatedDeclaration();
23005 });
23006 assert(I != CurComponents.end() && "Null decl on map clause.");
23007 (void)I;
23008 QualType Type;
23009 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
23010 auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens());
23011 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
23012 if (ASE) {
23013 Type = ASE->getType().getNonReferenceType();
23014 } else if (OASE) {
23015 QualType BaseType =
23017 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
23018 Type = ATy->getElementType();
23019 else
23020 Type = BaseType->getPointeeType();
23021 Type = Type.getNonReferenceType();
23022 } else if (OAShE) {
23023 Type = OAShE->getBase()->getType()->getPointeeType();
23024 } else {
23025 Type = VE->getType();
23026 }
23027
23028 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
23029 // A list item in a to or from clause must have a mappable type.
23030 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
23031 // A list item must have a mappable type.
23032 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
23033 DSAS, Type, /*FullCheck=*/true))
23034 continue;
23035
23036 if (CKind == OMPC_map) {
23037 // target enter data
23038 // OpenMP [2.10.2, Restrictions, p. 99]
23039 // A map-type must be specified in all map clauses and must be either
23040 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
23041 // no map type is present.
23042 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
23043 if (DKind == OMPD_target_enter_data &&
23044 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
23045 SemaRef.getLangOpts().OpenMP >= 52)) {
23046 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23047 << (IsMapTypeImplicit ? 1 : 0)
23048 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
23049 << getOpenMPDirectiveName(DKind, OMPVersion);
23050 continue;
23051 }
23052
23053 // target exit_data
23054 // OpenMP [2.10.3, Restrictions, p. 102]
23055 // A map-type must be specified in all map clauses and must be either
23056 // from, release, or delete. Starting with OpenMP 5.2 the default map
23057 // type is `from` if no map type is present.
23058 if (DKind == OMPD_target_exit_data &&
23059 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
23060 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
23061 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23062 << (IsMapTypeImplicit ? 1 : 0)
23063 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
23064 << getOpenMPDirectiveName(DKind, OMPVersion);
23065 continue;
23066 }
23067
23068 // The 'ompx_hold' modifier is specifically intended to be used on a
23069 // 'target' or 'target data' directive to prevent data from being unmapped
23070 // during the associated statement. It is not permitted on a 'target
23071 // enter data' or 'target exit data' directive, which have no associated
23072 // statement.
23073 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
23074 HasHoldModifier) {
23075 SemaRef.Diag(StartLoc,
23076 diag::err_omp_invalid_map_type_modifier_for_directive)
23078 OMPC_MAP_MODIFIER_ompx_hold)
23079 << getOpenMPDirectiveName(DKind, OMPVersion);
23080 continue;
23081 }
23082
23083 // target, target data
23084 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
23085 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
23086 // A map-type in a map clause must be to, from, tofrom or alloc
23087 if ((DKind == OMPD_target_data ||
23089 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
23090 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
23091 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23092 << (IsMapTypeImplicit ? 1 : 0)
23093 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
23094 << getOpenMPDirectiveName(DKind, OMPVersion);
23095 continue;
23096 }
23097
23098 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
23099 // A list item cannot appear in both a map clause and a data-sharing
23100 // attribute clause on the same construct
23101 //
23102 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
23103 // A list item cannot appear in both a map clause and a data-sharing
23104 // attribute clause on the same construct unless the construct is a
23105 // combined construct.
23106 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
23108 DKind == OMPD_target)) {
23109 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
23110 if (isOpenMPPrivate(DVar.CKind)) {
23111 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23112 << getOpenMPClauseNameForDiag(DVar.CKind)
23113 << getOpenMPClauseNameForDiag(OMPC_map)
23114 << getOpenMPDirectiveName(DSAS->getCurrentDirective(),
23115 OMPVersion);
23116 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
23117 continue;
23118 }
23119 }
23120 }
23121
23122 // Try to find the associated user-defined mapper.
23124 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23125 Type.getCanonicalType(), UnresolvedMapper);
23126 if (ER.isInvalid())
23127 continue;
23128
23129 // If no user-defined mapper is found, we need to create an implicit one for
23130 // arrays/array-sections on structs that have members that have
23131 // user-defined mappers. This is needed to ensure that the mapper for the
23132 // member is invoked when mapping each element of the array/array-section.
23133 if (!ER.get()) {
23134 QualType BaseType;
23135
23137 BaseType = VE->getType().getCanonicalType();
23138 if (BaseType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
23139 const auto *OASE = cast<ArraySectionExpr>(VE->IgnoreParenImpCasts());
23140 QualType BType =
23142 QualType ElemType;
23143 if (const auto *ATy = BType->getAsArrayTypeUnsafe())
23144 ElemType = ATy->getElementType();
23145 else
23146 ElemType = BType->getPointeeType();
23147 BaseType = ElemType.getCanonicalType();
23148 }
23149 } else if (VE->getType()->isArrayType()) {
23150 const ArrayType *AT = VE->getType()->getAsArrayTypeUnsafe();
23151 const QualType ElemType = AT->getElementType();
23152 BaseType = ElemType.getCanonicalType();
23153 }
23154
23155 if (!BaseType.isNull() && BaseType->getAsRecordDecl() &&
23156 isImplicitMapperNeeded(SemaRef, DSAS, BaseType, VE)) {
23157 ER = buildImplicitMapper(SemaRef, BaseType, DSAS);
23158 }
23159 }
23160 MVLI.UDMapperList.push_back(ER.get());
23161
23162 // Save the current expression.
23163 MVLI.ProcessedVarList.push_back(RE);
23164
23165 // Store the components in the stack so that they can be used to check
23166 // against other clauses later on.
23167 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
23168 /*WhereFoundClauseKind=*/OMPC_map);
23169
23170 // Save the components and declaration to create the clause. For purposes of
23171 // the clause creation, any component list that has base 'this' uses
23172 // null as base declaration.
23173 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23174 MVLI.VarComponents.back().append(CurComponents.begin(),
23175 CurComponents.end());
23176 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
23177 : CurDeclaration);
23178 }
23179}
23180
23182 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
23183 ArrayRef<SourceLocation> MapTypeModifiersLoc,
23184 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23185 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
23186 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23187 const OMPVarListLocTy &Locs, bool NoDiagnose,
23188 ArrayRef<Expr *> UnresolvedMappers) {
23189 OpenMPMapModifierKind Modifiers[] = {
23195
23196 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
23197 BuiltinType::OMPIterator))
23198 Diag(IteratorModifier->getExprLoc(),
23199 diag::err_omp_map_modifier_not_iterator);
23200
23201 // Process map-type-modifiers, flag errors for duplicate modifiers.
23202 unsigned Count = 0;
23203 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
23204 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
23205 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
23206 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
23207 continue;
23208 }
23209 assert(Count < NumberOfOMPMapClauseModifiers &&
23210 "Modifiers exceed the allowed number of map type modifiers");
23211 Modifiers[Count] = MapTypeModifiers[I];
23212 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
23213 ++Count;
23214 }
23215
23216 MappableVarListInfo MVLI(VarList);
23218 MapperIdScopeSpec, MapperId, UnresolvedMappers,
23219 MapType, Modifiers, IsMapTypeImplicit,
23220 NoDiagnose);
23221
23222 // We need to produce a map clause even if we don't have variables so that
23223 // other diagnostics related with non-existing map clauses are accurate.
23224 return OMPMapClause::Create(
23225 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23226 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
23227 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
23228 MapperId, MapType, IsMapTypeImplicit, MapLoc);
23229}
23230
23233 assert(ParsedType.isUsable());
23234
23235 QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get());
23236 if (ReductionType.isNull())
23237 return QualType();
23238
23239 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
23240 // A type name in a declare reduction directive cannot be a function type, an
23241 // array type, a reference type, or a type qualified with const, volatile or
23242 // restrict.
23243 if (ReductionType.hasQualifiers()) {
23244 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
23245 return QualType();
23246 }
23247
23248 if (ReductionType->isFunctionType()) {
23249 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
23250 return QualType();
23251 }
23252 if (ReductionType->isReferenceType()) {
23253 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
23254 return QualType();
23255 }
23256 if (ReductionType->isArrayType()) {
23257 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
23258 return QualType();
23259 }
23260 return ReductionType;
23261}
23262
23265 Scope *S, DeclContext *DC, DeclarationName Name,
23266 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
23267 AccessSpecifier AS, Decl *PrevDeclInScope) {
23269 Decls.reserve(ReductionTypes.size());
23270
23271 LookupResult Lookup(SemaRef, Name, SourceLocation(),
23273 SemaRef.forRedeclarationInCurContext());
23274 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
23275 // A reduction-identifier may not be re-declared in the current scope for the
23276 // same type or for a type that is compatible according to the base language
23277 // rules.
23278 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
23279 OMPDeclareReductionDecl *PrevDRD = nullptr;
23280 bool InCompoundScope = true;
23281 if (S != nullptr) {
23282 // Find previous declaration with the same name not referenced in other
23283 // declarations.
23284 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
23285 InCompoundScope =
23286 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
23287 SemaRef.LookupName(Lookup, S);
23288 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
23289 /*AllowInlineNamespace=*/false);
23290 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
23291 LookupResult::Filter Filter = Lookup.makeFilter();
23292 while (Filter.hasNext()) {
23293 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
23294 if (InCompoundScope) {
23295 UsedAsPrevious.try_emplace(PrevDecl, false);
23296 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
23297 UsedAsPrevious[D] = true;
23298 }
23299 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
23300 PrevDecl->getLocation();
23301 }
23302 Filter.done();
23303 if (InCompoundScope) {
23304 for (const auto &PrevData : UsedAsPrevious) {
23305 if (!PrevData.second) {
23306 PrevDRD = PrevData.first;
23307 break;
23308 }
23309 }
23310 }
23311 } else if (PrevDeclInScope != nullptr) {
23312 auto *PrevDRDInScope = PrevDRD =
23313 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
23314 do {
23315 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
23316 PrevDRDInScope->getLocation();
23317 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
23318 } while (PrevDRDInScope != nullptr);
23319 }
23320 for (const auto &TyData : ReductionTypes) {
23321 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
23322 bool Invalid = false;
23323 if (I != PreviousRedeclTypes.end()) {
23324 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
23325 << TyData.first;
23326 Diag(I->second, diag::note_previous_definition);
23327 Invalid = true;
23328 }
23329 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
23331 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
23332 DC->addDecl(DRD);
23333 DRD->setAccess(AS);
23334 Decls.push_back(DRD);
23335 if (Invalid)
23336 DRD->setInvalidDecl();
23337 else
23338 PrevDRD = DRD;
23339 }
23340
23341 return DeclGroupPtrTy::make(
23342 DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size()));
23343}
23344
23346 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23347
23348 // Enter new function scope.
23349 SemaRef.PushFunctionScope();
23350 SemaRef.setFunctionHasBranchProtectedScope();
23351 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
23352
23353 if (S != nullptr)
23354 SemaRef.PushDeclContext(S, DRD);
23355 else
23356 SemaRef.CurContext = DRD;
23357
23358 SemaRef.PushExpressionEvaluationContext(
23360
23361 QualType ReductionType = DRD->getType();
23362 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
23363 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
23364 // uses semantics of argument handles by value, but it should be passed by
23365 // reference. C lang does not support references, so pass all parameters as
23366 // pointers.
23367 // Create 'T omp_in;' variable.
23368 VarDecl *OmpInParm =
23369 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in");
23370 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
23371 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
23372 // uses semantics of argument handles by value, but it should be passed by
23373 // reference. C lang does not support references, so pass all parameters as
23374 // pointers.
23375 // Create 'T omp_out;' variable.
23376 VarDecl *OmpOutParm =
23377 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out");
23378 if (S != nullptr) {
23379 SemaRef.PushOnScopeChains(OmpInParm, S);
23380 SemaRef.PushOnScopeChains(OmpOutParm, S);
23381 } else {
23382 DRD->addDecl(OmpInParm);
23383 DRD->addDecl(OmpOutParm);
23384 }
23385 Expr *InE =
23386 ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation());
23387 Expr *OutE =
23388 ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation());
23389 DRD->setCombinerData(InE, OutE);
23390}
23391
23393 Expr *Combiner) {
23394 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23395 SemaRef.DiscardCleanupsInEvaluationContext();
23396 SemaRef.PopExpressionEvaluationContext();
23397
23398 SemaRef.PopDeclContext();
23399 SemaRef.PopFunctionScopeInfo();
23400
23401 if (Combiner != nullptr)
23402 DRD->setCombiner(Combiner);
23403 else
23404 DRD->setInvalidDecl();
23405}
23406
23408 Decl *D) {
23409 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23410
23411 // Enter new function scope.
23412 SemaRef.PushFunctionScope();
23413 SemaRef.setFunctionHasBranchProtectedScope();
23414
23415 if (S != nullptr)
23416 SemaRef.PushDeclContext(S, DRD);
23417 else
23418 SemaRef.CurContext = DRD;
23419
23420 SemaRef.PushExpressionEvaluationContext(
23422
23423 QualType ReductionType = DRD->getType();
23424 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
23425 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
23426 // uses semantics of argument handles by value, but it should be passed by
23427 // reference. C lang does not support references, so pass all parameters as
23428 // pointers.
23429 // Create 'T omp_priv;' variable.
23430 VarDecl *OmpPrivParm =
23431 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv");
23432 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
23433 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
23434 // uses semantics of argument handles by value, but it should be passed by
23435 // reference. C lang does not support references, so pass all parameters as
23436 // pointers.
23437 // Create 'T omp_orig;' variable.
23438 VarDecl *OmpOrigParm =
23439 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig");
23440 if (S != nullptr) {
23441 SemaRef.PushOnScopeChains(OmpPrivParm, S);
23442 SemaRef.PushOnScopeChains(OmpOrigParm, S);
23443 } else {
23444 DRD->addDecl(OmpPrivParm);
23445 DRD->addDecl(OmpOrigParm);
23446 }
23447 Expr *OrigE =
23448 ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation());
23449 Expr *PrivE =
23450 ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation());
23451 DRD->setInitializerData(OrigE, PrivE);
23452 return OmpPrivParm;
23453}
23454
23456 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
23457 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23458 SemaRef.DiscardCleanupsInEvaluationContext();
23459 SemaRef.PopExpressionEvaluationContext();
23460
23461 SemaRef.PopDeclContext();
23462 SemaRef.PopFunctionScopeInfo();
23463
23464 if (Initializer != nullptr) {
23465 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
23466 } else if (OmpPrivParm->hasInit()) {
23467 DRD->setInitializer(OmpPrivParm->getInit(),
23468 OmpPrivParm->isDirectInit()
23471 } else {
23472 DRD->setInvalidDecl();
23473 }
23474}
23475
23477 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
23478 for (Decl *D : DeclReductions.get()) {
23479 if (IsValid) {
23480 if (S)
23481 SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
23482 /*AddToContext=*/false);
23483 } else {
23484 D->setInvalidDecl();
23485 }
23486 }
23487 return DeclReductions;
23488}
23489
23491 Declarator &D) {
23492 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
23493 QualType T = TInfo->getType();
23494 if (D.isInvalidType())
23495 return true;
23496
23497 if (getLangOpts().CPlusPlus) {
23498 // Check that there are no default arguments (C++ only).
23499 SemaRef.CheckExtraCXXDefaultArguments(D);
23500 }
23501
23502 return SemaRef.CreateParsedType(T, TInfo);
23503}
23504
23507 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
23508
23509 QualType MapperType = SemaRef.GetTypeFromParser(ParsedType.get());
23510 assert(!MapperType.isNull() && "Expect valid mapper type");
23511
23512 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
23513 // The type must be of struct, union or class type in C and C++
23514 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
23515 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
23516 return QualType();
23517 }
23518 return MapperType;
23519}
23520
23522 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
23524 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
23525 LookupResult Lookup(SemaRef, Name, SourceLocation(),
23527 SemaRef.forRedeclarationInCurContext());
23528 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
23529 // A mapper-identifier may not be redeclared in the current scope for the
23530 // same type or for a type that is compatible according to the base language
23531 // rules.
23532 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
23533 OMPDeclareMapperDecl *PrevDMD = nullptr;
23534 bool InCompoundScope = true;
23535 if (S != nullptr) {
23536 // Find previous declaration with the same name not referenced in other
23537 // declarations.
23538 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
23539 InCompoundScope =
23540 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
23541 SemaRef.LookupName(Lookup, S);
23542 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
23543 /*AllowInlineNamespace=*/false);
23544 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
23545 LookupResult::Filter Filter = Lookup.makeFilter();
23546 while (Filter.hasNext()) {
23547 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
23548 if (InCompoundScope) {
23549 UsedAsPrevious.try_emplace(PrevDecl, false);
23550 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
23551 UsedAsPrevious[D] = true;
23552 }
23553 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
23554 PrevDecl->getLocation();
23555 }
23556 Filter.done();
23557 if (InCompoundScope) {
23558 for (const auto &PrevData : UsedAsPrevious) {
23559 if (!PrevData.second) {
23560 PrevDMD = PrevData.first;
23561 break;
23562 }
23563 }
23564 }
23565 } else if (PrevDeclInScope) {
23566 auto *PrevDMDInScope = PrevDMD =
23567 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
23568 do {
23569 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
23570 PrevDMDInScope->getLocation();
23571 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
23572 } while (PrevDMDInScope != nullptr);
23573 }
23574 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
23575 bool Invalid = false;
23576 if (I != PreviousRedeclTypes.end()) {
23577 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
23578 << MapperType << Name;
23579 Diag(I->second, diag::note_previous_definition);
23580 Invalid = true;
23581 }
23582 // Build expressions for implicit maps of data members with 'default'
23583 // mappers.
23584 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
23585 if (getLangOpts().OpenMP >= 50)
23587 ClausesWithImplicit);
23588 auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name,
23589 MapperType, VN, ClausesWithImplicit,
23590 PrevDMD);
23591 if (S)
23592 SemaRef.PushOnScopeChains(DMD, S);
23593 else
23594 DC->addDecl(DMD);
23595 DMD->setAccess(AS);
23596 if (Invalid)
23597 DMD->setInvalidDecl();
23598
23599 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
23600 VD->setDeclContext(DMD);
23601 VD->setLexicalDeclContext(DMD);
23602 DMD->addDecl(VD);
23603 DMD->setMapperVarRef(MapperVarRef);
23604
23606}
23607
23609 Scope *S, QualType MapperType, SourceLocation StartLoc,
23610 DeclarationName VN) {
23611 TypeSourceInfo *TInfo =
23612 getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc);
23613 auto *VD = VarDecl::Create(
23614 getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc,
23615 StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None);
23616 if (S)
23617 SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false);
23618 Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc);
23619 DSAStack->addDeclareMapperVarRef(E);
23620 return E;
23621}
23622
23624 bool IsGlobalVar =
23626 if (DSAStack->getDeclareMapperVarRef()) {
23627 if (IsGlobalVar)
23628 SemaRef.Consumer.HandleTopLevelDecl(DeclGroupRef(VD));
23629 DSAStack->addIteratorVarDecl(VD);
23630 } else {
23631 // Currently, only declare mapper handles global-scope iterator vars.
23632 assert(!IsGlobalVar && "Only declare mapper handles TU-scope iterators.");
23633 }
23634}
23635
23637 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
23638 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
23639 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
23640 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
23641 return true;
23643 return true;
23644 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
23645 return true;
23646 return false;
23647 }
23648 return true;
23649}
23650
23652 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
23653 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
23654}
23655
23657 SourceLocation StartLoc,
23658 SourceLocation LParenLoc,
23659 SourceLocation EndLoc) {
23660 if (VarList.empty())
23661 return nullptr;
23662
23663 for (Expr *ValExpr : VarList) {
23664 // OpenMP [teams Constrcut, Restrictions]
23665 // The num_teams expression must evaluate to a positive integer value.
23666 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams,
23667 /*StrictlyPositive=*/true))
23668 return nullptr;
23669 }
23670
23671 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23673 DKind, OMPC_num_teams, getLangOpts().OpenMP);
23674 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
23675 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
23676 LParenLoc, EndLoc, VarList,
23677 /*PreInit=*/nullptr);
23678
23679 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23681 for (Expr *ValExpr : VarList) {
23682 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23683 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23684 Vars.push_back(ValExpr);
23685 }
23686
23687 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
23688 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
23689 LParenLoc, EndLoc, Vars, PreInit);
23690}
23691
23693 SourceLocation StartLoc,
23694 SourceLocation LParenLoc,
23695 SourceLocation EndLoc) {
23696 if (VarList.empty())
23697 return nullptr;
23698
23699 for (Expr *ValExpr : VarList) {
23700 // OpenMP [teams Constrcut, Restrictions]
23701 // The thread_limit expression must evaluate to a positive integer value.
23702 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit,
23703 /*StrictlyPositive=*/true))
23704 return nullptr;
23705 }
23706
23707 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23709 DKind, OMPC_thread_limit, getLangOpts().OpenMP);
23710 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
23711 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion,
23712 StartLoc, LParenLoc, EndLoc, VarList,
23713 /*PreInit=*/nullptr);
23714
23715 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23717 for (Expr *ValExpr : VarList) {
23718 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23719 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23720 Vars.push_back(ValExpr);
23721 }
23722
23723 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
23724 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion, StartLoc,
23725 LParenLoc, EndLoc, Vars, PreInit);
23726}
23727
23729 SourceLocation StartLoc,
23730 SourceLocation LParenLoc,
23731 SourceLocation EndLoc) {
23732 Expr *ValExpr = Priority;
23733 Stmt *HelperValStmt = nullptr;
23734 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23735
23736 // OpenMP [2.9.1, task Constrcut]
23737 // The priority-value is a non-negative numerical scalar expression.
23739 ValExpr, SemaRef, OMPC_priority,
23740 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
23741 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23742 return nullptr;
23743
23744 return new (getASTContext()) OMPPriorityClause(
23745 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23746}
23747
23749 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
23750 SourceLocation StartLoc, SourceLocation LParenLoc,
23751 SourceLocation ModifierLoc, SourceLocation EndLoc) {
23752 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
23753 "Unexpected grainsize modifier in OpenMP < 51.");
23754
23755 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
23756 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
23758 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23759 << Values << getOpenMPClauseNameForDiag(OMPC_grainsize);
23760 return nullptr;
23761 }
23762
23763 Expr *ValExpr = Grainsize;
23764 Stmt *HelperValStmt = nullptr;
23765 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23766
23767 // OpenMP [2.9.2, taskloop Constrcut]
23768 // The parameter of the grainsize clause must be a positive integer
23769 // expression.
23770 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize,
23771 /*StrictlyPositive=*/true,
23772 /*BuildCapture=*/true,
23773 DSAStack->getCurrentDirective(),
23774 &CaptureRegion, &HelperValStmt))
23775 return nullptr;
23776
23777 return new (getASTContext())
23778 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
23779 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23780}
23781
23783 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
23784 SourceLocation StartLoc, SourceLocation LParenLoc,
23785 SourceLocation ModifierLoc, SourceLocation EndLoc) {
23786 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
23787 "Unexpected num_tasks modifier in OpenMP < 51.");
23788
23789 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
23790 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
23792 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23793 << Values << getOpenMPClauseNameForDiag(OMPC_num_tasks);
23794 return nullptr;
23795 }
23796
23797 Expr *ValExpr = NumTasks;
23798 Stmt *HelperValStmt = nullptr;
23799 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23800
23801 // OpenMP [2.9.2, taskloop Constrcut]
23802 // The parameter of the num_tasks clause must be a positive integer
23803 // expression.
23805 ValExpr, SemaRef, OMPC_num_tasks,
23806 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
23807 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23808 return nullptr;
23809
23810 return new (getASTContext())
23811 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
23812 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23813}
23814
23816 SourceLocation StartLoc,
23817 SourceLocation LParenLoc,
23818 SourceLocation EndLoc) {
23819 // OpenMP [2.13.2, critical construct, Description]
23820 // ... where hint-expression is an integer constant expression that evaluates
23821 // to a valid lock hint.
23822 ExprResult HintExpr =
23823 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
23824 if (HintExpr.isInvalid())
23825 return nullptr;
23826 return new (getASTContext())
23827 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
23828}
23829
23830/// Tries to find omp_event_handle_t type.
23832 DSAStackTy *Stack) {
23833 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
23834 if (!OMPEventHandleT.isNull())
23835 return true;
23836 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
23837 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
23838 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23839 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
23840 return false;
23841 }
23842 Stack->setOMPEventHandleT(PT.get());
23843 return true;
23844}
23845
23847 SourceLocation StartLoc,
23848 SourceLocation LParenLoc,
23849 SourceLocation EndLoc) {
23850 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
23851 !Evt->isInstantiationDependent() &&
23854 return nullptr;
23855 // OpenMP 5.0, 2.10.1 task Construct.
23856 // event-handle is a variable of the omp_event_handle_t type.
23857 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
23858 if (!Ref) {
23859 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23860 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
23861 return nullptr;
23862 }
23863 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
23864 if (!VD) {
23865 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23866 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
23867 return nullptr;
23868 }
23869 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
23870 VD->getType()) ||
23871 VD->getType().isConstant(getASTContext())) {
23872 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23873 << "omp_event_handle_t" << 1 << VD->getType()
23874 << Evt->getSourceRange();
23875 return nullptr;
23876 }
23877 // OpenMP 5.0, 2.10.1 task Construct
23878 // [detach clause]... The event-handle will be considered as if it was
23879 // specified on a firstprivate clause.
23880 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
23881 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
23882 DVar.RefExpr) {
23883 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
23884 << getOpenMPClauseNameForDiag(DVar.CKind)
23885 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
23887 return nullptr;
23888 }
23889 }
23890
23891 return new (getASTContext())
23892 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
23893}
23894
23896 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
23897 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
23898 SourceLocation EndLoc) {
23899 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
23900 std::string Values;
23901 Values += "'";
23902 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
23903 Values += "'";
23904 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23905 << Values << getOpenMPClauseNameForDiag(OMPC_dist_schedule);
23906 return nullptr;
23907 }
23908 Expr *ValExpr = ChunkSize;
23909 Stmt *HelperValStmt = nullptr;
23910 if (ChunkSize) {
23911 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
23912 !ChunkSize->isInstantiationDependent() &&
23913 !ChunkSize->containsUnexpandedParameterPack()) {
23914 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
23915 ExprResult Val =
23916 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
23917 if (Val.isInvalid())
23918 return nullptr;
23919
23920 ValExpr = Val.get();
23921
23922 // OpenMP [2.7.1, Restrictions]
23923 // chunk_size must be a loop invariant integer expression with a positive
23924 // value.
23925 if (std::optional<llvm::APSInt> Result =
23927 if (Result->isSigned() && !Result->isStrictlyPositive()) {
23928 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
23929 << "dist_schedule" << /*strictly positive*/ 1
23930 << ChunkSize->getSourceRange();
23931 return nullptr;
23932 }
23934 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
23935 getLangOpts().OpenMP) != OMPD_unknown &&
23936 !SemaRef.CurContext->isDependentContext()) {
23937 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23938 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23939 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23940 HelperValStmt = buildPreInits(getASTContext(), Captures);
23941 }
23942 }
23943 }
23944
23945 return new (getASTContext())
23946 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
23947 Kind, ValExpr, HelperValStmt);
23948}
23949
23952 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
23953 SourceLocation KindLoc, SourceLocation EndLoc) {
23954 if (getLangOpts().OpenMP < 50) {
23955 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
23956 Kind != OMPC_DEFAULTMAP_scalar) {
23957 std::string Value;
23958 SourceLocation Loc;
23959 Value += "'";
23960 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
23961 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
23962 OMPC_DEFAULTMAP_MODIFIER_tofrom);
23963 Loc = MLoc;
23964 } else {
23965 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
23966 OMPC_DEFAULTMAP_scalar);
23967 Loc = KindLoc;
23968 }
23969 Value += "'";
23970 Diag(Loc, diag::err_omp_unexpected_clause_value)
23971 << Value << getOpenMPClauseNameForDiag(OMPC_defaultmap);
23972 return nullptr;
23973 }
23974 } else {
23975 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
23976 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
23977 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
23978 if (!isDefaultmapKind || !isDefaultmapModifier) {
23979 StringRef KindValue = getLangOpts().OpenMP < 52
23980 ? "'scalar', 'aggregate', 'pointer'"
23981 : "'scalar', 'aggregate', 'pointer', 'all'";
23982 if (getLangOpts().OpenMP == 50) {
23983 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
23984 "'firstprivate', 'none', 'default'";
23985 if (!isDefaultmapKind && isDefaultmapModifier) {
23986 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23987 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
23988 } else if (isDefaultmapKind && !isDefaultmapModifier) {
23989 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23990 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
23991 } else {
23992 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23993 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
23994 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23995 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
23996 }
23997 } else {
23998 StringRef ModifierValue =
23999 getLangOpts().OpenMP < 60
24000 ? "'alloc', 'from', 'to', 'tofrom', "
24001 "'firstprivate', 'none', 'default', 'present'"
24002 : "'storage', 'from', 'to', 'tofrom', "
24003 "'firstprivate', 'private', 'none', 'default', 'present'";
24004 if (!isDefaultmapKind && isDefaultmapModifier) {
24005 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24006 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24007 } else if (isDefaultmapKind && !isDefaultmapModifier) {
24008 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24009 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24010 } else {
24011 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24012 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24013 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24014 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24015 }
24016 }
24017 return nullptr;
24018 }
24019
24020 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
24021 // At most one defaultmap clause for each category can appear on the
24022 // directive.
24023 if (DSAStack->checkDefaultmapCategory(Kind)) {
24024 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
24025 return nullptr;
24026 }
24027 }
24028 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
24029 // Variable category is not specified - mark all categories.
24030 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
24031 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
24032 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
24033 } else {
24034 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
24035 }
24036
24037 return new (getASTContext())
24038 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
24039}
24040
24043 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
24044 if (!CurLexicalContext->isFileContext() &&
24045 !CurLexicalContext->isExternCContext() &&
24046 !CurLexicalContext->isExternCXXContext() &&
24047 !isa<CXXRecordDecl>(CurLexicalContext) &&
24048 !isa<ClassTemplateDecl>(CurLexicalContext) &&
24049 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
24050 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
24051 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
24052 return false;
24053 }
24054
24055 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
24056 if (getLangOpts().HIP)
24057 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
24058
24059 DeclareTargetNesting.push_back(DTCI);
24060 return true;
24061}
24062
24065 assert(!DeclareTargetNesting.empty() &&
24066 "check isInOpenMPDeclareTargetContext() first!");
24067 return DeclareTargetNesting.pop_back_val();
24068}
24069
24072 for (auto &It : DTCI.ExplicitlyMapped)
24073 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
24074}
24075
24077 if (DeclareTargetNesting.empty())
24078 return;
24079 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
24080 unsigned OMPVersion = getLangOpts().OpenMP;
24081 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
24082 << getOpenMPDirectiveName(DTCI.Kind, OMPVersion);
24083}
24084
24086 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
24088 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
24089 /*ObjectType=*/QualType(),
24090 /*AllowBuiltinCreation=*/true);
24091
24092 if (Lookup.isAmbiguous())
24093 return nullptr;
24094 Lookup.suppressDiagnostics();
24095
24096 if (!Lookup.isSingleResult()) {
24097 VarOrFuncDeclFilterCCC CCC(SemaRef);
24098 if (TypoCorrection Corrected =
24099 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
24101 SemaRef.diagnoseTypo(Corrected,
24102 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
24103 << Id.getName());
24104 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
24105 return nullptr;
24106 }
24107
24108 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
24109 return nullptr;
24110 }
24111
24112 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
24113 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
24115 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
24116 return nullptr;
24117 }
24118 return ND;
24119}
24120
24122 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
24124 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
24126 "Expected variable, function or function template.");
24127
24128 if (auto *VD = dyn_cast<VarDecl>(ND)) {
24129 // Only global variables can be marked as declare target.
24130 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24131 !VD->isStaticDataMember()) {
24132 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
24133 << VD->getNameAsString();
24134 return;
24135 }
24136 }
24137 // Diagnose marking after use as it may lead to incorrect diagnosis and
24138 // codegen.
24139 if (getLangOpts().OpenMP >= 50 &&
24140 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
24141 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
24142
24143 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
24144 if (getLangOpts().HIP)
24145 Diag(Loc, diag::warn_hip_omp_target_directives);
24146
24147 // Explicit declare target lists have precedence.
24148 const unsigned Level = -1;
24149
24150 auto *VD = cast<ValueDecl>(ND);
24151 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24152 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24153 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
24154 (*ActiveAttr)->getLevel() == Level) {
24155 Diag(Loc, diag::err_omp_device_type_mismatch)
24156 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
24157 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
24158 (*ActiveAttr)->getDevType());
24159 return;
24160 }
24161 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
24162 (*ActiveAttr)->getLevel() == Level) {
24163 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
24164 return;
24165 }
24166
24167 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
24168 return;
24169
24170 Expr *IndirectE = nullptr;
24171 bool IsIndirect = false;
24172 if (DTCI.Indirect) {
24173 IndirectE = *DTCI.Indirect;
24174 if (!IndirectE)
24175 IsIndirect = true;
24176 }
24177 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
24178 getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level,
24179 SourceRange(Loc, Loc));
24180 ND->addAttr(A);
24181 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
24182 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
24183 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
24184 if (auto *VD = dyn_cast<VarDecl>(ND);
24185 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
24186 VD->hasGlobalStorage())
24188}
24189
24191 Sema &SemaRef, Decl *D) {
24192 if (!D || !isa<VarDecl>(D))
24193 return;
24194 auto *VD = cast<VarDecl>(D);
24195 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
24196 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
24197 if (SemaRef.LangOpts.OpenMP >= 50 &&
24198 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
24199 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
24200 VD->hasGlobalStorage()) {
24201 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
24202 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
24203 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
24204 // If a lambda declaration and definition appears between a
24205 // declare target directive and the matching end declare target
24206 // directive, all variables that are captured by the lambda
24207 // expression must also appear in a to clause.
24208 SemaRef.Diag(VD->getLocation(),
24209 diag::err_omp_lambda_capture_in_declare_target_not_to);
24210 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
24211 << VD << 0 << SR;
24212 return;
24213 }
24214 }
24215 if (MapTy)
24216 return;
24217 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
24218 SemaRef.Diag(SL, diag::note_used_here) << SR;
24219}
24220
24222 Sema &SemaRef, DSAStackTy *Stack,
24223 ValueDecl *VD) {
24224 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
24225 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
24226 /*FullCheck=*/false);
24227}
24228
24230 SourceLocation IdLoc) {
24231 if (!D || D->isInvalidDecl())
24232 return;
24233 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
24234 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
24235 if (auto *VD = dyn_cast<VarDecl>(D)) {
24236 // Only global variables can be marked as declare target.
24237 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24238 !VD->isStaticDataMember())
24239 return;
24240 // 2.10.6: threadprivate variable cannot appear in a declare target
24241 // directive.
24242 if (DSAStack->isThreadPrivate(VD)) {
24243 Diag(SL, diag::err_omp_threadprivate_in_target);
24244 reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false));
24245 return;
24246 }
24247 }
24248 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
24249 D = FTD->getTemplatedDecl();
24250 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
24251 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
24252 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
24253 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
24254 Diag(IdLoc, diag::err_omp_function_in_link_clause);
24255 Diag(FD->getLocation(), diag::note_defined_here) << FD;
24256 return;
24257 }
24258 }
24259 if (auto *VD = dyn_cast<ValueDecl>(D)) {
24260 // Problem if any with var declared with incomplete type will be reported
24261 // as normal, so no need to check it here.
24262 if ((E || !VD->getType()->isIncompleteType()) &&
24264 return;
24265 if (!E && isInOpenMPDeclareTargetContext()) {
24266 // Checking declaration inside declare target region.
24267 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
24269 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24270 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24271 unsigned Level = DeclareTargetNesting.size();
24272 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
24273 return;
24274 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
24275 Expr *IndirectE = nullptr;
24276 bool IsIndirect = false;
24277 if (DTCI.Indirect) {
24278 IndirectE = *DTCI.Indirect;
24279 if (!IndirectE)
24280 IsIndirect = true;
24281 }
24282 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
24283 getASTContext(),
24284 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
24285 : OMPDeclareTargetDeclAttr::MT_To,
24286 DTCI.DT, IndirectE, IsIndirect, Level,
24287 SourceRange(DTCI.Loc, DTCI.Loc));
24288 D->addAttr(A);
24289 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
24290 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
24291 }
24292 return;
24293 }
24294 }
24295 if (!E)
24296 return;
24298}
24299
24300/// This class visits every VarDecl that the initializer references and adds
24301/// OMPDeclareTargetDeclAttr to each of them.
24302class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
24303 SmallVector<VarDecl *> DeclVector;
24304 Attr *A;
24305
24306public:
24307 /// A StmtVisitor class function that visits all DeclRefExpr and adds
24308 /// OMPDeclareTargetDeclAttr to them.
24310 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
24311 VD->addAttr(A);
24312 DeclVector.push_back(VD);
24313 }
24314 }
24315 /// A function that iterates across each of the Expr's children.
24316 void VisitExpr(Expr *Ex) {
24317 for (auto *Child : Ex->children()) {
24318 Visit(Child);
24319 }
24320 }
24321 /// A function that keeps a record of all the Decls that are variables, has
24322 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
24323 /// each Decl one at a time and use the inherited 'visit' functions to look
24324 /// for DeclRefExpr.
24326 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
24327 DeclVector.push_back(cast<VarDecl>(TD));
24328 llvm::SmallDenseSet<Decl *> Visited;
24329 while (!DeclVector.empty()) {
24330 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
24331 if (!Visited.insert(TargetVarDecl).second)
24332 continue;
24333
24334 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
24335 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
24336 if (Expr *Ex = TargetVarDecl->getInit())
24337 Visit(Ex);
24338 }
24339 }
24340 }
24341};
24342
24343/// Adding OMPDeclareTargetDeclAttr to variables with static storage
24344/// duration that are referenced in the initializer expression list of
24345/// variables with static storage duration in declare target directive.
24347 GlobalDeclRefChecker Checker;
24348 if (isa<VarDecl>(TargetDecl))
24349 Checker.declareTargetInitializer(TargetDecl);
24350}
24351
24353 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
24354 ArrayRef<SourceLocation> MotionModifiersLoc,
24355 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
24356 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
24357 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
24361
24362 // Process motion-modifiers, flag errors for duplicate modifiers.
24363 unsigned Count = 0;
24364 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
24365 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
24366 llvm::is_contained(Modifiers, MotionModifiers[I])) {
24367 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
24368 continue;
24369 }
24370 assert(Count < NumberOfOMPMotionModifiers &&
24371 "Modifiers exceed the allowed number of motion modifiers");
24372 Modifiers[Count] = MotionModifiers[I];
24373 ModifiersLoc[Count] = MotionModifiersLoc[I];
24374 ++Count;
24375 }
24376
24377 MappableVarListInfo MVLI(VarList);
24379 MapperIdScopeSpec, MapperId, UnresolvedMappers);
24380 if (MVLI.ProcessedVarList.empty())
24381 return nullptr;
24382
24383 return OMPToClause::Create(
24384 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24385 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
24386 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
24387}
24388
24390 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
24391 ArrayRef<SourceLocation> MotionModifiersLoc,
24392 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
24393 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
24394 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
24398
24399 // Process motion-modifiers, flag errors for duplicate modifiers.
24400 unsigned Count = 0;
24401 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
24402 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
24403 llvm::is_contained(Modifiers, MotionModifiers[I])) {
24404 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
24405 continue;
24406 }
24407 assert(Count < NumberOfOMPMotionModifiers &&
24408 "Modifiers exceed the allowed number of motion modifiers");
24409 Modifiers[Count] = MotionModifiers[I];
24410 ModifiersLoc[Count] = MotionModifiersLoc[I];
24411 ++Count;
24412 }
24413
24414 MappableVarListInfo MVLI(VarList);
24415 checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
24416 MapperIdScopeSpec, MapperId, UnresolvedMappers);
24417 if (MVLI.ProcessedVarList.empty())
24418 return nullptr;
24419
24420 return OMPFromClause::Create(
24421 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24422 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
24423 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
24424}
24425
24426OMPClause *
24428 const OMPVarListLocTy &Locs) {
24429 MappableVarListInfo MVLI(VarList);
24430 SmallVector<Expr *, 8> PrivateCopies;
24432
24433 for (Expr *RefExpr : VarList) {
24434 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
24435 SourceLocation ELoc;
24436 SourceRange ERange;
24437 Expr *SimpleRefExpr = RefExpr;
24438 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24439 if (Res.second) {
24440 // It will be analyzed later.
24441 MVLI.ProcessedVarList.push_back(RefExpr);
24442 PrivateCopies.push_back(nullptr);
24443 Inits.push_back(nullptr);
24444 }
24445 ValueDecl *D = Res.first;
24446 if (!D)
24447 continue;
24448
24449 QualType Type = D->getType();
24450 Type = Type.getNonReferenceType().getUnqualifiedType();
24451
24452 auto *VD = dyn_cast<VarDecl>(D);
24453
24454 // Item should be a pointer or reference to pointer.
24455 if (!Type->isPointerType()) {
24456 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
24457 << 0 << RefExpr->getSourceRange();
24458 continue;
24459 }
24460
24461 // Build the private variable and the expression that refers to it.
24462 auto VDPrivate =
24463 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
24464 D->hasAttrs() ? &D->getAttrs() : nullptr,
24465 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
24466 if (VDPrivate->isInvalidDecl())
24467 continue;
24468
24469 SemaRef.CurContext->addDecl(VDPrivate);
24470 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
24471 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
24472
24473 // Add temporary variable to initialize the private copy of the pointer.
24474 VarDecl *VDInit =
24475 buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp");
24476 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
24477 SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
24478 SemaRef.AddInitializerToDecl(
24479 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
24480 /*DirectInit=*/false);
24481
24482 // If required, build a capture to implement the privatization initialized
24483 // with the current list item value.
24484 DeclRefExpr *Ref = nullptr;
24485 if (!VD)
24486 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
24487 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
24488 PrivateCopies.push_back(VDPrivateRefExpr);
24489 Inits.push_back(VDInitRefExpr);
24490
24491 // We need to add a data sharing attribute for this variable to make sure it
24492 // is correctly captured. A variable that shows up in a use_device_ptr has
24493 // similar properties of a first private variable.
24494 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24495
24496 // Create a mappable component for the list item. List items in this clause
24497 // only need a component.
24498 MVLI.VarBaseDeclarations.push_back(D);
24499 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24500 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
24501 /*IsNonContiguous=*/false);
24502 }
24503
24504 if (MVLI.ProcessedVarList.empty())
24505 return nullptr;
24506
24508 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
24509 MVLI.VarBaseDeclarations, MVLI.VarComponents);
24510}
24511
24512OMPClause *
24514 const OMPVarListLocTy &Locs) {
24515 MappableVarListInfo MVLI(VarList);
24516
24517 for (Expr *RefExpr : VarList) {
24518 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
24519 SourceLocation ELoc;
24520 SourceRange ERange;
24521 Expr *SimpleRefExpr = RefExpr;
24522 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24523 /*AllowArraySection=*/true,
24524 /*AllowAssumedSizeArray=*/true);
24525 if (Res.second) {
24526 // It will be analyzed later.
24527 MVLI.ProcessedVarList.push_back(RefExpr);
24528 }
24529 ValueDecl *D = Res.first;
24530 if (!D)
24531 continue;
24532 auto *VD = dyn_cast<VarDecl>(D);
24533
24534 // If required, build a capture to implement the privatization initialized
24535 // with the current list item value.
24536 DeclRefExpr *Ref = nullptr;
24537 if (!VD)
24538 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
24539 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
24540
24541 // We need to add a data sharing attribute for this variable to make sure it
24542 // is correctly captured. A variable that shows up in a use_device_addr has
24543 // similar properties of a first private variable.
24544 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24545
24546 // Create a mappable component for the list item. List items in this clause
24547 // only need a component.
24548 MVLI.VarBaseDeclarations.push_back(D);
24549 MVLI.VarComponents.emplace_back();
24550 Expr *Component = SimpleRefExpr;
24551 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
24552 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
24553 Component =
24554 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
24555 MVLI.VarComponents.back().emplace_back(Component, D,
24556 /*IsNonContiguous=*/false);
24557 }
24558
24559 if (MVLI.ProcessedVarList.empty())
24560 return nullptr;
24561
24563 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24564 MVLI.VarComponents);
24565}
24566
24567OMPClause *
24569 const OMPVarListLocTy &Locs) {
24570 MappableVarListInfo MVLI(VarList);
24571 for (Expr *RefExpr : VarList) {
24572 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
24573 SourceLocation ELoc;
24574 SourceRange ERange;
24575 Expr *SimpleRefExpr = RefExpr;
24576 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24577 if (Res.second) {
24578 // It will be analyzed later.
24579 MVLI.ProcessedVarList.push_back(RefExpr);
24580 }
24581 ValueDecl *D = Res.first;
24582 if (!D)
24583 continue;
24584
24585 QualType Type = D->getType();
24586 // item should be a pointer or array or reference to pointer or array
24587 if (!Type.getNonReferenceType()->isPointerType() &&
24588 !Type.getNonReferenceType()->isArrayType()) {
24589 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
24590 << 0 << RefExpr->getSourceRange();
24591 continue;
24592 }
24593
24594 // Check if the declaration in the clause does not show up in any data
24595 // sharing attribute.
24596 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
24597 if (isOpenMPPrivate(DVar.CKind)) {
24598 unsigned OMPVersion = getLangOpts().OpenMP;
24599 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24600 << getOpenMPClauseNameForDiag(DVar.CKind)
24601 << getOpenMPClauseNameForDiag(OMPC_is_device_ptr)
24602 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
24603 OMPVersion);
24605 continue;
24606 }
24607
24608 const Expr *ConflictExpr;
24609 if (DSAStack->checkMappableExprComponentListsForDecl(
24610 D, /*CurrentRegionOnly=*/true,
24611 [&ConflictExpr](
24613 OpenMPClauseKind) -> bool {
24614 ConflictExpr = R.front().getAssociatedExpression();
24615 return true;
24616 })) {
24617 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24618 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
24619 << ConflictExpr->getSourceRange();
24620 continue;
24621 }
24622
24623 // Store the components in the stack so that they can be used to check
24624 // against other clauses later on.
24626 SimpleRefExpr, D, /*IsNonContiguous=*/false);
24627 DSAStack->addMappableExpressionComponents(
24628 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
24629
24630 // Record the expression we've just processed.
24631 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
24632
24633 // Create a mappable component for the list item. List items in this clause
24634 // only need a component. We use a null declaration to signal fields in
24635 // 'this'.
24636 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
24637 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
24638 "Unexpected device pointer expression!");
24639 MVLI.VarBaseDeclarations.push_back(
24640 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
24641 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24642 MVLI.VarComponents.back().push_back(MC);
24643 }
24644
24645 if (MVLI.ProcessedVarList.empty())
24646 return nullptr;
24647
24649 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24650 MVLI.VarComponents);
24651}
24652
24653OMPClause *
24655 const OMPVarListLocTy &Locs) {
24656 MappableVarListInfo MVLI(VarList);
24657 for (Expr *RefExpr : VarList) {
24658 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
24659 SourceLocation ELoc;
24660 SourceRange ERange;
24661 Expr *SimpleRefExpr = RefExpr;
24662 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24663 /*AllowArraySection=*/true);
24664 if (Res.second) {
24665 // It will be analyzed later.
24666 MVLI.ProcessedVarList.push_back(RefExpr);
24667 }
24668 ValueDecl *D = Res.first;
24669 if (!D)
24670 continue;
24671
24672 // Check if the declaration in the clause does not show up in any data
24673 // sharing attribute.
24674 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
24675 if (isOpenMPPrivate(DVar.CKind)) {
24676 unsigned OMPVersion = getLangOpts().OpenMP;
24677 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24678 << getOpenMPClauseNameForDiag(DVar.CKind)
24679 << getOpenMPClauseNameForDiag(OMPC_has_device_addr)
24680 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
24681 OMPVersion);
24683 continue;
24684 }
24685
24686 const Expr *ConflictExpr;
24687 if (DSAStack->checkMappableExprComponentListsForDecl(
24688 D, /*CurrentRegionOnly=*/true,
24689 [&ConflictExpr](
24691 OpenMPClauseKind) -> bool {
24692 ConflictExpr = R.front().getAssociatedExpression();
24693 return true;
24694 })) {
24695 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24696 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
24697 << ConflictExpr->getSourceRange();
24698 continue;
24699 }
24700
24701 // Store the components in the stack so that they can be used to check
24702 // against other clauses later on.
24703 Expr *Component = SimpleRefExpr;
24704 auto *VD = dyn_cast<VarDecl>(D);
24705 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
24706 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
24707 Component =
24708 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
24710 Component, D, /*IsNonContiguous=*/false);
24711 DSAStack->addMappableExpressionComponents(
24712 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
24713
24714 // Record the expression we've just processed.
24715 if (!VD && !SemaRef.CurContext->isDependentContext()) {
24716 DeclRefExpr *Ref =
24717 buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
24718 assert(Ref && "has_device_addr capture failed");
24719 MVLI.ProcessedVarList.push_back(Ref);
24720 } else
24721 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
24722
24723 // Create a mappable component for the list item. List items in this clause
24724 // only need a component. We use a null declaration to signal fields in
24725 // 'this'.
24726 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
24727 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
24728 "Unexpected device pointer expression!");
24729 MVLI.VarBaseDeclarations.push_back(
24730 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
24731 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24732 MVLI.VarComponents.back().push_back(MC);
24733 }
24734
24735 if (MVLI.ProcessedVarList.empty())
24736 return nullptr;
24737
24739 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24740 MVLI.VarComponents);
24741}
24742
24744 Expr *Allocator, Expr *Alignment,
24745 OpenMPAllocateClauseModifier FirstAllocateModifier,
24746 SourceLocation FirstAllocateModifierLoc,
24747 OpenMPAllocateClauseModifier SecondAllocateModifier,
24748 SourceLocation SecondAllocateModifierLoc, ArrayRef<Expr *> VarList,
24749 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
24750 SourceLocation EndLoc) {
24751 if (Allocator) {
24752 // Allocator expression is dependent - skip it for now and build the
24753 // allocator when instantiated.
24754 bool AllocDependent =
24755 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
24756 Allocator->isInstantiationDependent() ||
24757 Allocator->containsUnexpandedParameterPack());
24758 if (!AllocDependent) {
24759 // OpenMP [2.11.4 allocate Clause, Description]
24760 // allocator is an expression of omp_allocator_handle_t type.
24762 return nullptr;
24763
24764 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
24765 if (AllocatorRes.isInvalid())
24766 return nullptr;
24767 AllocatorRes = SemaRef.PerformImplicitConversion(
24768 AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
24770 /*AllowExplicit=*/true);
24771 if (AllocatorRes.isInvalid())
24772 return nullptr;
24773 Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr;
24774 }
24775 } else {
24776 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
24777 // allocate clauses that appear on a target construct or on constructs in a
24778 // target region must specify an allocator expression unless a requires
24779 // directive with the dynamic_allocators clause is present in the same
24780 // compilation unit.
24781 if (getLangOpts().OpenMPIsTargetDevice &&
24782 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
24783 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
24784 }
24785 if (Alignment) {
24786 bool AlignmentDependent = Alignment->isTypeDependent() ||
24787 Alignment->isValueDependent() ||
24788 Alignment->isInstantiationDependent() ||
24790 if (!AlignmentDependent) {
24791 ExprResult AlignResult =
24792 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_allocate);
24793 Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr;
24794 }
24795 }
24796 // Analyze and build list of variables.
24798 for (Expr *RefExpr : VarList) {
24799 assert(RefExpr && "NULL expr in OpenMP allocate clause.");
24800 SourceLocation ELoc;
24801 SourceRange ERange;
24802 Expr *SimpleRefExpr = RefExpr;
24803 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24804 if (Res.second) {
24805 // It will be analyzed later.
24806 Vars.push_back(RefExpr);
24807 }
24808 ValueDecl *D = Res.first;
24809 if (!D)
24810 continue;
24811
24812 auto *VD = dyn_cast<VarDecl>(D);
24813 DeclRefExpr *Ref = nullptr;
24814 if (!VD && !SemaRef.CurContext->isDependentContext())
24815 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
24816 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
24817 ? RefExpr->IgnoreParens()
24818 : Ref);
24819 }
24820
24821 if (Vars.empty())
24822 return nullptr;
24823
24824 if (Allocator)
24825 DSAStack->addInnerAllocatorExpr(Allocator);
24826
24828 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
24829 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
24830 SecondAllocateModifierLoc, EndLoc, Vars);
24831}
24832
24834 SourceLocation StartLoc,
24835 SourceLocation LParenLoc,
24836 SourceLocation EndLoc) {
24838 for (Expr *RefExpr : VarList) {
24839 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
24840 SourceLocation ELoc;
24841 SourceRange ERange;
24842 Expr *SimpleRefExpr = RefExpr;
24843 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24844 if (Res.second)
24845 // It will be analyzed later.
24846 Vars.push_back(RefExpr);
24847 ValueDecl *D = Res.first;
24848 if (!D)
24849 continue;
24850
24851 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
24852 // A list-item cannot appear in more than one nontemporal clause.
24853 if (const Expr *PrevRef =
24854 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
24855 Diag(ELoc, diag::err_omp_used_in_clause_twice)
24856 << 0 << getOpenMPClauseNameForDiag(OMPC_nontemporal) << ERange;
24857 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
24858 << getOpenMPClauseNameForDiag(OMPC_nontemporal);
24859 continue;
24860 }
24861
24862 Vars.push_back(RefExpr);
24863 }
24864
24865 if (Vars.empty())
24866 return nullptr;
24867
24868 return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc,
24869 EndLoc, Vars);
24870}
24871
24873 Stmt *AStmt,
24874 SourceLocation StartLoc,
24875 SourceLocation EndLoc) {
24876 if (!AStmt)
24877 return StmtError();
24878
24879 SemaRef.setFunctionHasBranchProtectedScope();
24880
24881 return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
24882 AStmt);
24883}
24884
24886 SourceLocation StartLoc,
24887 SourceLocation LParenLoc,
24888 SourceLocation EndLoc) {
24890 for (Expr *RefExpr : VarList) {
24891 assert(RefExpr && "NULL expr in OpenMP inclusive clause.");
24892 SourceLocation ELoc;
24893 SourceRange ERange;
24894 Expr *SimpleRefExpr = RefExpr;
24895 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24896 /*AllowArraySection=*/true);
24897 if (Res.second)
24898 // It will be analyzed later.
24899 Vars.push_back(RefExpr);
24900 ValueDecl *D = Res.first;
24901 if (!D)
24902 continue;
24903
24904 const DSAStackTy::DSAVarData DVar =
24905 DSAStack->getTopDSA(D, /*FromParent=*/true);
24906 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
24907 // A list item that appears in the inclusive or exclusive clause must appear
24908 // in a reduction clause with the inscan modifier on the enclosing
24909 // worksharing-loop, worksharing-loop SIMD, or simd construct.
24910 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
24911 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
24912 << RefExpr->getSourceRange();
24913
24914 if (DSAStack->getParentDirective() != OMPD_unknown)
24915 DSAStack->markDeclAsUsedInScanDirective(D);
24916 Vars.push_back(RefExpr);
24917 }
24918
24919 if (Vars.empty())
24920 return nullptr;
24921
24922 return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
24923 EndLoc, Vars);
24924}
24925
24927 SourceLocation StartLoc,
24928 SourceLocation LParenLoc,
24929 SourceLocation EndLoc) {
24931 for (Expr *RefExpr : VarList) {
24932 assert(RefExpr && "NULL expr in OpenMP exclusive clause.");
24933 SourceLocation ELoc;
24934 SourceRange ERange;
24935 Expr *SimpleRefExpr = RefExpr;
24936 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24937 /*AllowArraySection=*/true);
24938 if (Res.second)
24939 // It will be analyzed later.
24940 Vars.push_back(RefExpr);
24941 ValueDecl *D = Res.first;
24942 if (!D)
24943 continue;
24944
24945 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
24946 DSAStackTy::DSAVarData DVar;
24947 if (ParentDirective != OMPD_unknown)
24948 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
24949 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
24950 // A list item that appears in the inclusive or exclusive clause must appear
24951 // in a reduction clause with the inscan modifier on the enclosing
24952 // worksharing-loop, worksharing-loop SIMD, or simd construct.
24953 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
24954 DVar.Modifier != OMPC_REDUCTION_inscan) {
24955 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
24956 << RefExpr->getSourceRange();
24957 } else {
24958 DSAStack->markDeclAsUsedInScanDirective(D);
24959 }
24960 Vars.push_back(RefExpr);
24961 }
24962
24963 if (Vars.empty())
24964 return nullptr;
24965
24966 return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
24967 EndLoc, Vars);
24968}
24969
24970/// Tries to find omp_alloctrait_t type.
24971static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
24972 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
24973 if (!OMPAlloctraitT.isNull())
24974 return true;
24975 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
24976 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
24977 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
24978 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
24979 return false;
24980 }
24981 Stack->setOMPAlloctraitT(PT.get());
24982 return true;
24983}
24984
24986 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
24988 ASTContext &Context = getASTContext();
24989 // OpenMP [2.12.5, target Construct]
24990 // allocator is an identifier of omp_allocator_handle_t type.
24991 if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack))
24992 return nullptr;
24993 // OpenMP [2.12.5, target Construct]
24994 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
24995 if (llvm::any_of(
24996 Data,
24997 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
24998 !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack))
24999 return nullptr;
25000 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
25001 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
25002 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
25003 StringRef Allocator =
25004 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
25005 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
25006 PredefinedAllocators.insert(SemaRef.LookupSingleName(
25007 SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
25008 }
25009
25011 for (const UsesAllocatorsData &D : Data) {
25012 Expr *AllocatorExpr = nullptr;
25013 // Check allocator expression.
25014 if (D.Allocator->isTypeDependent()) {
25015 AllocatorExpr = D.Allocator;
25016 } else {
25017 // Traits were specified - need to assign new allocator to the specified
25018 // allocator, so it must be an lvalue.
25019 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
25020 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
25021 bool IsPredefinedAllocator = false;
25022 if (DRE) {
25023 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
25024 getAllocatorKind(SemaRef, DSAStack, AllocatorExpr);
25025 IsPredefinedAllocator =
25026 AllocatorTy !=
25027 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
25028 }
25029 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
25030 QualType AllocatorExprType = AllocatorExpr->getType();
25031 bool IsTypeCompatible = IsPredefinedAllocator;
25032 IsTypeCompatible = IsTypeCompatible ||
25033 Context.hasSameUnqualifiedType(AllocatorExprType,
25034 OMPAllocatorHandleT);
25035 IsTypeCompatible =
25036 IsTypeCompatible ||
25037 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
25038 bool IsNonConstantLValue =
25039 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
25040 if (!DRE || !IsTypeCompatible ||
25041 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
25042 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
25043 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
25044 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
25045 continue;
25046 }
25047 // OpenMP [2.12.5, target Construct]
25048 // Predefined allocators appearing in a uses_allocators clause cannot have
25049 // traits specified.
25050 if (IsPredefinedAllocator && D.AllocatorTraits) {
25052 diag::err_omp_predefined_allocator_with_traits)
25054 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
25055 << cast<NamedDecl>(DRE->getDecl())->getName()
25056 << D.Allocator->getSourceRange();
25057 continue;
25058 }
25059 // OpenMP [2.12.5, target Construct]
25060 // Non-predefined allocators appearing in a uses_allocators clause must
25061 // have traits specified.
25062 if (getLangOpts().OpenMP < 52) {
25063 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
25065 diag::err_omp_nonpredefined_allocator_without_traits);
25066 continue;
25067 }
25068 }
25069 // No allocator traits - just convert it to rvalue.
25070 if (!D.AllocatorTraits)
25071 AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
25072 DSAStack->addUsesAllocatorsDecl(
25073 DRE->getDecl(),
25074 IsPredefinedAllocator
25075 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
25076 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
25077 }
25078 Expr *AllocatorTraitsExpr = nullptr;
25079 if (D.AllocatorTraits) {
25081 AllocatorTraitsExpr = D.AllocatorTraits;
25082 } else {
25083 // OpenMP [2.12.5, target Construct]
25084 // Arrays that contain allocator traits that appear in a uses_allocators
25085 // clause must be constant arrays, have constant values and be defined
25086 // in the same scope as the construct in which the clause appears.
25087 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
25088 // Check that traits expr is a constant array.
25089 QualType TraitTy;
25090 if (const ArrayType *Ty =
25091 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
25092 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
25093 TraitTy = ConstArrayTy->getElementType();
25094 if (TraitTy.isNull() ||
25095 !(Context.hasSameUnqualifiedType(TraitTy,
25096 DSAStack->getOMPAlloctraitT()) ||
25097 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
25098 /*CompareUnqualified=*/true))) {
25100 diag::err_omp_expected_array_alloctraits)
25101 << AllocatorTraitsExpr->getType();
25102 continue;
25103 }
25104 // Do not map by default allocator traits if it is a standalone
25105 // variable.
25106 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
25107 DSAStack->addUsesAllocatorsDecl(
25108 DRE->getDecl(),
25109 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
25110 }
25111 }
25112 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
25113 NewD.Allocator = AllocatorExpr;
25114 NewD.AllocatorTraits = AllocatorTraitsExpr;
25115 NewD.LParenLoc = D.LParenLoc;
25116 NewD.RParenLoc = D.RParenLoc;
25117 }
25118 return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc,
25119 EndLoc, NewData);
25120}
25121
25123 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
25124 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
25126 for (Expr *RefExpr : Locators) {
25127 assert(RefExpr && "NULL expr in OpenMP affinity clause.");
25128 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
25129 // It will be analyzed later.
25130 Vars.push_back(RefExpr);
25131 continue;
25132 }
25133
25134 SourceLocation ELoc = RefExpr->getExprLoc();
25135 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
25136
25137 if (!SimpleExpr->isLValue()) {
25138 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
25139 << 1 << 0 << RefExpr->getSourceRange();
25140 continue;
25141 }
25142
25143 ExprResult Res;
25144 {
25146 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
25147 }
25148 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
25150 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
25151 << 1 << 0 << RefExpr->getSourceRange();
25152 continue;
25153 }
25154 Vars.push_back(SimpleExpr);
25155 }
25156
25157 return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc,
25158 ColonLoc, EndLoc, Modifier, Vars);
25159}
25160
25162 SourceLocation KindLoc,
25163 SourceLocation StartLoc,
25164 SourceLocation LParenLoc,
25165 SourceLocation EndLoc) {
25166 if (Kind == OMPC_BIND_unknown) {
25167 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
25168 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
25169 /*Last=*/unsigned(OMPC_BIND_unknown))
25170 << getOpenMPClauseNameForDiag(OMPC_bind);
25171 return nullptr;
25172 }
25173
25174 return OMPBindClause::Create(getASTContext(), Kind, KindLoc, StartLoc,
25175 LParenLoc, EndLoc);
25176}
25177
25179 SourceLocation StartLoc,
25180 SourceLocation LParenLoc,
25181 SourceLocation EndLoc) {
25182 Expr *ValExpr = Size;
25183 Stmt *HelperValStmt = nullptr;
25184
25185 // OpenMP [2.5, Restrictions]
25186 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
25187 // value.
25188 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem,
25189 /*StrictlyPositive=*/false))
25190 return nullptr;
25191
25192 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
25194 DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP);
25195 if (CaptureRegion != OMPD_unknown &&
25196 !SemaRef.CurContext->isDependentContext()) {
25197 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
25198 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
25199 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
25200 HelperValStmt = buildPreInits(getASTContext(), Captures);
25201 }
25202
25204 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
25205}
25206
25209 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
25210 SourceLocation LParenLoc, SourceLocation EndLoc) {
25211
25212 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
25213 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
25214 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
25215 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
25216 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
25217 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_doacross);
25218 return nullptr;
25219 }
25220
25222 DSAStackTy::OperatorOffsetTy OpsOffs;
25223 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
25224 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
25225 SemaRef,
25226 DepType == OMPC_DOACROSS_source ||
25227 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
25228 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
25229 VarList, DSAStack, EndLoc);
25230 Vars = VarOffset.Vars;
25231 OpsOffs = VarOffset.OpsOffs;
25232 TotalDepCount = VarOffset.TotalDepCount;
25233 auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc,
25234 EndLoc, DepType, DepLoc, ColonLoc, Vars,
25235 TotalDepCount.getZExtValue());
25236 if (DSAStack->isParentOrderedRegion())
25237 DSAStack->addDoacrossDependClause(C, OpsOffs);
25238 return C;
25239}
25240
25242 SourceLocation StartLoc,
25243 SourceLocation LParenLoc,
25244 SourceLocation EndLoc) {
25245 return new (getASTContext())
25246 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
25247}
25248
25250 SourceLocation EndLoc) {
25251 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
25252}
25253
25255 SourceLocation LParenLoc,
25256 SourceLocation EndLoc) {
25257 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
25258}
25259
25263 switch (CK) {
25264 case OMPC_absent:
25265 return OMPAbsentClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
25266 case OMPC_contains:
25267 return OMPContainsClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
25268 default:
25269 llvm_unreachable("Unexpected OpenMP clause");
25270 }
25271}
25272
25274 SourceLocation Loc,
25275 SourceLocation RLoc) {
25276 switch (CK) {
25277 case OMPC_no_openmp:
25278 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
25279 case OMPC_no_openmp_routines:
25280 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
25281 case OMPC_no_parallelism:
25282 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
25283 case OMPC_no_openmp_constructs:
25284 return new (getASTContext()) OMPNoOpenMPConstructsClause(Loc, RLoc);
25285 default:
25286 llvm_unreachable("Unexpected OpenMP clause");
25287 }
25288}
25289
25291 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
25292 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
25293 Expr *Stride, SourceLocation RBLoc) {
25294 ASTContext &Context = getASTContext();
25295 if (Base->hasPlaceholderType() &&
25296 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
25297 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
25298 if (Result.isInvalid())
25299 return ExprError();
25300 Base = Result.get();
25301 }
25302 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
25303 ExprResult Result = SemaRef.CheckPlaceholderExpr(LowerBound);
25304 if (Result.isInvalid())
25305 return ExprError();
25306 Result = SemaRef.DefaultLvalueConversion(Result.get());
25307 if (Result.isInvalid())
25308 return ExprError();
25309 LowerBound = Result.get();
25310 }
25311 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
25312 ExprResult Result = SemaRef.CheckPlaceholderExpr(Length);
25313 if (Result.isInvalid())
25314 return ExprError();
25315 Result = SemaRef.DefaultLvalueConversion(Result.get());
25316 if (Result.isInvalid())
25317 return ExprError();
25318 Length = Result.get();
25319 }
25320 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
25321 ExprResult Result = SemaRef.CheckPlaceholderExpr(Stride);
25322 if (Result.isInvalid())
25323 return ExprError();
25324 Result = SemaRef.DefaultLvalueConversion(Result.get());
25325 if (Result.isInvalid())
25326 return ExprError();
25327 Stride = Result.get();
25328 }
25329
25330 // Build an unanalyzed expression if either operand is type-dependent.
25331 if (Base->isTypeDependent() ||
25332 (LowerBound &&
25333 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
25334 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
25335 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
25336 return new (Context) ArraySectionExpr(
25337 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
25338 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
25339 }
25340
25341 // Perform default conversions.
25343 QualType ResultTy;
25344 if (OriginalTy->isAnyPointerType()) {
25345 ResultTy = OriginalTy->getPointeeType();
25346 } else if (OriginalTy->isArrayType()) {
25347 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
25348 } else {
25349 return ExprError(
25350 Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
25351 << Base->getSourceRange());
25352 }
25353 // C99 6.5.2.1p1
25354 if (LowerBound) {
25355 auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
25356 LowerBound);
25357 if (Res.isInvalid())
25358 return ExprError(Diag(LowerBound->getExprLoc(),
25359 diag::err_omp_typecheck_section_not_integer)
25360 << 0 << LowerBound->getSourceRange());
25361 LowerBound = Res.get();
25362
25363 if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25364 LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25365 Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
25366 << 0 << LowerBound->getSourceRange();
25367 }
25368 if (Length) {
25369 auto Res =
25370 PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
25371 if (Res.isInvalid())
25372 return ExprError(Diag(Length->getExprLoc(),
25373 diag::err_omp_typecheck_section_not_integer)
25374 << 1 << Length->getSourceRange());
25375 Length = Res.get();
25376
25377 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25378 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25379 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
25380 << 1 << Length->getSourceRange();
25381 }
25382 if (Stride) {
25383 ExprResult Res =
25385 if (Res.isInvalid())
25386 return ExprError(Diag(Stride->getExprLoc(),
25387 diag::err_omp_typecheck_section_not_integer)
25388 << 1 << Stride->getSourceRange());
25389 Stride = Res.get();
25390
25391 if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25392 Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25393 Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
25394 << 1 << Stride->getSourceRange();
25395 }
25396
25397 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
25398 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
25399 // type. Note that functions are not objects, and that (in C99 parlance)
25400 // incomplete types are not object types.
25401 if (ResultTy->isFunctionType()) {
25402 Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
25403 << ResultTy << Base->getSourceRange();
25404 return ExprError();
25405 }
25406
25407 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
25408 diag::err_omp_section_incomplete_type, Base))
25409 return ExprError();
25410
25411 if (LowerBound && !OriginalTy->isAnyPointerType()) {
25413 if (LowerBound->EvaluateAsInt(Result, Context)) {
25414 // OpenMP 5.0, [2.1.5 Array Sections]
25415 // The array section must be a subset of the original array.
25416 llvm::APSInt LowerBoundValue = Result.Val.getInt();
25417 if (LowerBoundValue.isNegative()) {
25418 Diag(LowerBound->getExprLoc(),
25419 diag::err_omp_section_not_subset_of_array)
25420 << LowerBound->getSourceRange();
25421 return ExprError();
25422 }
25423 }
25424 }
25425
25426 if (Length) {
25428 if (Length->EvaluateAsInt(Result, Context)) {
25429 // OpenMP 5.0, [2.1.5 Array Sections]
25430 // The length must evaluate to non-negative integers.
25431 llvm::APSInt LengthValue = Result.Val.getInt();
25432 if (LengthValue.isNegative()) {
25433 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
25434 << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
25435 << Length->getSourceRange();
25436 return ExprError();
25437 }
25438 }
25439 } else if (SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.isValid() &&
25440 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
25441 !OriginalTy->isVariableArrayType()))) {
25442 // OpenMP 5.0, [2.1.5 Array Sections]
25443 // When the size of the array dimension is not known, the length must be
25444 // specified explicitly.
25445 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
25446 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
25447 return ExprError();
25448 }
25449
25450 if (Stride) {
25452 if (Stride->EvaluateAsInt(Result, Context)) {
25453 // OpenMP 5.0, [2.1.5 Array Sections]
25454 // The stride must evaluate to a positive integer.
25455 llvm::APSInt StrideValue = Result.Val.getInt();
25456 if (!StrideValue.isStrictlyPositive()) {
25457 Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
25458 << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
25459 << Stride->getSourceRange();
25460 return ExprError();
25461 }
25462 }
25463 }
25464
25465 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
25466 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(Base);
25467 if (Result.isInvalid())
25468 return ExprError();
25469 Base = Result.get();
25470 }
25471 return new (Context) ArraySectionExpr(
25472 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
25473 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
25474}
25475
25477 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
25478 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
25479 ASTContext &Context = getASTContext();
25480 if (Base->hasPlaceholderType()) {
25481 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
25482 if (Result.isInvalid())
25483 return ExprError();
25484 Result = SemaRef.DefaultLvalueConversion(Result.get());
25485 if (Result.isInvalid())
25486 return ExprError();
25487 Base = Result.get();
25488 }
25489 QualType BaseTy = Base->getType();
25490 // Delay analysis of the types/expressions if instantiation/specialization is
25491 // required.
25492 if (!BaseTy->isPointerType() && Base->isTypeDependent())
25493 return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
25494 LParenLoc, RParenLoc, Dims, Brackets);
25495 if (!BaseTy->isPointerType() ||
25496 (!Base->isTypeDependent() &&
25497 BaseTy->getPointeeType()->isIncompleteType()))
25498 return ExprError(Diag(Base->getExprLoc(),
25499 diag::err_omp_non_pointer_type_array_shaping_base)
25500 << Base->getSourceRange());
25501
25502 SmallVector<Expr *, 4> NewDims;
25503 bool ErrorFound = false;
25504 for (Expr *Dim : Dims) {
25505 if (Dim->hasPlaceholderType()) {
25506 ExprResult Result = SemaRef.CheckPlaceholderExpr(Dim);
25507 if (Result.isInvalid()) {
25508 ErrorFound = true;
25509 continue;
25510 }
25511 Result = SemaRef.DefaultLvalueConversion(Result.get());
25512 if (Result.isInvalid()) {
25513 ErrorFound = true;
25514 continue;
25515 }
25516 Dim = Result.get();
25517 }
25518 if (!Dim->isTypeDependent()) {
25521 if (Result.isInvalid()) {
25522 ErrorFound = true;
25523 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
25524 << Dim->getSourceRange();
25525 continue;
25526 }
25527 Dim = Result.get();
25528 Expr::EvalResult EvResult;
25529 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
25530 // OpenMP 5.0, [2.1.4 Array Shaping]
25531 // Each si is an integral type expression that must evaluate to a
25532 // positive integer.
25533 llvm::APSInt Value = EvResult.Val.getInt();
25534 if (!Value.isStrictlyPositive()) {
25535 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
25536 << toString(Value, /*Radix=*/10, /*Signed=*/true)
25537 << Dim->getSourceRange();
25538 ErrorFound = true;
25539 continue;
25540 }
25541 }
25542 }
25543 NewDims.push_back(Dim);
25544 }
25545 if (ErrorFound)
25546 return ExprError();
25547 return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
25548 LParenLoc, RParenLoc, NewDims, Brackets);
25549}
25550
25552 SourceLocation IteratorKwLoc,
25553 SourceLocation LLoc,
25554 SourceLocation RLoc,
25556 ASTContext &Context = getASTContext();
25558 bool IsCorrect = true;
25559 for (const OMPIteratorData &D : Data) {
25560 TypeSourceInfo *TInfo = nullptr;
25561 SourceLocation StartLoc;
25562 QualType DeclTy;
25563 if (!D.Type.getAsOpaquePtr()) {
25564 // OpenMP 5.0, 2.1.6 Iterators
25565 // In an iterator-specifier, if the iterator-type is not specified then
25566 // the type of that iterator is of int type.
25567 DeclTy = Context.IntTy;
25568 StartLoc = D.DeclIdentLoc;
25569 } else {
25570 DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo);
25571 StartLoc = TInfo->getTypeLoc().getBeginLoc();
25572 }
25573
25574 bool IsDeclTyDependent = DeclTy->isDependentType() ||
25575 DeclTy->containsUnexpandedParameterPack() ||
25576 DeclTy->isInstantiationDependentType();
25577 if (!IsDeclTyDependent) {
25578 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
25579 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
25580 // The iterator-type must be an integral or pointer type.
25581 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25582 << DeclTy;
25583 IsCorrect = false;
25584 continue;
25585 }
25586 if (DeclTy.isConstant(Context)) {
25587 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
25588 // The iterator-type must not be const qualified.
25589 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25590 << DeclTy;
25591 IsCorrect = false;
25592 continue;
25593 }
25594 }
25595
25596 // Iterator declaration.
25597 assert(D.DeclIdent && "Identifier expected.");
25598 // Always try to create iterator declarator to avoid extra error messages
25599 // about unknown declarations use.
25600 auto *VD =
25601 VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc,
25602 D.DeclIdent, DeclTy, TInfo, SC_None);
25603 VD->setImplicit();
25604 if (S) {
25605 // Check for conflicting previous declaration.
25606 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
25609 Previous.suppressDiagnostics();
25610 SemaRef.LookupName(Previous, S);
25611
25612 SemaRef.FilterLookupForScope(Previous, SemaRef.CurContext, S,
25613 /*ConsiderLinkage=*/false,
25614 /*AllowInlineNamespace=*/false);
25615 if (!Previous.empty()) {
25616 NamedDecl *Old = Previous.getRepresentativeDecl();
25617 Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
25618 Diag(Old->getLocation(), diag::note_previous_definition);
25619 } else {
25620 SemaRef.PushOnScopeChains(VD, S);
25621 }
25622 } else {
25623 SemaRef.CurContext->addDecl(VD);
25624 }
25625
25626 /// Act on the iterator variable declaration.
25628
25629 Expr *Begin = D.Range.Begin;
25630 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
25631 ExprResult BeginRes = SemaRef.PerformImplicitConversion(
25632 Begin, DeclTy, AssignmentAction::Converting);
25633 Begin = BeginRes.get();
25634 }
25635 Expr *End = D.Range.End;
25636 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
25637 ExprResult EndRes = SemaRef.PerformImplicitConversion(
25638 End, DeclTy, AssignmentAction::Converting);
25639 End = EndRes.get();
25640 }
25641 Expr *Step = D.Range.Step;
25642 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
25643 if (!Step->getType()->isIntegralType(Context)) {
25644 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
25645 << Step << Step->getSourceRange();
25646 IsCorrect = false;
25647 continue;
25648 }
25649 std::optional<llvm::APSInt> Result =
25650 Step->getIntegerConstantExpr(Context);
25651 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
25652 // If the step expression of a range-specification equals zero, the
25653 // behavior is unspecified.
25654 if (Result && Result->isZero()) {
25655 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
25656 << Step << Step->getSourceRange();
25657 IsCorrect = false;
25658 continue;
25659 }
25660 }
25661 if (!Begin || !End || !IsCorrect) {
25662 IsCorrect = false;
25663 continue;
25664 }
25665 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
25666 IDElem.IteratorDecl = VD;
25667 IDElem.AssignmentLoc = D.AssignLoc;
25668 IDElem.Range.Begin = Begin;
25669 IDElem.Range.End = End;
25670 IDElem.Range.Step = Step;
25671 IDElem.ColonLoc = D.ColonLoc;
25672 IDElem.SecondColonLoc = D.SecColonLoc;
25673 }
25674 if (!IsCorrect) {
25675 // Invalidate all created iterator declarations if error is found.
25676 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
25677 if (Decl *ID = D.IteratorDecl)
25678 ID->setInvalidDecl();
25679 }
25680 return ExprError();
25681 }
25683 if (!SemaRef.CurContext->isDependentContext()) {
25684 // Build number of ityeration for each iteration range.
25685 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
25686 // ((Begini-Stepi-1-Endi) / -Stepi);
25688 // (Endi - Begini)
25689 ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub,
25690 D.Range.End, D.Range.Begin);
25691 if (!Res.isUsable()) {
25692 IsCorrect = false;
25693 continue;
25694 }
25695 ExprResult St, St1;
25696 if (D.Range.Step) {
25697 St = D.Range.Step;
25698 // (Endi - Begini) + Stepi
25699 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(),
25700 St.get());
25701 if (!Res.isUsable()) {
25702 IsCorrect = false;
25703 continue;
25704 }
25705 // (Endi - Begini) + Stepi - 1
25706 Res = SemaRef.CreateBuiltinBinOp(
25707 D.AssignmentLoc, BO_Sub, Res.get(),
25708 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
25709 if (!Res.isUsable()) {
25710 IsCorrect = false;
25711 continue;
25712 }
25713 // ((Endi - Begini) + Stepi - 1) / Stepi
25714 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(),
25715 St.get());
25716 if (!Res.isUsable()) {
25717 IsCorrect = false;
25718 continue;
25719 }
25720 St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
25721 D.Range.Step);
25722 // (Begini - Endi)
25723 ExprResult Res1 = SemaRef.CreateBuiltinBinOp(
25724 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
25725 if (!Res1.isUsable()) {
25726 IsCorrect = false;
25727 continue;
25728 }
25729 // (Begini - Endi) - Stepi
25730 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(),
25731 St1.get());
25732 if (!Res1.isUsable()) {
25733 IsCorrect = false;
25734 continue;
25735 }
25736 // (Begini - Endi) - Stepi - 1
25737 Res1 = SemaRef.CreateBuiltinBinOp(
25738 D.AssignmentLoc, BO_Sub, Res1.get(),
25739 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
25740 if (!Res1.isUsable()) {
25741 IsCorrect = false;
25742 continue;
25743 }
25744 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
25745 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(),
25746 St1.get());
25747 if (!Res1.isUsable()) {
25748 IsCorrect = false;
25749 continue;
25750 }
25751 // Stepi > 0.
25752 ExprResult CmpRes = SemaRef.CreateBuiltinBinOp(
25753 D.AssignmentLoc, BO_GT, D.Range.Step,
25754 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
25755 if (!CmpRes.isUsable()) {
25756 IsCorrect = false;
25757 continue;
25758 }
25759 Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
25760 CmpRes.get(), Res.get(), Res1.get());
25761 if (!Res.isUsable()) {
25762 IsCorrect = false;
25763 continue;
25764 }
25765 }
25766 Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false);
25767 if (!Res.isUsable()) {
25768 IsCorrect = false;
25769 continue;
25770 }
25771
25772 // Build counter update.
25773 // Build counter.
25774 auto *CounterVD = VarDecl::Create(Context, SemaRef.CurContext,
25775 D.IteratorDecl->getBeginLoc(),
25776 D.IteratorDecl->getBeginLoc(), nullptr,
25777 Res.get()->getType(), nullptr, SC_None);
25778 CounterVD->setImplicit();
25779 ExprResult RefRes =
25780 SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue,
25781 D.IteratorDecl->getBeginLoc());
25782 // Build counter update.
25783 // I = Begini + counter * Stepi;
25784 ExprResult UpdateRes;
25785 if (D.Range.Step) {
25786 UpdateRes = SemaRef.CreateBuiltinBinOp(
25787 D.AssignmentLoc, BO_Mul,
25788 SemaRef.DefaultLvalueConversion(RefRes.get()).get(), St.get());
25789 } else {
25790 UpdateRes = SemaRef.DefaultLvalueConversion(RefRes.get());
25791 }
25792 if (!UpdateRes.isUsable()) {
25793 IsCorrect = false;
25794 continue;
25795 }
25796 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
25797 D.Range.Begin, UpdateRes.get());
25798 if (!UpdateRes.isUsable()) {
25799 IsCorrect = false;
25800 continue;
25801 }
25802 ExprResult VDRes =
25803 SemaRef.BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl),
25804 cast<VarDecl>(D.IteratorDecl)->getType(),
25805 VK_LValue, D.IteratorDecl->getBeginLoc());
25806 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
25807 VDRes.get(), UpdateRes.get());
25808 if (!UpdateRes.isUsable()) {
25809 IsCorrect = false;
25810 continue;
25811 }
25812 UpdateRes =
25813 SemaRef.ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true);
25814 if (!UpdateRes.isUsable()) {
25815 IsCorrect = false;
25816 continue;
25817 }
25818 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
25819 D.AssignmentLoc, UO_PreInc, RefRes.get());
25820 if (!CounterUpdateRes.isUsable()) {
25821 IsCorrect = false;
25822 continue;
25823 }
25824 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(CounterUpdateRes.get(),
25825 /*DiscardedValue=*/true);
25826 if (!CounterUpdateRes.isUsable()) {
25827 IsCorrect = false;
25828 continue;
25829 }
25830 OMPIteratorHelperData &HD = Helpers.emplace_back();
25831 HD.CounterVD = CounterVD;
25832 HD.Upper = Res.get();
25833 HD.Update = UpdateRes.get();
25834 HD.CounterUpdate = CounterUpdateRes.get();
25835 }
25836 } else {
25837 Helpers.assign(ID.size(), {});
25838 }
25839 if (!IsCorrect) {
25840 // Invalidate all created iterator declarations if error is found.
25841 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
25842 if (Decl *ID = D.IteratorDecl)
25843 ID->setInvalidDecl();
25844 }
25845 return ExprError();
25846 }
25847 return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc,
25848 LLoc, RLoc, ID, Helpers);
25849}
25850
25851/// Check if \p AssumptionStr is a known assumption and warn if not.
25853 StringRef AssumptionStr) {
25854 if (llvm::getKnownAssumptionStrings().count(AssumptionStr))
25855 return;
25856
25857 unsigned BestEditDistance = 3;
25858 StringRef Suggestion;
25859 for (const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) {
25860 unsigned EditDistance =
25861 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
25862 if (EditDistance < BestEditDistance) {
25863 Suggestion = KnownAssumptionIt.getKey();
25864 BestEditDistance = EditDistance;
25865 }
25866 }
25867
25868 if (!Suggestion.empty())
25869 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
25870 << AssumptionStr << Suggestion;
25871 else
25872 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
25873 << AssumptionStr;
25874}
25875
25877 // Handle the case where the attribute has a text message.
25878 StringRef Str;
25879 SourceLocation AttrStrLoc;
25880 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
25881 return;
25882
25883 checkOMPAssumeAttr(SemaRef, AttrStrLoc, Str);
25884
25885 D->addAttr(::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
25886}
25887
25889 : SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
Defines the clang::ASTContext interface.
#define V(N, I)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
This file defines OpenMP nodes for declarative directives.
Expr::Classification Cl
FormatToken * Previous
The previous token in the unwrapped line.
static const Decl * getCanonicalDecl(const Decl *D)
#define X(type, name)
Definition Value.h:97
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
llvm::MachO::TargetList TargetList
Definition MachO.h:52
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
llvm::DenseMap< Stmt *, Stmt * > MapTy
Definition ParentMap.cpp:21
Implements a partial diagnostic that can be emitted anwyhere in a DiagnosticBuilder stream.
@ ForVisibleRedeclaration
The lookup results will be used for redeclaration of a name, if an entity by that name already exists...
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
CastType
Definition SemaCast.cpp:49
static VarDecl * buildVarDecl(Sema &S, SourceLocation Loc, QualType Type, IdentifierInfo *II)
Build a variable declaration for move parameter.
static NamedDecl * findAcceptableDecl(Sema &SemaRef, NamedDecl *D, unsigned IDNS)
Retrieve the visible declaration corresponding to D, if any.
static Expr * getOrderedNumberExpr(ArrayRef< OMPClause * > Clauses)
static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack, bool Diagnose=true)
Tries to find omp_depend_t. type.
static Stmt * buildPreInits(ASTContext &Context, MutableArrayRef< Decl * > PreInits)
Build preinits statement for the given declarations.
static void argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id, SourceLocation Loc, QualType Ty, SmallVectorImpl< UnresolvedSet< 8 > > &Lookups)
static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR, Sema &SemaRef, Decl *D)
static void updatePreInits(OMPLoopTransformationDirective *Transform, SmallVectorImpl< Stmt * > &PreInits)
Updates OriginalInits by checking Transform against loop transformation directives and appending thei...
static bool checkGenericLoopLastprivate(Sema &S, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind K, DSAStackTy *Stack)
static bool checkSimdlenSafelenSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto, QualType NewType)
static bool checkOMPArraySectionConstantForReduction(ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement, SmallVectorImpl< llvm::APSInt > &ArraySizes)
static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPDirectiveKind > AllowedNameModifiers)
static void handleDeclareVariantConstructTrait(DSAStackTy *Stack, OpenMPDirectiveKind DKind, bool ScopeEntry)
static VarDecl * precomputeExpr(Sema &Actions, SmallVectorImpl< Stmt * > &BodyStmts, Expr *E, StringRef Name)
static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type)
static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type, Expr *UnresolvedMapper)
static bool checkReductionClauseWithNogroup(Sema &S, ArrayRef< OMPClause * > Clauses)
static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt, DSAStackTy *Stack)
static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, SourceLocation M1Loc, SourceLocation M2Loc)
static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef)
static Expr * makeFloorIVRef(Sema &SemaRef, ArrayRef< VarDecl * > FloorIndVars, int I, QualType IVTy, DeclRefExpr *OrigCntVar)
Build and return a DeclRefExpr for the floor induction variable using the SemaRef and the provided pa...
static OMPAllocateDeclAttr::AllocatorTypeTy getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator)
static bool isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind, bool StrictlyPositive, bool BuildCapture=false, OpenMPDirectiveKind DKind=OMPD_unknown, OpenMPDirectiveKind *CaptureRegion=nullptr, Stmt **HelperValStmt=nullptr)
static Expr * buildPostUpdate(Sema &S, ArrayRef< Expr * > PostUpdates)
Build postupdate expression for the given list of postupdates expressions.
static CapturedStmt * buildLoopVarFunc(Sema &Actions, QualType LoopVarTy, QualType LogicalTy, DeclRefExpr *StartExpr, Expr *Step, bool Deref)
Create a closure that computes the loop variable from the logical iteration number.
static ExprResult buildCounterUpdate(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract, bool IsNonRectangularLB, llvm::MapVector< const Expr *, DeclRefExpr * > *Captures=nullptr)
Build 'VarRef = Start + Iter * Step'.
static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion, OpenMPDirectiveKind NameModifier=OMPD_unknown)
static bool finishLinearClauses(Sema &SemaRef, ArrayRef< OMPClause * > Clauses, OMPLoopBasedDirective::HelperExprs &B, DSAStackTy *Stack)
static Expr * getCollapseNumberExpr(ArrayRef< OMPClause * > Clauses)
static Expr * getDirectCallExpr(Expr *E)
static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
static OMPCapturedExprDecl * buildCaptureDecl(Sema &S, IdentifierInfo *Id, Expr *CaptureExpr, bool WithInit, DeclContext *CurContext, bool AsExpression)
static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_allocator_handle_t type.
static bool isClauseMappable(ArrayRef< OMPClause * > Clauses)
Check if the variables in the mapping clause are externally visible.
static BinaryOperatorKind getRelatedCompoundReductionOp(BinaryOperatorKind BOK)
static SmallVector< SemaOpenMP::CapturedParamNameType > getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing)
static void collectLoopStmts(Stmt *AStmt, MutableArrayRef< Stmt * > LoopStmts)
Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected loop of a construct.
static bool checkMutuallyExclusiveClauses(Sema &S, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPClauseKind > MutuallyExclusiveClauses)
Find and diagnose mutually exclusive clause kinds.
static std::pair< ValueDecl *, bool > getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, SourceRange &ERange, bool AllowArraySection=false, bool AllowAssumedSizeArray=false, StringRef DiagType="")
static DeclRefExpr * buildImplicitMap(Sema &S, QualType BaseType, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Maps)
static bool checkOrderedOrderSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static OpenMPMapClauseKind getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M, bool IsAggregateOrDeclareTarget)
static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind, Scope *CurScope, SourceLocation Loc)
static const Expr * getExprAsWritten(const Expr *E)
static bool checkMapConflicts(Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E, bool CurrentRegionOnly, OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents, OpenMPClauseKind CKind)
static bool isOpenMPDeviceDelayedContext(Sema &S)
static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef)
Convert integer expression E to make it have at least Bits bits.
static SmallVector< SemaOpenMP::CapturedParamNameType > getUnknownRegionParams(Sema &SemaRef)
static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack, QualType CanonType, const Expr *E)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTeamsRegionParams(Sema &SemaRef)
static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc, StringRef AssumptionStr)
Check if AssumptionStr is a known assumption and warn if not.
static void applyOMPAllocateAttribute(Sema &S, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator, Expr *Alignment, SourceRange SR)
static ExprResult buildImplicitMapper(Sema &S, QualType BaseType, DSAStackTy *Stack)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTargetRegionParams(Sema &SemaRef)
static CapturedStmt * buildDistanceFunc(Sema &Actions, QualType LogicalTy, BinaryOperator::Opcode Rel, Expr *StartExpr, Expr *StopExpr, Expr *StepExpr)
Create a closure that computes the number of iterations of a loop.
static bool checkPreviousOMPAllocateAttribute(Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator)
static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, Expr *NumIterations, Sema &SemaRef, Scope *S, DSAStackTy *Stack)
static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D, QualType Type, OpenMPClauseKind CKind, SourceLocation ELoc, bool AcceptIfMutable=true, bool ListItemNotVar=false)
static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr, SourceLocation VarLoc, OpenMPClauseKind Kind)
static const ValueDecl * getCanonicalDecl(const ValueDecl *D)
static std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C)
static const Expr * checkMapClauseExpressionBase(Sema &SemaRef, Expr *E, OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose)
Return the expression of the base of the mappable expression or null if it cannot be determined and d...
static void checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind, MappableVarListInfo &MVLI, SourceLocation StartLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId, ArrayRef< Expr * > UnresolvedMappers, OpenMPMapClauseKind MapType=OMPC_MAP_unknown, ArrayRef< OpenMPMapModifierKind > Modifiers={}, bool IsMapTypeImplicit=false, bool NoDiagnose=false)
static bool hasClauses(ArrayRef< OMPClause * > Clauses, const OpenMPClauseKind K)
Check for existence of a map clause in the list of clauses.
static bool checkOpenMPIterationSpace(OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA, unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, llvm::MutableArrayRef< LoopIterationSpace > ResultIterSpaces, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures, const llvm::SmallPtrSetImpl< const Decl * > &CollapsedLoopVarDecls)
Called on a for stmt to check and extract its iteration space for further processing (such as collaps...
static CapturedStmt * setBranchProtectedScope(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt)
static void processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Clauses)
Perform DFS through the structure/class data members trying to find member(s) with user-defined 'defa...
static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion, OpenMPDirectiveKind CancelRegion, SourceLocation StartLoc)
static DeclRefExpr * buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty, SourceLocation Loc, bool RefersToCapture=false)
static ExprResult buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, ExprResult Start, bool IsNonRectangularLB, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures)
Build 'VarRef = Start.
static DoacrossDataInfoTy ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource, ArrayRef< Expr * > VarList, DSAStackTy *Stack, SourceLocation EndLoc)
static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR, Sema &SemaRef, DSAStackTy *Stack, ValueDecl *VD)
static bool findOMPEventHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_event_handle_t type.
static ExprResult buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, Scope *S, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, QualType Ty, CXXCastPath &BasePath, Expr *UnresolvedReduction)
static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef)
Check if the given expression E is a constant integer that fits into Bits bits.
#define DSAStack
static void checkAllocateClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
static bool actOnOMPReductionKindClause(Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions, ReductionData &RD)
static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack, const ValueDecl *D, const DSAStackTy::DSAVarData &DVar, bool IsLoopIterVar=false)
static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, ArrayRef< unsigned > Exclude={})
static DeclRefExpr * buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, bool WithInit)
static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_alloctrait_t type.
static void appendFlattenedStmtList(SmallVectorImpl< Stmt * > &TargetList, Stmt *Item)
Append the Item or the content of a CompoundStmt to the list TargetList.
static bool isConstNotMutableType(Sema &SemaRef, QualType Type, bool AcceptIfMutable=true, bool *IsClassType=nullptr)
static void addLoopPreInits(ASTContext &Context, OMPLoopBasedDirective::HelperExprs &LoopHelper, Stmt *LoopStmt, ArrayRef< Stmt * > OriginalInit, SmallVectorImpl< Stmt * > &PreInits)
Add preinit statements that need to be propagated from the selected loop.
static void checkReductionClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
Check consistency of the reduction clauses.
static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef, DSAStackTy *Stack, QualType QTy, bool FullCheck=true)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTaskRegionParams(Sema &SemaRef)
static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, OpenMPDirectiveKind CurrentRegion, const DeclarationNameInfo &CurrentName, OpenMPDirectiveKind CancelRegion, OpenMPBindClauseKind BindKind, SourceLocation StartLoc)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTaskloopRegionParams(Sema &SemaRef)
static unsigned checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef, DSAStackTy &DSA, SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, OMPLoopBasedDirective::HelperExprs &Built)
Called on a for stmt to check itself and nested loops (if any).
static OpenMPDefaultmapClauseKind getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD)
static bool checkNumExprsInClause(SemaBase &SemaRef, ArrayRef< OMPClause * > Clauses, unsigned MaxNum, unsigned Diag)
This checks whether a ClauseType clause C has at most Max expression.
static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
Return true if it can be proven that the provided array expression (array section or array subscript)...
static T filterLookupForUDReductionAndMapper(SmallVectorImpl< U > &Lookups, const llvm::function_ref< T(ValueDecl *)> Gen)
This file declares semantic analysis for OpenMP constructs and clauses.
static CharSourceRange getRange(const CharSourceRange &EditRange, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeMacroExpansion)
This file defines OpenMP AST classes for executable directives and clauses.
Expr * getUpdateExpr()
Get helper expression of the form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or 'OpaqueValueExp...
Expr * getV()
Get 'v' part of the associated expression/statement.
Expr * getR()
Get 'r' part of the associated expression/statement.
Expr * getD()
Get 'd' part of the associated expression/statement.
Expr * getX()
Get 'x' part of the associated expression/statement.
bool isFailOnly() const
Return true if 'v' is updated only when the condition is evaluated false (compare capture only).
bool isPostfixUpdate() const
Return true if 'v' expression must be updated to original value of 'x', false if 'v' must be updated ...
Expr * getExpr()
Get 'expr' part of the associated expression/statement.
bool isXLHSInRHSPart() const
Return true if helper update expression has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and...
static QualType getPointeeType(const MemRegion *R)
VerifyDiagnosticConsumer::Directive Directive
Look for variables declared in the body parts of a for-loop nest.
bool VisitCXXForRangeStmt(CXXForRangeStmt *RF) override
bool VisitVarDecl(VarDecl *D) override
ForVarDeclFinder(llvm::SmallPtrSetImpl< const Decl * > &VD)
bool VisitForStmt(ForStmt *F) override
This class visits every VarDecl that the initializer references and adds OMPDeclareTargetDeclAttr to ...
void declareTargetInitializer(Decl *TD)
A function that keeps a record of all the Decls that are variables, has OMPDeclareTargetDeclAttr,...
void VisitDeclRefExpr(DeclRefExpr *Node)
A StmtVisitor class function that visits all DeclRefExpr and adds OMPDeclareTargetDeclAttr to them.
void VisitExpr(Expr *Ex)
A function that iterates across each of the Expr's children.
bool VisitCXXForRangeStmt(CXXForRangeStmt *FRS) override
NestedLoopCounterVisitor()=default
bool VisitForStmt(ForStmt *FS) override
bool TraverseStmt(Stmt *S) override
bool TraverseDecl(Decl *D) override
unsigned getNestedLoopCount() const
static OMPAssumeDirective * Create(const ASTContext &Ctx, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AStmt)
static OMPCancelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind CancelRegion)
Creates directive.
static OMPCancellationPointDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Creates directive.
static OMPDispatchDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, SourceLocation TargetCallLoc)
Creates directive with a list of Clauses.
static OMPDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPErrorDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
static OMPFuseDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumGeneratedTopLevelLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for pragma omp fuse'.
static OMPGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPInterchangeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp interchange'.
static OMPInteropDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
static OMPMaskedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPReverseDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, unsigned NumLoops, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp reverse'.
static OMPScanDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
static OMPStripeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp stripe'.
static OMPTargetDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetEnterDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetExitDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetParallelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool CanBeParallelFor)
Creates directive with a list of Clauses.
static OMPTargetUpdateDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTileDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp tile'.
static OMPUnrollDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, unsigned NumGeneratedTopLevelLoops, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp unroll'.
APSInt & getInt()
Definition APValue.h:489
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:220
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
unsigned getIntWidth(QualType T) const
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, bool Unqualified=false, bool AllowCXX=false, bool IsConditionalOperator=false)
DeclarationNameTable DeclarationNames
Definition ASTContext.h:776
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 getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
CanQualType VoidPtrTy
void Deallocate(void *Ptr) const
Definition ASTContext.h:852
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:772
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.
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
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
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:891
An abstract interface that should be implemented by listeners that want to be notified when an AST en...
bool isUnset() const
Definition Ownership.h:168
PtrTy get() const
Definition Ownership.h:171
bool isInvalid() const
Definition Ownership.h:167
bool isUsable() const
Definition Ownership.h:169
This class represents BOTH the OpenMP Array Section and OpenACC 'subarray', with a boolean differenti...
Definition Expr.h:7105
Expr * getBase()
Get base of the array section.
Definition Expr.h:7171
Expr * getLength()
Get length of array section.
Definition Expr.h:7181
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition Expr.cpp:5265
Expr * getLowerBound()
Get lower bound of array section.
Definition Expr.h:7175
SourceLocation getColonLocFirst() const
Definition Expr.h:7202
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3722
QualType getElementType() const
Definition TypeBase.h:3734
Attr - This represents one attribute.
Definition Attr.h:44
Represents an attribute applied to a statement.
Definition Stmt.h:2203
static AttributedStmt * Create(const ASTContext &C, SourceLocation Loc, ArrayRef< const Attr * > Attrs, Stmt *SubStmt)
Definition Stmt.cpp:432
SourceLocation getBeginLoc() const
Definition Stmt.h:2242
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:3972
Expr * getLHS() const
Definition Expr.h:4022
static bool isRelationalOp(Opcode Opc)
Definition Expr.h:4066
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition Expr.cpp:2175
static Opcode getOpForCompoundAssignment(Opcode Opc)
Definition Expr.h:4119
SourceLocation getOperatorLoc() const
Definition Expr.h:4014
SourceLocation getExprLoc() const
Definition Expr.h:4013
static Opcode reverseComparisonOp(Opcode Opc)
Definition Expr.h:4091
Expr * getRHS() const
Definition Expr.h:4024
Opcode getOpcode() const
Definition Expr.h:4017
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition Expr.cpp:2137
BinaryOperatorKind Opcode
Definition Expr.h:3977
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
CXXBasePath & front()
bool isAmbiguous(CanQualType BaseType)
Determine whether the path from the most-derived type to the given base type is ambiguous (i....
Represents a C++ constructor within a class.
Definition DeclCXX.h:2604
Represents a C++ conversion function within a class.
Definition DeclCXX.h:2943
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
Definition StmtCXX.h:135
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool hasMutableFields() const
Determine whether this class, or any of its class subobjects, contains a mutable field.
Definition DeclCXX.h:1233
bool hasDefinition() const
Definition DeclCXX.h:561
Represents a C++ nested-name-specifier or a global scope specifier.
Definition DeclSpec.h:73
bool isValid() const
A scope specifier is present, and it refers to a real scope.
Definition DeclSpec.h:185
SourceLocation getBeginLoc() const
Definition DeclSpec.h:83
bool isSet() const
Deprecated.
Definition DeclSpec.h:198
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const
Retrieve a nested-name-specifier with location information, copied into the given AST context.
Definition DeclSpec.cpp:123
bool isInvalid() const
An error occurred during parsing of the scope specifier.
Definition DeclSpec.h:183
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2877
SourceLocation getBeginLoc() const
Definition Expr.h:3211
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
Definition Expr.cpp:1513
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3060
Expr * getCallee()
Definition Expr.h:3024
arg_range arguments()
Definition Expr.h:3129
A wrapper class around a pointer that always points to its canonical declaration.
Represents the body of a CapturedStmt, and serves as its DeclContext.
Definition Decl.h:4926
unsigned getNumParams() const
Definition Decl.h:4964
void setNothrow(bool Nothrow=true)
Definition Decl.cpp:5621
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:5617
ImplicitParamDecl * getParam(unsigned i) const
Definition Decl.h:4966
This captures a statement into a function.
Definition Stmt.h:3886
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
Definition Stmt.cpp:1451
SourceRange getSourceRange() const LLVM_READONLY
Definition Stmt.h:4089
Stmt * getCapturedStmt()
Retrieve the statement being captured.
Definition Stmt.h:3990
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
Definition Stmt.cpp:1475
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.h:4081
capture_range captures()
Definition Stmt.h:4024
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3610
Declaration of a class template.
Complex values, per C99 6.2.5p11.
Definition TypeBase.h:3275
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition Stmt.h:1720
SourceLocation getBeginLoc() const
Definition Stmt.h:1854
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
Definition Stmt.cpp:390
ConditionalOperator - The ?
Definition Expr.h:4325
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1449
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2109
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
Definition DeclBase.h:2238
bool isFileContext() const
Definition DeclBase.h:2180
DeclContextLookupResult lookup_result
Definition DeclBase.h:2577
ASTContext & getParentASTContext() const
Definition DeclBase.h:2138
bool isExternCXXContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
bool isNamespace() const
Definition DeclBase.h:2198
bool isTranslationUnit() const
Definition DeclBase.h:2185
void addDecl(Decl *D)
Add the declaration D into this context.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition DeclBase.h:2373
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
bool Encloses(const DeclContext *DC) const
Determine whether this declaration context semantically encloses the declaration context DC.
void addHiddenDecl(Decl *D)
Add the declaration D to this context without modifying any lookup tables.
static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls)
Definition DeclGroup.h:64
Decl * getSingleDecl()
Definition DeclGroup.h:79
bool isSingleDecl() const
Definition DeclGroup.h:76
bool isNull() const
Definition DeclGroup.h:75
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1270
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Definition Expr.cpp:484
ValueDecl * getDecl()
Definition Expr.h:1338
NonOdrUseReason isNonOdrUse() const
Is this expression a non-odr-use reference, and if so, why?
Definition Expr.h:1468
SourceLocation getEndLoc() const LLVM_READONLY
Definition Expr.cpp:547
SourceLocation getBeginLoc() const
Definition Expr.h:1349
ConstexprSpecKind getConstexprSpecifier() const
Definition DeclSpec.h:802
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1611
SourceLocation getEndLoc() const
Definition Stmt.h:1634
const DeclGroupRef getDeclGroup() const
Definition Stmt.h:1629
const Decl * getSingleDecl() const
Definition Stmt.h:1626
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.h:1637
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:573
bool hasAttrs() const
Definition DeclBase.h:518
void addAttr(Attr *A)
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition DeclBase.h:593
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Definition DeclBase.cpp:156
void markUsed(ASTContext &C)
Mark the declaration used, in the sense of odr-use.
Definition DeclBase.cpp:568
bool isReferenced() const
Whether any declaration of this entity was referenced.
Definition DeclBase.cpp:578
bool isCanonicalDecl() const
Whether this particular Decl is a canonical one.
Definition DeclBase.h:984
bool isInvalidDecl() const
Definition DeclBase.h:588
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition DeclBase.h:559
void setAccess(AccessSpecifier AS)
Definition DeclBase.h:502
SourceLocation getLocation() const
Definition DeclBase.h:439
void setImplicit(bool I=true)
Definition DeclBase.h:594
void setReferenced(bool R=true)
Definition DeclBase.h:623
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
Definition DeclBase.h:1049
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
Definition DeclBase.cpp:553
DeclContext * getDeclContext()
Definition DeclBase.h:448
AccessSpecifier getAccess() const
Definition DeclBase.h:507
AttrVec & getAttrs()
Definition DeclBase.h:524
void setDeclContext(DeclContext *DC)
setDeclContext - Set both the semantic and lexical DeclContext to DC.
Definition DeclBase.cpp:360
bool hasAttr() const
Definition DeclBase.h:577
void setLexicalDeclContext(DeclContext *DC)
Definition DeclBase.cpp:364
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition DeclBase.h:978
Kind getKind() const
Definition DeclBase.h:442
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:427
DeclarationName getIdentifier(const IdentifierInfo *ID)
Create a declaration name that is a simple identifier.
The name of a declaration.
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
bool isEmpty() const
Evaluates true when this declaration name is empty.
Information about one declarator, including the parsed type information and the identifier.
Definition DeclSpec.h:1874
const DeclSpec & getDeclSpec() const
getDeclSpec - Return the declaration-specifier that this declarator was declared with.
Definition DeclSpec.h:2021
SourceLocation getIdentifierLoc() const
Definition DeclSpec.h:2310
void SetIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc)
Set the name of this declarator to be the given identifier.
Definition DeclSpec.h:2313
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclSpec.h:2057
void setFunctionDefinitionKind(FunctionDefinitionKind Val)
Definition DeclSpec.h:2707
const CXXScopeSpec & getCXXScopeSpec() const
getCXXScopeSpec - Return the C++ scope specifier (global scope or nested-name-specifier) that is part...
Definition DeclSpec.h:2036
bool isInvalidType() const
Definition DeclSpec.h:2688
const IdentifierInfo * getIdentifier() const
Definition DeclSpec.h:2304
virtual bool TraverseStmt(MaybeConst< Stmt > *S)
RAII object that enters a new expression evaluation context.
This represents one expression.
Definition Expr.h:112
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
bool isIntegerConstantExpr(const ASTContext &Ctx) const
bool isGLValue() const
Definition Expr.h:287
@ SE_AllowSideEffects
Allow any unmodeled side effect.
Definition Expr.h:674
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition Expr.cpp:3090
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition Expr.h:177
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition Expr.h:444
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition Expr.h:194
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
Definition Expr.h:241
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Skip past any parentheses and lvalue casts which might surround this expression until reaching a fixe...
Definition Expr.cpp:3102
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:3085
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3073
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:3081
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition Expr.h:284
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition Expr.h:451
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition Expr.h:223
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3065
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:273
QualType getType() const
Definition Expr.h:144
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
Definition Decl.h:3160
bool isBitField() const
Determines whether this field is a bitfield.
Definition Decl.h:3263
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4814
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
Definition Decl.h:3407
static FloatingLiteral * Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L)
Definition Expr.cpp:1072
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition Stmt.h:2888
Stmt * getBody()
Definition Stmt.h:2932
Represents a function declaration or definition.
Definition Decl.h:2000
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2797
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2774
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition Decl.h:2470
FunctionDecl * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
bool isConsteval() const
Definition Decl.h:2482
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3814
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:5266
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:2259
Stmt * getThen()
Definition Stmt.h:2348
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:1002
Expr * getCond()
Definition Stmt.h:2336
Stmt * getElse()
Definition Stmt.h:2357
SourceLocation getBeginLoc() const
Definition Stmt.h:2471
ImaginaryLiteral - We support imaginary integer and floating point literals, like "1....
Definition Expr.h:1731
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition Expr.cpp:2068
ImplicitConversionSequence - Represents an implicit conversion sequence, which may be a standard conv...
Definition Overload.h:615
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateCopy(SourceLocation InitLoc, SourceLocation EqualLoc, bool AllowExplicitConvs=false)
Create a copy initialization.
Describes the sequence of initializations required to initialize a given object or reference with a s...
ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)
Perform the actual initialization of the given entity based on the computed initialization sequence.
Describes an entity that is being initialized.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Definition Expr.cpp:971
Describes the capture of a variable or of this, or of a C++1y init-capture.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
A class for iterating through a result set and possibly filtering out results.
Definition Lookup.h:677
Represents the results of name lookup.
Definition Lookup.h:147
LLVM_ATTRIBUTE_REINITIALIZES void clear()
Clears out any current state.
Definition Lookup.h:607
DeclClass * getAsSingle() const
Definition Lookup.h:558
bool empty() const
Return true if no decls were found.
Definition Lookup.h:362
Filter makeFilter()
Create a filter for this result set.
Definition Lookup.h:751
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
Definition Lookup.h:569
bool isAmbiguous() const
Definition Lookup.h:324
bool isSingleResult() const
Determines if this names a single result which is not an unresolved value using decl.
Definition Lookup.h:331
NamedDecl * getRepresentativeDecl() const
Fetches a representative decl. Useful for lazy diagnostics.
Definition Lookup.h:576
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
Definition Lookup.h:636
iterator end() const
Definition Lookup.h:359
static bool isVisible(Sema &SemaRef, NamedDecl *D)
Determine whether the given declaration is visible to the program.
iterator begin() const
Definition Lookup.h:358
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition Expr.h:3381
Expr * getBase() const
Definition Expr.h:3375
static MemberExpr * CreateImplicit(const ASTContext &C, Expr *Base, bool IsArrow, ValueDecl *MemberDecl, QualType T, ExprValueKind VK, ExprObjectKind OK)
Create an implicit MemberExpr, with no location, qualifier, template arguments, and so on.
Definition Expr.h:3359
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:3493
This represents a decl that may have a name.
Definition Decl.h:274
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:295
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:340
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
Definition Decl.h:317
virtual void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const
Appends a human-readable name for this declaration into the given stream.
Definition Decl.cpp:1834
void setDeclName(DeclarationName N)
Set the name of this declaration.
Definition Decl.h:343
A C++ nested-name-specifier augmented with source location information.
static OMPAbsentClause * Create(const ASTContext &C, ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
This represents 'acq_rel' clause in the 'pragma omp atomic|flush' directives.
This represents 'acquire' clause in the 'pragma omp atomic|flush' directives.
static OMPAffinityClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Creates clause with a modifier a list of locator items.
static OMPAlignClause * Create(const ASTContext &C, Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'align' clause with the given alignment.
static OMPAlignedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Expr *A)
Creates clause with a list of variables VL and alignment A.
static OMPAllocateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, Expr *Allocator, Expr *Alignment, SourceLocation ColonLoc, OpenMPAllocateClauseModifier Modifier1, SourceLocation Modifier1Loc, OpenMPAllocateClauseModifier Modifier2, SourceLocation Modifier2Loc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static bool classof(const OMPClause *T)
static OMPAllocateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL, ArrayRef< OMPClause * > CL)
This represents 'allocator' clause in the 'pragma omp ...' directive.
Expr * getBase()
Fetches base expression of array shaping expression.
Definition ExprOpenMP.h:90
static OMPArrayShapingExpr * Create(const ASTContext &Context, QualType T, Expr *Op, SourceLocation L, SourceLocation R, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > BracketRanges)
Definition Expr.cpp:5346
This represents 'at' clause in the 'pragma omp error' directive.
SourceLocation getAtKindKwLoc() const
Returns location of clause kind.
OpenMPAtClauseKind getAtKind() const
Returns kind of the clause.
This represents 'atomic_default_mem_order' clause in the 'pragma omp requires' directive.
This represents 'bind' clause in the 'pragma omp ...' directives.
static OMPBindClause * Create(const ASTContext &C, OpenMPBindClauseKind K, SourceLocation KLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'bind' clause with kind K ('teams', 'parallel', or 'thread').
This represents 'capture' clause in the 'pragma omp atomic' directive.
Pseudo declaration for capturing expressions.
Definition DeclOpenMP.h:445
static OMPCapturedExprDecl * Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, QualType T, SourceLocation StartLoc)
Class that represents a component of a mappable expression.
ArrayRef< MappableComponent > MappableExprComponentListRef
SmallVector< MappableComponent, 8 > MappableExprComponentList
SmallVector< MappableExprComponentList, 8 > MappableExprComponentLists
static OMPClauseWithPostUpdate * get(OMPClause *C)
Class that handles pre-initialization statement for some clauses, like 'schedule',...
static OMPClauseWithPreInit * get(OMPClause *C)
This is a basic class for representing single OpenMP clause.
SourceLocation getBeginLoc() const
Returns the starting location of the clause.
SourceLocation getEndLoc() const
Returns the ending location of the clause.
OpenMPClauseKind getClauseKind() const
Returns kind of OpenMP clause (private, shared, reduction, etc.).
This represents 'collapse' clause in the 'pragma omp ...' directive.
This represents 'compare' clause in the 'pragma omp atomic' directive.
static OMPContainsClause * Create(const ASTContext &C, ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
static OMPCopyinClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
static OMPCopyprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
This represents 'pragma omp declare mapper ...' directive.
Definition DeclOpenMP.h:349
static OMPDeclareMapperDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, DeclarationName VarName, ArrayRef< OMPClause * > Clauses, OMPDeclareMapperDecl *PrevDeclInScope)
Creates declare mapper node.
This represents 'pragma omp declare reduction ...' directive.
Definition DeclOpenMP.h:239
static OMPDeclareReductionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, OMPDeclareReductionDecl *PrevDeclInScope)
Create declare reduction node.
This represents 'default' clause in the 'pragma omp ...' directive.
This represents 'defaultmap' clause in the 'pragma omp ...' directive.
This represents implicit clause 'depend' for the 'pragma omp task' directive.
static OMPDependClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, DependDataTy Data, Expr *DepModifier, ArrayRef< Expr * > VL, unsigned NumLoops)
Creates clause with a list of variables VL.
static OMPDepobjClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Depobj)
Creates clause.
This represents 'destroy' clause in the 'pragma omp depobj' directive or the 'pragma omp interop' dir...
This represents 'detach' clause in the 'pragma omp task' directive.
This represents 'device' clause in the 'pragma omp ...' directive.
This represents 'dist_schedule' clause in the 'pragma omp ...' directive.
This represents the 'doacross' clause for the 'pragma omp ordered' directive.
static OMPDoacrossClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VL, unsigned NumLoops)
Creates clause with a list of expressions VL.
This represents 'dynamic_allocators' clause in the 'pragma omp requires' directive.
static OMPExclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'fail' clause in the 'pragma omp atomic' directive.
This represents 'filter' clause in the 'pragma omp ...' directive.
This represents 'final' clause in the 'pragma omp ...' directive.
static OMPFirstprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PrivateVL, ArrayRef< Expr * > InitVL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents implicit clause 'flush' for the 'pragma omp flush' directive.
static OMPFlushClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPFromClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
Representation of the 'full' clause of the 'pragma omp unroll' directive.
static OMPFullClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Build an AST node for a 'full' clause.
This represents 'grainsize' clause in the 'pragma omp ...' directive.
This represents 'pragma omp groupprivate ...' directive.
Definition DeclOpenMP.h:173
static OMPGroupPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
static OMPHasDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
This represents 'hint' clause in the 'pragma omp ...' directive.
This represents the 'holds' clause in the 'pragma omp assume' directive.
This represents 'if' clause in the 'pragma omp ...' directive.
static OMPInReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > TaskgroupDescriptors, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
static OMPInclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPInitClause * Create(const ASTContext &C, Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Creates a fully specified clause.
static OMPIsDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPIteratorExpr * Create(const ASTContext &Context, QualType T, SourceLocation IteratorKwLoc, SourceLocation L, SourceLocation R, ArrayRef< IteratorDefinition > Data, ArrayRef< OMPIteratorHelperData > Helpers)
Definition Expr.cpp:5473
This represents clause 'lastprivate' in the 'pragma omp ...' directives.
static OMPLastprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
This represents clause 'linear' in the 'pragma omp ...' directives.
static OMPLinearClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation StepModifierLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PL, ArrayRef< Expr * > IL, Expr *Step, Expr *CalcStep, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL and a linear step Step.
static OMPLoopRangeClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc, Expr *First, Expr *Count)
Build a 'looprange' clause AST node.
static OMPMapClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapModifiers, ArrayRef< SourceLocation > MapModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId, OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc)
Creates clause with a list of variables VL.
This represents 'mergeable' clause in the 'pragma omp ...' directive.
This represents the 'message' clause in the 'pragma omp error' and the 'pragma omp parallel' directiv...
Expr * getMessageString() const
Returns message string of the clause.
std::optional< std::string > tryEvaluateString(ASTContext &Ctx) const
Try to evaluate the message string at compile time.
This represents the 'no_openmp' clause in the 'pragma omp assume' directive.
This represents the 'no_openmp_constructs' clause in the.
This represents the 'no_openmp_routines' clause in the 'pragma omp assume' directive.
This represents the 'no_parallelism' clause in the 'pragma omp assume' directive.
This represents 'nocontext' clause in the 'pragma omp ...' directive.
This represents 'nogroup' clause in the 'pragma omp ...' directive.
This represents clause 'nontemporal' in the 'pragma omp ...' directives.
static OMPNontemporalClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'novariants' clause in the 'pragma omp ...' directive.
This represents 'nowait' clause in the 'pragma omp ...' directive.
This represents 'num_tasks' clause in the 'pragma omp ...' directive.
static OMPNumTeamsClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
This represents 'order' clause in the 'pragma omp ...' directive.
SourceLocation getKindKwLoc() const
Returns location of clause kind.
OpenMPOrderClauseKind getKind() const
Returns kind of the clause.
This represents 'ordered' clause in the 'pragma omp ...' directive.
Expr * getNumForLoops() const
Return the number of associated for-loops.
static OMPOrderedClause * Create(const ASTContext &C, Expr *Num, unsigned NumLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'ordered' clause.
Representation of the 'partial' clause of the 'pragma omp unroll' directive.
static OMPPartialClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Factor)
Build an AST node for a 'partial' clause.
Expr * getFactor() const
Returns the argument of the clause or nullptr if not set.
This class represents the 'permutation' clause in the 'pragma omp interchange' directive.
unsigned getNumLoops() const
Returns the number of list items.
MutableArrayRef< Expr * > getArgsRefs()
Returns the permutation index expressions.
static OMPPermutationClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Args)
Build a 'permutation' clause AST node.
This represents 'priority' clause in the 'pragma omp ...' directive.
static OMPPrivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PrivateVL)
Creates clause with a list of variables VL.
This represents 'proc_bind' clause in the 'pragma omp ...' directive.
This represents 'read' clause in the 'pragma omp atomic' directive.
static OMPReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, OpenMPReductionClauseModifier Modifier, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > CopyOps, ArrayRef< Expr * > CopyArrayTemps, ArrayRef< Expr * > CopyArrayElems, Stmt *PreInit, Expr *PostUpdate, ArrayRef< bool > IsPrivateVarReduction, OpenMPOriginalSharingModifier OriginalSharingModifier)
Creates clause with a list of variables VL.
This represents 'relaxed' clause in the 'pragma omp atomic' directives.
This represents 'release' clause in the 'pragma omp atomic|flush' directives.
This represents 'pragma omp requires...' directive.
Definition DeclOpenMP.h:479
clauselist_range clauselists()
Definition DeclOpenMP.h:504
static OMPRequiresDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< OMPClause * > CL)
Create requires node.
This represents 'reverse_offload' clause in the 'pragma omp requires' directive.
This represents 'simd' clause in the 'pragma omp ...' directive.
This represents 'safelen' clause in the 'pragma omp ...' directive.
Expr * getSafelen() const
Return safe iteration space distance.
This represents 'schedule' clause in the 'pragma omp ...' directive.
SourceLocation getFirstScheduleModifierLoc() const
Get the first modifier location.
OpenMPScheduleClauseModifier getSecondScheduleModifier() const
Get the second modifier of the clause.
OpenMPScheduleClauseModifier getFirstScheduleModifier() const
Get the first modifier of the clause.
SourceLocation getSecondScheduleModifierLoc() const
Get the second modifier location.
This represents 'self_maps' clause in the 'pragma omp requires' directive.
This represents 'seq_cst' clause in the 'pragma omp atomic|flush' directives.
This represents the 'severity' clause in the 'pragma omp error' and the 'pragma omp parallel' directi...
OpenMPSeverityClauseKind getSeverityKind() const
Returns kind of the clause.
SourceLocation getSeverityKindKwLoc() const
Returns location of clause kind.
static OMPSharedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'simdlen' clause in the 'pragma omp ...' directive.
Expr * getSimdlen() const
Return safe iteration space distance.
static OMPSizesClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Sizes)
Build a 'sizes' AST node.
static OMPTaskReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
static OMPThreadLimitClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents 'pragma omp threadprivate ...' directive.
Definition DeclOpenMP.h:110
static OMPThreadPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
This represents 'threads' clause in the 'pragma omp ...' directive.
static OMPToClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
Helper data structure representing the traits in a match clause of an declare variant or metadirectiv...
bool isExtensionActive(llvm::omp::TraitProperty TP)
Check the extension trait TP is active.
bool anyScoreOrCondition(llvm::function_ref< bool(Expr *&, bool)> Cond)
void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const
Create a variant match info object from this trait info object.
This represents 'unified_address' clause in the 'pragma omp requires' directive.
This represents 'unified_shared_memory' clause in the 'pragma omp requires' directive.
This represents 'untied' clause in the 'pragma omp ...' directive.
static OMPUpdateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates clause for 'atomic' directive.
This represents the 'use' clause in 'pragma omp ...' directives.
static OMPUseDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPUseDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< Expr * > PrivateVars, ArrayRef< Expr * > Inits, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
This represents clause 'uses_allocators' in the 'pragma omp target'-based directives.
static OMPUsesAllocatorsClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< OMPUsesAllocatorsClause::Data > Data)
Creates clause with a list of allocators Data.
SourceLocation getLParenLoc() const
Returns the location of '('.
This represents 'weak' clause in the 'pragma omp atomic' directives.
This represents 'write' clause in the 'pragma omp atomic' directive.
This represents 'ompx_attribute' clause in a directive that might generate an outlined function.
This represents 'ompx_bare' clause in the 'pragma omp target teams ...' directive.
This represents 'ompx_dyn_cgroup_mem' clause in the 'pragma omp target ...' directive.
void * getAsOpaquePtr() const
Definition Ownership.h:91
PtrTy get() const
Definition Ownership.h:81
static OpaquePtr make(DeclGroupRef P)
Definition Ownership.h:61
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1178
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition Expr.h:1228
void setIsUnique(bool V)
Definition Expr.h:1230
Represents a parameter to a function.
Definition Decl.h:1790
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
Definition Decl.cpp:2946
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:5073
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
Definition Type.cpp:2867
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition TypeBase.h:8376
QualType withRestrict() const
Definition TypeBase.h:1175
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
Definition Type.cpp:3556
QualType withConst() const
Definition TypeBase.h:1159
void addConst()
Add the const type qualifier to this QualType.
Definition TypeBase.h:1156
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8287
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:8472
QualType getCanonicalType() const
Definition TypeBase.h:8339
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8381
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:8441
const Type * getTypePtrOrNull() const
Definition TypeBase.h:8291
Represents a struct/union/class.
Definition Decl.h:4312
field_range fields() const
Definition Decl.h:4515
field_iterator field_begin() const
Definition Decl.cpp:5201
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3573
Scope - A scope is a transient data structure that is used while parsing the program.
Definition Scope.h:41
bool isDeclScope(const Decl *D) const
isDeclScope - Return true if this is the scope that the specified decl is declared in.
Definition Scope.h:398
Scope * getBreakParent()
getBreakParent - Return the closest scope that a break statement would be affected by.
Definition Scope.h:322
bool isOpenMPOrderClauseScope() const
Determine whether this scope is some OpenMP directive with order clause which specifies concurrent sc...
Definition Scope.h:558
const Scope * getParent() const
getParent - Return the scope that this is nested in.
Definition Scope.h:287
bool isOpenMPLoopScope() const
Determine whether this scope is a loop having OpenMP loop directive attached.
Definition Scope.h:551
@ OpenMPOrderClauseScope
This is a scope of some OpenMP directive with order clause which specifies concurrent.
Definition Scope.h:150
A generic diagnostic builder for errors which may or may not be deferred.
Definition SemaBase.h:111
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition SemaBase.cpp:61
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
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 * ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'holds' clause.
StmtResult ActOnOpenMPParallelMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop simd' after parsing of the associated sta...
StmtResult ActOnOpenMPParallelMasterDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel master' after parsing of the associated statement.
StmtResult ActOnOpenMPDispatchDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp dispatch' after parsing of the.
OMPClause * ActOnOpenMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'read' clause.
OMPClause * ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'filter' clause.
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)
Finish current declare reduction construct initializer.
ExprResult ActOnOpenMPCall(ExprResult Call, Scope *Scope, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig)
Given the potential call expression Call, determine if there is a specialization via the OpenMP decla...
void setOpenMPDeviceNum(int Num)
Setter and getter functions for device_num.
OMPClause * ActOnOpenMPFullClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-form 'full' clauses.
StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target enter data' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'detach' clause.
OMPClause * ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'use' clause.
OMPClause * ActOnOpenMPFailClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'fail' clause.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for simd' after parsing of the as...
StmtResult ActOnOpenMPAssumeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Process an OpenMP assume directive.
void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called once a target context is completed, that can be when a 'pragma omp end declare target' was enc...
OMPClause * ActOnOpenMPDirectivePresenceClause(OpenMPClauseKind CK, llvm::ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
Called on well-formed 'absent' or 'contains' clauses.
void tryCaptureOpenMPLambdas(ValueDecl *V)
Function tries to capture lambda's captured variables in the OpenMP region before the original lambda...
OMPClause * ActOnOpenMPToClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'to' clause.
StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel masked' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for' after parsing of the associa...
OMPClause * ActOnOpenMPPrivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'private' clause.
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, SourceLocation StartLoc, DeclarationName VN)
Build the mapper variable of 'pragma omp declare mapper'.
OMPClause * ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc, SourceLocation LParenLoc=SourceLocation(), Expr *NumForLoops=nullptr)
Called on well-formed 'ordered' clause.
OMPClause * ActOnOpenMPSelfMapsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'self_maps' clause.
bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, OpenMPLinearClauseKind LinKind, QualType Type, bool IsDeclareSimd=false)
Checks that the specified declaration matches requirements for the linear decls.
OMPClause * ActOnOpenMPIsDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'is_device_ptr' clause.
OMPClause * ActOnOpenMPHasDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'has_device_addr' clause.
StmtResult ActOnOpenMPErrorDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, bool InExContext=true)
Called on well-formed '#pragma omp error'.
OMPClause * ActOnOpenMPPartialClause(Expr *FactorExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'partial' clauses.
StmtResult ActOnOpenMPSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPLastprivateClause(ArrayRef< Expr * > VarList, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'lastprivate' clause.
void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT, DeclareTargetContextInfo &DTCI)
Called on correct id-expression from the 'pragma omp declare target'.
DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef< OMPClause * > ClauseList)
Called on well-formed 'pragma omp requires'.
OMPGroupPrivateDecl * CheckOMPGroupPrivateDecl(SourceLocation Loc, ArrayRef< Expr * > VarList)
Builds a new OpenMPGroupPrivateDecl and checks its correctness.
StmtResult ActOnOpenMPDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPFirstprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'firstprivate' clause.
StmtResult ActOnOpenMPDepobjDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp depobj'.
ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK, ExprObjectKind OK, SourceLocation Loc)
OMPClause * ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'priority' clause.
OMPClause * ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, ArrayRef< unsigned > Arguments, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, ArrayRef< SourceLocation > ArgumentsLoc, SourceLocation DelimLoc, SourceLocation EndLoc)
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< Expr * > AdjustArgsNothing, ArrayRef< Expr * > AdjustArgsNeedDevicePtr, ArrayRef< Expr * > AdjustArgsNeedDeviceAddr, ArrayRef< OMPInteropInfo > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)
Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.
StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target parallel' after parsing of the associated statement.
OMPClause * ActOnOpenMPDistScheduleClause(OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'dist_schedule' clause.
OpenMPClauseKind isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, unsigned CapLevel) const
Check if the specified variable is used in 'private' clause.
OMPClause * ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nowait' 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 * ActOnOpenMPFromClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'from' clause.
OMPClause * ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'bind' clause.
OMPClause * ActOnOpenMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'threads' clause.
OMPClause * ActOnOpenMPThreadLimitClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'thread_limit' clause.
OMPClause * ActOnOpenMPSharedClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'shared' clause.
StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target exit data' after parsing of the associated statement.
StmtResult ActOnOpenMPTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPCopyinClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyin' clause.
OMPClause * ActOnOpenMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'mergeable' clause.
void startOpenMPCXXRangeFor()
If the current region is a range loop-based region, mark the start of the loop construct.
OMPClause * ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'destroy' clause.
StmtResult ActOnOpenMPParallelMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop' after parsing of the associated statemen...
OMPClause * ActOnOpenMPAffinityClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Called on well-formed 'affinity' clause.
OMPClause * ActOnOpenMPCompareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'compare' clause.
StmtResult ActOnOpenMPFuseDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp fuse' after parsing of its clauses and the associated statement.
OMPClause * ActOnOpenMPNumTeamsClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_teams' clause.
StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel sections' after parsing of the associated statement.
OMPClause * ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'update' clause.
OMPClause * ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data, Expr *DepModifier, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depend' clause.
OMPClause * ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'doacross' clause.
VarDecl * ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
StmtResult ActOnOpenMPTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for' after parsing of the associated sta...
StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp master' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskgroup'.
VarDecl * isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo=false, unsigned StopAt=0)
Check if the specified variable is used in one of the private clauses (private, firstprivate,...
StmtResult ActOnOpenMPMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop simd' after parsing of the associated statement.
friend class Sema
Definition SemaOpenMP.h:53
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id, OpenMPDirectiveKind Kind)
Called on correct id-expression from the 'pragma omp threadprivate'.
void ActOnOpenMPEndAssumesDirective()
Called on well-formed 'pragma omp end assumes'.
OMPClause * ActOnOpenMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nogroup' clause.
OMPClause * ActOnOpenMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier, Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'grainsize' clause.
ExprResult ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, Expr *LowerBound, SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length, Expr *Stride, SourceLocation RBLoc)
bool isOpenMPRebuildMemberExpr(ValueDecl *D)
The member expression(this->fd) needs to be rebuilt in the template instantiation to generate private...
void ActOnOpenMPDeviceNum(Expr *DeviceNumExpr)
Called on device_num selector in context selectors.
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
StmtResult ActOnOpenMPMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop simd' after parsing of the associated statement.
bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, unsigned OpenMPCaptureLevel) const
Return true if the provided declaration VD should be captured by reference.
StmtResult ActOnOpenMPParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel loop' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)
Called on well-formed 'pragma omp allocate'.
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind)
Return the number of captured regions created for an OpenMP directive.
bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified variable is captured by 'target' directive.
StmtResult ActOnOpenMPParallelMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop simd' after parsing of the associated sta...
OMPClause * ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'dynamic_allocators' clause.
StmtResult ActOnOpenMPScopeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scope' after parsing of the associated statement.
void ActOnOpenMPIteratorVarDecl(VarDecl *VD)
bool isInOpenMPDeclareVariantScope() const
Can we exit an OpenMP declare variant scope at the moment.
Definition SemaOpenMP.h:111
StmtResult ActOnOpenMPDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for simd' after parsing of the associated stat...
StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp barrier'.
TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D)
Check variable declaration in 'omp declare mapper' construct.
ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc, SourceLocation LLoc, SourceLocation RLoc, ArrayRef< OMPIteratorData > Data)
OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)
Called on well-formed 'uses_allocators' clause.
StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)
End of OpenMP region.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart(Scope *S, DeclContext *DC, DeclarationName Name, ArrayRef< std::pair< QualType, SourceLocation > > ReductionTypes, AccessSpecifier AS, Decl *PrevDeclInScope=nullptr)
Called on start of 'pragma omp declare reduction'.
OMPClause * ActOnOpenMPAcqRelClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acq_rel' clause.
OMPClause * ActOnOpenMPAllocatorClause(Expr *Allocator, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocator' clause.
ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind, bool StrictlyPositive=true, bool SuppressExprDiags=false)
DeclGroupPtrTy ActOnOpenMPGroupPrivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed 'pragma omp groupprivate'.
bool isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const
OMPClause * ActOnOpenMPInclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'inclusive' clause.
SemaDiagnosticBuilder diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as host cod...
SemaDiagnosticBuilder diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as device c...
StmtResult ActOnOpenMPSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp sections' after parsing of the associated statement.
void ActOnOpenMPEndDeclareVariant()
Handle a omp end declare variant.
OMPClause * ActOnOpenMPTaskReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions={})
Called on well-formed 'task_reduction' clause.
StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp critical' after parsing of the associated statement.
StmtResult ActOnOpenMPMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp masked' after parsing of the.
StmtResult ActOnOpenMPStripeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
void ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D)
Act on D, a function definition inside of an omp [begin/end] assumes.
void EndOpenMPDSABlock(Stmt *CurDirective)
Called on end of data sharing attribute block.
OMPClause * ActOnOpenMPOrderClause(OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'order' clause.
llvm::SmallDenseMap< const ValueDecl *, const Expr *, 4 > VarsWithInheritedDSAType
Definition SemaOpenMP.h:436
OMPClause * ActOnOpenMPSizesClause(ArrayRef< Expr * > SizeExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'sizes' clause.
bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called on the start of target region i.e. 'pragma omp declare target'.
StmtResult ActOnOpenMPTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for simd' after parsing of the associate...
OMPClause * ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'device' clause.
StmtResult ActOnOpenMPDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute' after parsing of the associated statement.
StmtResult ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp section' after parsing of the associated statement.
StmtResult ActOnOpenMPInterchangeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp interchange' after parsing of its clauses and the associated statem...
bool isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified global variable must be captured by outer capture regions.
OMPClause * ActOnOpenMPInReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions={})
Called on well-formed 'in_reduction' clause.
StmtResult ActOnOpenMPGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPFlushClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'flush' pseudo clause.
OMPRequiresDecl * CheckOMPRequiresDecl(SourceLocation Loc, ArrayRef< OMPClause * > Clauses)
Check restrictions on Requires directive.
void ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(Decl *D, SmallVectorImpl< FunctionDecl * > &Bases)
Register D as specialization of all base functions in Bases in the current omp begin/end declare vari...
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
void EndOpenMPClause()
End analysis of clauses.
bool isInOpenMPAssumeScope() const
Check if there is an active global omp begin assumes directive.
Definition SemaOpenMP.h:249
void setOpenMPDeviceNumID(StringRef ID)
StmtResult ActOnOpenMPDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for' after parsing of the associated statement...
QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare mapper' construct.
StmtResult ActOnOpenMPTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPMessageClause(Expr *MS, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'message' clause.
int getOpenMPDeviceNum() const
StmtResult ActOnOpenMPScanDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scan'.
OMPClause * ActOnOpenMPScheduleClause(OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'schedule' clause.
void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init)
Check if the current region is an OpenMP loop region and if it is, mark loop control variable,...
OMPClause * ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
void DiagnoseUnterminatedOpenMPDeclareTarget()
Report unterminated 'omp declare target' or 'omp begin declare target' at the end of a compilation un...
void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, const FunctionDecl *Callee, SourceLocation Loc)
Finishes analysis of the deferred functions calls that may be declared as host/nohost during device/h...
OMPClause * ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'simdlen' clause.
std::optional< std::pair< FunctionDecl *, Expr * > > checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, OMPTraitInfo &TI, unsigned NumAppendArgs, SourceRange SR)
Checks '#pragma omp declare variant' variant function and original functions after parsing of the ass...
OMPClause * ActOnOpenMPUseDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_ptr' clause.
StmtResult ActOnOpenMPParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for simd' after parsing of the associated statement.
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
Definition SemaOpenMP.h:55
OMPClause * ActOnOpenMPReleaseClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'release' clause.
OMPClause * ActOnOpenMPAcquireClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acquire' clause.
OMPClause * ActOnOpenMPProcBindClause(llvm::omp::ProcBindKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'proc_bind' clause.
OMPClause * ActOnOpenMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'simd' clause.
OMPClause * ActOnOpenMPXBareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_bare' clause.
StmtResult ActOnOpenMPInformationalDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Process an OpenMP informational directive.
StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt)
Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to an OpenMP loop directive.
OMPClause * ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'hint' clause.
OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK, SourceLocation Loc, SourceLocation RLoc)
StmtResult ActOnOpenMPTargetTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute' after parsing of the associated statement...
StmtResult ActOnOpenMPParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for' after parsing of the associated statement.
OMPClause * ActOnOpenMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'capture' clause.
StmtResult ActOnOpenMPForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for' after parsing of the associated statement.
StmtResult ActOnOpenMPAtomicDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp atomic' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target update'.
StmtResult ActOnOpenMPOrderedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp ordered' after parsing of the associated statement.
StmtResult ActOnOpenMPReverseDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp reverse'.
ExprResult ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > Brackets)
OMPClause * ActOnOpenMPNumThreadsClause(OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'num_threads' clause.
OMPClause * ActOnOpenMPAtClause(OpenMPAtClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'at' clause.
StmtResult ActOnOpenMPTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop' after parsing of the associated statement.
OMPClause * ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'init' clause.
OMPClause * ActOnOpenMPUseDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_addr' clause.
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
OMPClause * ActOnOpenMPAllocateClause(Expr *Allocator, Expr *Alignment, OpenMPAllocateClauseModifier FirstModifier, SourceLocation FirstModifierLoc, OpenMPAllocateClauseModifier SecondModifier, SourceLocation SecondModifierLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocate' clause.
std::pair< StringRef, QualType > CapturedParamNameType
Definition SemaOpenMP.h:56
OMPClause * ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'final' clause.
bool isInOpenMPTargetExecutionDirective() const
Return true inside OpenMP target region.
StmtResult ActOnOpenMPTargetDataDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target data' after parsing of the associated statement.
StmtResult ActOnOpenMPMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop' after parsing of the associated statement.
void ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, SmallVectorImpl< FunctionDecl * > &Bases)
The declarator D defines a function in the scope S which is nested in an omp begin/end declare varian...
StmtResult ActOnOpenMPFlushDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp flush'.
StmtResult ActOnOpenMPUnrollDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp unroll' after parsing of its clauses and the associated statement.
OMPClause * ActOnOpenMPMapClause(Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapTypeModifiers, ArrayRef< SourceLocation > MapTypeModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, bool NoDiagnose=false, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'map' clause.
OMPClause * ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'num_tasks' clause.
void ActOnOpenMPDeclareTargetInitializer(Decl *D)
Adds OMPDeclareTargetDeclAttr to referenced variables in declare target directive.
bool isInOpenMPDeclareTargetContext() const
Return true inside OpenMP declare target region.
Definition SemaOpenMP.h:377
StmtResult ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancellation point'.
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.
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:1289
Expr * get() const
Definition Sema.h:7724
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition Sema.h:12425
Abstract base class used for diagnosing integer constant expression violations.
Definition Sema.h:7675
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:853
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition Sema.h:1119
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:9290
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
Definition Sema.h:9331
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
Definition Sema.h:9333
@ LookupAnyName
Look up any declaration with any name.
Definition Sema.h:9335
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:1504
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
Definition Sema.h:4728
@ AR_inaccessible
Definition Sema.h:1658
Scope * getScopeForContext(DeclContext *Ctx)
Determines the active Scope associated with the given declaration context.
Definition Sema.cpp:2311
FPOptionsOverride CurFPFeatureOverrides()
Definition Sema.h:2048
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:1282
void ActOnCapturedRegionError()
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
Definition SemaDecl.cpp:75
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:748
ASTContext & getASTContext() const
Definition Sema.h:924
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:9283
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition Sema.h:1190
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:917
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:1281
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:1280
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
Definition Sema.cpp:2557
llvm::SmallSetVector< DeclContext *, 16 > AssociatedNamespaceSet
Definition Sema.h:9282
DeclContext * getCurLexicalContext() const
Definition Sema.h:1123
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:633
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
Definition Sema.h:15345
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
Definition Sema.cpp:2512
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition Sema.h:1417
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:15300
void setFunctionHasBranchProtectedScope()
Definition Sema.cpp:2497
std::pair< StringRef, QualType > CapturedParamNameType
Definition Sema.h:11178
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:270
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:6705
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
Definition Sema.h:6674
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
Definition SemaStmt.cpp:75
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
Definition Sema.h:1245
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:2096
sema::CapturedRegionScopeInfo * getCurCapturedRegion()
Retrieve the current captured region, if any.
Definition Sema.cpp:2886
bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation=false, bool ForceNoCPlusPlus=false)
Perform unqualified name lookup starting from a given scope.
static QualType GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo=nullptr)
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
Definition SemaStmt.cpp:436
FullExprArg MakeFullExpr(Expr *Arg)
Definition Sema.h:7738
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition Sema.h:8608
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
void setBegin(SourceLocation b)
SourceLocation getBegin() const
void setEnd(SourceLocation e)
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
Definition Stmt.h:85
SourceLocation getEndLoc() const LLVM_READONLY
Definition Stmt.cpp:358
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:295
StmtClass getStmtClass() const
Definition Stmt.h:1472
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:334
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical, bool ProfileLambdaExpr=false) const
Produce a unique representation of the given statement.
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
Definition Stmt.cpp:205
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:346
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4881
bool isTLSSupported() const
Whether the target supports thread-local storage.
A semantic tree transformation that allows one to transform one abstract syntax tree into another.
Represents a declaration of a type.
Definition Decl.h:3513
SourceLocation getBeginLoc() const
Get the begin source location.
Definition TypeLoc.cpp:193
A container of type source information.
Definition TypeBase.h:8258
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition TypeLoc.h:272
QualType getType() const
Return the type wrapped by this type source info.
Definition TypeBase.h:8269
The base class of the type hierarchy.
Definition TypeBase.h:1833
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
Definition TypeBase.h:9060
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:8627
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
Definition Type.cpp:2066
bool isArrayType() const
Definition TypeBase.h:8623
bool isArithmeticType() const
Definition Type.cpp:2337
bool isPointerType() const
Definition TypeBase.h:8524
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:8924
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9167
bool isReferenceType() const
Definition TypeBase.h:8548
bool isEnumeralType() const
Definition TypeBase.h:8655
bool isScalarType() const
Definition TypeBase.h:8982
bool isVariableArrayType() const
Definition TypeBase.h:8635
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
Definition Type.cpp:2103
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:752
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
Definition Type.cpp:2291
bool isAnyCharacterType() const
Determine whether this type is any of the built-in character types.
Definition Type.cpp:2168
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
Definition TypeBase.h:8874
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition TypeBase.h:2790
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition TypeBase.h:8849
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition TypeBase.h:2782
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
Definition Type.cpp:2411
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
bool isAnyComplexType() const
Definition TypeBase.h:8659
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
Definition TypeBase.h:2405
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition Type.cpp:2243
bool isFunctionProtoType() const
Definition TypeBase.h:2601
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
Definition TypeBase.h:9023
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2800
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition TypeBase.h:9153
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition Type.cpp:2436
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
Definition TypeBase.h:9117
bool isFunctionType() const
Definition TypeBase.h:8520
bool isStructureOrClassType() const
Definition Type.cpp:706
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2320
bool isFloatingType() const
Definition Type.cpp:2304
bool isAnyPointerType() const
Definition TypeBase.h:8532
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9100
bool isRecordType() const
Definition TypeBase.h:8651
bool isUnionType() const
Definition Type.cpp:718
bool isFunctionNoProtoType() const
Definition TypeBase.h:2600
Simple class containing the result of Sema::CorrectTypo.
NamedDecl * getCorrectionDecl() const
Gets the pointer to the declaration of the typo correction.
Expr * getSubExpr() const
Definition Expr.h:2285
Opcode getOpcode() const
Definition Expr.h:2280
static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent, bool KnownInstantiationDependent)
Definition ExprCXX.cpp:432
void append(iterator I, iterator E)
void addDecl(NamedDecl *D)
A set of unresolved declarations.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:712
void setType(QualType newType)
Definition Decl.h:724
QualType getType() const
Definition Decl.h:723
VarDecl * getPotentiallyDecomposedVarDecl()
Definition DeclCXX.cpp:3582
const Expr * getExprStmt() const
Definition Stmt.cpp:411
Represents a variable declaration or definition.
Definition Decl.h:926
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition Decl.cpp:2151
bool isFunctionOrMethodVarDecl() const
Similar to isLocalVarDecl, but excludes variables declared in blocks.
Definition Decl.h:1267
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition Decl.h:1569
TLSKind getTLSKind() const
Definition Decl.cpp:2168
bool hasInit() const
Definition Decl.cpp:2398
void setInitStyle(InitializationStyle Style)
Definition Decl.h:1452
InitializationStyle getInitStyle() const
The style of initialization for this declaration.
Definition Decl.h:1466
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
Definition Decl.cpp:2260
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2190
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition Decl.cpp:2257
@ CInit
C-style initialization with assignment.
Definition Decl.h:931
@ CallInit
Call-style initialization (C++98)
Definition Decl.h:934
bool isStaticDataMember() const
Determines whether this is a static data member.
Definition Decl.h:1283
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1226
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition Decl.h:1208
bool isFileVarDecl() const
Returns true for file scoped variable declaration.
Definition Decl.h:1342
const Expr * getInit() const
Definition Decl.h:1368
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition Decl.h:1184
@ TLS_None
Not a TLS variable.
Definition Decl.h:946
void setInit(Expr *I)
Definition Decl.cpp:2477
@ DeclarationOnly
This declaration is only a declaration.
Definition Decl.h:1295
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
Definition Decl.h:1253
bool isDirectInit() const
Whether the initializer is a direct-initializer (list or call).
Definition Decl.h:1471
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
Definition Decl.h:1229
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition Decl.h:1168
bool isUsableInConstantExpressions(const ASTContext &C) const
Determine whether this variable's value can be used in a constant expression, according to the releva...
Definition Decl.cpp:2528
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
Definition Decl.h:1262
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Definition Decl.h:1358
Retains information about a captured region.
Definition ScopeInfo.h:816
Retains information about a function, method, or block that is currently being parsed.
Definition ScopeInfo.h:104
SmallVector< CompoundScopeInfo, 4 > CompoundScopes
The stack of currently active compound statement scopes in the function.
Definition ScopeInfo.h:228
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
Defines the clang::TargetInfo interface.
Definition SPIR.cpp:47
VE builtins.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
bool LE(InterpState &S, CodePtr OpPC)
Definition Interp.h:1274
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
OpenMPOriginalSharingModifier
OpenMP 6.0 original sharing modifiers.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
@ NUM_OVERLOADED_OPERATORS
bool isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a teams directive in the outermost n...
bool isa(CodeGen::Address addr)
Definition Address.h:330
bool checkFailClauseParameter(OpenMPClauseKind FailClauseParameter)
Checks if the parameter to the fail clause in "#pragma atomic compare fail" is restricted only to mem...
@ CPlusPlus
MutableArrayRef< TemplateParameterList * > MultiTemplateParamsArg
Definition Ownership.h:263
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
OpenMPDefaultClauseVariableCategory
OpenMP variable-category for 'default' clause.
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:664
ExprObjectKind
A further classification of the kind of object referenced by an l-value or x-value.
Definition Specifiers.h:149
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition Specifiers.h:151
OpenMPAtClauseKind
OpenMP attributes for 'at' clause.
@ OMPC_AT_unknown
Expr * AssertSuccess(ExprResult R)
Definition Ownership.h:275
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
Definition Lambda.h:37
@ LCK_This
Capturing the *this object by reference.
Definition Lambda.h:34
OpenMPReductionClauseModifier
OpenMP modifiers for 'reduction' clause.
@ OMPC_REDUCTION_unknown
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
Definition OpenMPKinds.h:39
@ OMPC_SCHEDULE_MODIFIER_last
Definition OpenMPKinds.h:44
@ OMPC_SCHEDULE_MODIFIER_unknown
Definition OpenMPKinds.h:40
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
Definition Specifiers.h:123
@ AS_public
Definition Specifiers.h:124
@ AS_none
Definition Specifiers.h:127
SmallVector< Attr *, 4 > AttrVec
AttrVec - A vector of Attr, which is how they are stored on the AST.
ActionResult< Decl * > DeclResult
Definition Ownership.h:255
const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ CR_Default
@ CR_OpenMP
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
bool isOpenMPPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of private clauses like 'private', 'firstprivate',...
@ SC_Auto
Definition Specifiers.h:256
@ SC_Register
Definition Specifiers.h:257
@ SC_None
Definition Specifiers.h:250
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
@ OMPC_DIST_SCHEDULE_unknown
Expr * Cond
};
static constexpr StringRef getOpenMPVariantManglingSeparatorStr()
OpenMP variants are mangled early based on their OpenMP context selector.
Definition Decl.h:5367
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.
MutableArrayRef< Expr * > MultiExprArg
Definition Ownership.h:259
StmtResult StmtError()
Definition Ownership.h:266
@ SD_Static
Static storage duration.
Definition Specifiers.h:343
@ Parameter
The parameter type of a method or function.
Definition TypeBase.h:908
@ Result
The result type of a method or function.
Definition TypeBase.h:905
ActionResult< ParsedType > TypeResult
Definition Ownership.h:251
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
@ OMPC_BIND_unknown
const FunctionProtoType * T
OpenMPLastprivateModifier
OpenMP 'lastprivate' clause modifier.
@ OMPC_LASTPRIVATE_unknown
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
Definition OpenMPKinds.h:55
@ OMPC_DEPEND_unknown
Definition OpenMPKinds.h:59
bool isOpenMPCanonicalLoopSequenceTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive that applies to a canonical loop...
OpenMPGrainsizeClauseModifier
@ OMPC_GRAINSIZE_unknown
bool IsXLHSInRHSPart
True if UE has the first form and false if the second.
bool IsPostfixUpdate
True if original value of 'x' must be stored in 'v', not an updated one.
bool isOpenMPCanonicalLoopNestTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive that applies to a canonical loop...
OpenMPNumTasksClauseModifier
@ OMPC_NUMTASKS_unknown
ExprResult ExprError()
Definition Ownership.h:265
bool isOpenMPOrderConcurrentNestableDirective(OpenMPDirectiveKind DKind, const LangOptions &LangOpts)
Checks if the specified directive is an order concurrent nestable directive that can be nested within...
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
bool isOpenMPCapturingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive can capture variables.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
@ OMPC_SEVERITY_unknown
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
static constexpr unsigned NumberOfOMPMotionModifiers
Number of allowed motion-modifiers.
OpenMPMotionModifierKind
OpenMP modifier kind for 'to' or 'from' clause.
Definition OpenMPKinds.h:92
@ OMPC_MOTION_MODIFIER_unknown
Definition OpenMPKinds.h:96
OpenMPDefaultmapClauseKind
OpenMP attributes for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_unknown
OpenMPAllocateClauseModifier
OpenMP modifiers for 'allocate' clause.
@ OMPC_ALLOCATE_unknown
bool isOpenMPThreadPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of threadprivate clauses like 'threadprivate',...
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
Definition OpenMPKinds.h:63
@ OMPC_LINEAR_unknown
Definition OpenMPKinds.h:67
bool isOpenMPExecutableDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "executable".
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
Definition OpenMPKinds.h:25
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
bool isOpenMPInformationalDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "informational".
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
Definition Specifiers.h:132
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition Specifiers.h:135
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition Specifiers.h:139
SmallVector< CXXBaseSpecifier *, 4 > CXXCastPath
A simple array of base specifiers.
Definition ASTContext.h:149
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_NUMTHREADS_unknown
OpenMPAtomicDefaultMemOrderClauseKind
OpenMP attributes for 'atomic_default_mem_order' clause.
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
bool IsFailOnly
True if 'v' is updated only when the condition is false (compare capture only).
U cast(CodeGen::Address addr)
Definition Address.h:327
OpenMPDeviceClauseModifier
OpenMP modifiers for 'device' clause.
Definition OpenMPKinds.h:48
@ OMPC_DEVICE_unknown
Definition OpenMPKinds.h:51
OpaquePtr< QualType > ParsedType
An opaque type for threading parsed type information through the parser.
Definition Ownership.h:230
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
Definition OpenMPKinds.h:79
@ OMPC_MAP_MODIFIER_unknown
Definition OpenMPKinds.h:80
@ None
No keyword precedes the qualified type name.
Definition TypeBase.h:5886
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:437
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
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Definition OpenMPKinds.h:71
@ OMPC_MAP_unknown
Definition OpenMPKinds.h:75
@ NOUR_Unevaluated
This name appears in an unevaluated operand.
Definition Specifiers.h:177
unsigned long uint64_t
int const char * function
Definition c++config.h:31
#define false
Definition stdbool.h:26
#define true
Definition stdbool.h:25
unsigned operator()(argument_type DK)
OpenMPDirectiveKind argument_type
const Expr * RHS
The original right-hand side.
Definition ExprCXX.h:313
BinaryOperatorKind Opcode
The original opcode, prior to rewriting.
Definition ExprCXX.h:309
const Expr * LHS
The original left-hand side.
Definition ExprCXX.h:311
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
SourceLocation getLoc() const
getLoc - Returns the main location of the declaration name.
DeclarationName getName() const
getName - Returns the embedded declaration name.
void setLoc(SourceLocation L)
setLoc - Sets the main location of the declaration name.
void setName(DeclarationName N)
setName - Sets the embedded declaration name.
SourceLocation getBeginLoc() const
getBeginLoc - Retrieve the location of the first token.
std::string getAsString() const
getAsString - Retrieve the human-readable string for this name.
SourceLocation getEndLoc() const LLVM_READONLY
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:645
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:647
Extra information about a function prototype.
Definition TypeBase.h:5351
llvm::SmallVector< Expr *, 4 > PreferTypes
Iterator definition representation.
Definition ExprOpenMP.h:160
Helper expressions and declaration for OMPIteratorExpr class for each iteration space.
Definition ExprOpenMP.h:111
Expr * CounterUpdate
Updater for the internal counter: ++CounterVD;.
Definition ExprOpenMP.h:121
Expr * Upper
Normalized upper bound.
Definition ExprOpenMP.h:116
Expr * Update
Update expression for the originally specified iteration variable, calculated as VD = Begin + Counter...
Definition ExprOpenMP.h:119
VarDecl * CounterVD
Internal normalized counter.
Definition ExprOpenMP.h:113
Data for list of allocators.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Expr * AllocatorTraits
Allocator traits.
This structure contains most locations needed for by an OMPVarListClause.
SourceLocation StartLoc
Starting location of the clause (the clause keyword).
SourceLocation LParenLoc
Location of '('.
SourceLocation EndLoc
Ending location of the clause.
std::optional< Expr * > Indirect
The directive with indirect clause.
Definition SemaOpenMP.h:322
OpenMPDirectiveKind Kind
The directive kind, begin declare target or declare target.
Definition SemaOpenMP.h:319
OMPDeclareTargetDeclAttr::DevTypeTy DT
The 'device_type' as parsed from the clause.
Definition SemaOpenMP.h:316
SourceLocation Loc
The directive location.
Definition SemaOpenMP.h:325
llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped
Explicitly listed variables and functions in a 'to' or 'link' clause.
Definition SemaOpenMP.h:313
Data structure for iterator expression.
Data used for processing a list of variables in OpenMP clauses.
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Clang specific specialization of the OMPContext to lookup target features.