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() || !DVarTop.AppliedToPointee))
2494 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2495 // Threadprivate variables must not be captured.
2496 if (isOpenMPThreadPrivate(DVarTop.CKind))
2497 return nullptr;
2498 // The variable is not private or it is the variable in the directive with
2499 // default(none) clause and not used in any clause.
2500 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2501 D,
2502 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2503 return isOpenMPPrivate(C) && !AppliedToPointee;
2504 },
2505 [](OpenMPDirectiveKind) { return true; },
2506 DSAStack->isClauseParsingMode());
2507 // Global shared must not be captured.
2508 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2509 ((DSAStack->getDefaultDSA() != DSA_none &&
2510 DSAStack->getDefaultDSA() != DSA_private &&
2511 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2512 DVarTop.CKind == OMPC_shared))
2513 return nullptr;
2514 auto *FD = dyn_cast<FieldDecl>(D);
2515 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2516 !DVarPrivate.PrivateCopy) {
2517 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2518 D,
2519 [](OpenMPClauseKind C, bool AppliedToPointee,
2520 DefaultDataSharingAttributes DefaultAttr) {
2521 return isOpenMPPrivate(C) && !AppliedToPointee &&
2522 (DefaultAttr == DSA_firstprivate ||
2523 DefaultAttr == DSA_private);
2524 },
2525 [](OpenMPDirectiveKind) { return true; },
2526 DSAStack->isClauseParsingMode());
2527 if (DVarPrivate.CKind == OMPC_unknown)
2528 return nullptr;
2529
2530 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2531 if (VD)
2532 return VD;
2533 if (SemaRef.getCurrentThisType().isNull())
2534 return nullptr;
2535 Expr *ThisExpr = SemaRef.BuildCXXThisExpr(SourceLocation(),
2536 SemaRef.getCurrentThisType(),
2537 /*IsImplicit=*/true);
2538 const CXXScopeSpec CS = CXXScopeSpec();
2539 Expr *ME = SemaRef.BuildMemberExpr(
2540 ThisExpr, /*IsArrow=*/true, SourceLocation(),
2543 /*HadMultipleCandidates=*/false, DeclarationNameInfo(), FD->getType(),
2546 SemaRef, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2547 SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2548 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2550 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2551 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2552 return VD;
2553 }
2554 if (DVarPrivate.CKind != OMPC_unknown ||
2555 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2556 DSAStack->getDefaultDSA() == DSA_private ||
2557 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2558 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2559 }
2560 return nullptr;
2561}
2562
2563void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2564 unsigned Level) const {
2565 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2566}
2567
2569 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2570 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2571 DSAStack->loopInit();
2572}
2573
2575 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2576 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2577 DSAStack->resetPossibleLoopCounter();
2578 DSAStack->loopStart();
2579 }
2580}
2581
2583 unsigned CapLevel) const {
2584 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2585 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2586 (!DSAStack->isClauseParsingMode() ||
2587 DSAStack->getParentDirective() != OMPD_unknown)) {
2588 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2589 D,
2590 [](OpenMPClauseKind C, bool AppliedToPointee,
2591 DefaultDataSharingAttributes DefaultAttr) {
2592 return isOpenMPPrivate(C) && !AppliedToPointee &&
2593 DefaultAttr == DSA_private;
2594 },
2595 [](OpenMPDirectiveKind) { return true; },
2596 DSAStack->isClauseParsingMode());
2597 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2598 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2599 !DSAStack->isLoopControlVariable(D).first)
2600 return OMPC_private;
2601 }
2602 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2603 bool IsTriviallyCopyable =
2605 getASTContext()) &&
2606 !D->getType()
2610 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2612 getOpenMPCaptureRegions(CaptureRegions, DKind);
2613 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2614 (IsTriviallyCopyable ||
2615 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2616 if (DSAStack->hasExplicitDSA(
2617 D,
2618 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2619 Level, /*NotLastprivate=*/true))
2620 return OMPC_firstprivate;
2621 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2622 if (DVar.CKind != OMPC_shared &&
2623 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2624 DSAStack->addImplicitTaskFirstprivate(Level, D);
2625 return OMPC_firstprivate;
2626 }
2627 }
2628 }
2629 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2630 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2631 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2632 DSAStack->resetPossibleLoopCounter(D);
2633 DSAStack->loopStart();
2634 return OMPC_private;
2635 }
2636 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2637 DSAStack->isLoopControlVariable(D).first) &&
2638 !DSAStack->hasExplicitDSA(
2639 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2640 Level) &&
2641 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2642 return OMPC_private;
2643 }
2644 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2645 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2646 DSAStack->isForceVarCapturing() &&
2647 !DSAStack->hasExplicitDSA(
2648 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2649 Level))
2650 return OMPC_private;
2651 }
2652 // User-defined allocators are private since they must be defined in the
2653 // context of target region.
2654 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2655 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2656 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2657 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2658 return OMPC_private;
2659 return (DSAStack->hasExplicitDSA(
2660 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2661 Level) ||
2662 (DSAStack->isClauseParsingMode() &&
2663 DSAStack->getClauseParsingMode() == OMPC_private) ||
2664 // Consider taskgroup reduction descriptor variable a private
2665 // to avoid possible capture in the region.
2666 (DSAStack->hasExplicitDirective(
2667 [](OpenMPDirectiveKind K) {
2668 return K == OMPD_taskgroup ||
2669 ((isOpenMPParallelDirective(K) ||
2670 isOpenMPWorksharingDirective(K)) &&
2671 !isOpenMPSimdDirective(K));
2672 },
2673 Level) &&
2674 DSAStack->isTaskgroupReductionRef(D, Level)))
2675 ? OMPC_private
2676 : OMPC_unknown;
2677}
2678
2680 unsigned Level) {
2681 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2682 D = getCanonicalDecl(D);
2683 OpenMPClauseKind OMPC = OMPC_unknown;
2684 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2685 const unsigned NewLevel = I - 1;
2686 if (DSAStack->hasExplicitDSA(
2687 D,
2688 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2689 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2690 OMPC = K;
2691 return true;
2692 }
2693 return false;
2694 },
2695 NewLevel))
2696 break;
2697 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2698 D, NewLevel,
2700 OpenMPClauseKind) { return true; })) {
2701 OMPC = OMPC_map;
2702 break;
2703 }
2704 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2705 NewLevel)) {
2706 OMPC = OMPC_map;
2707 if (DSAStack->mustBeFirstprivateAtLevel(
2709 OMPC = OMPC_firstprivate;
2710 break;
2711 }
2712 }
2713 if (OMPC != OMPC_unknown)
2714 FD->addAttr(
2715 OMPCaptureKindAttr::CreateImplicit(getASTContext(), unsigned(OMPC)));
2716}
2717
2719 unsigned CaptureLevel) const {
2720 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2721 // Return true if the current level is no longer enclosed in a target region.
2722
2724 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2725 const auto *VD = dyn_cast<VarDecl>(D);
2726 return VD && !VD->hasLocalStorage() &&
2727 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2728 Level) &&
2729 Regions[CaptureLevel] != OMPD_task;
2730}
2731
2733 unsigned CaptureLevel) const {
2734 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2735 // Return true if the current level is no longer enclosed in a target region.
2736
2737 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2738 if (!VD->hasLocalStorage()) {
2740 return true;
2741 DSAStackTy::DSAVarData TopDVar =
2742 DSAStack->getTopDSA(D, /*FromParent=*/false);
2743 unsigned NumLevels =
2744 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2745 if (Level == 0)
2746 // non-file scope static variable with default(firstprivate)
2747 // should be global captured.
2748 return (NumLevels == CaptureLevel + 1 &&
2749 (TopDVar.CKind != OMPC_shared ||
2750 DSAStack->getDefaultDSA() == DSA_firstprivate));
2751 do {
2752 --Level;
2753 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2754 if (DVar.CKind != OMPC_shared)
2755 return true;
2756 } while (Level > 0);
2757 }
2758 }
2759 return true;
2760}
2761
2762void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2763
2765 OMPTraitInfo &TI) {
2766 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2767}
2768
2771 "Not in OpenMP declare variant scope!");
2772
2773 OMPDeclareVariantScopes.pop_back();
2774}
2775
2777 const FunctionDecl *Callee,
2778 SourceLocation Loc) {
2779 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2780 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2781 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2782 // Ignore host functions during device analysis.
2783 if (getLangOpts().OpenMPIsTargetDevice &&
2784 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2785 return;
2786 // Ignore nohost functions during host analysis.
2787 if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2788 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2789 return;
2790 const FunctionDecl *FD = Callee->getMostRecentDecl();
2791 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2792 if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2793 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2794 // Diagnose host function called during device codegen.
2795 StringRef HostDevTy =
2796 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2797 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2798 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2799 diag::note_omp_marked_device_type_here)
2800 << HostDevTy;
2801 return;
2802 }
2803 if (!getLangOpts().OpenMPIsTargetDevice &&
2804 !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2805 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2806 // In OpenMP 5.2 or later, if the function has a host variant then allow
2807 // that to be called instead
2808 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2809 for (OMPDeclareVariantAttr *A :
2810 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2811 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2812 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2813 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2814 OMPDeclareTargetDeclAttr::getDeviceType(
2815 VariantFD->getMostRecentDecl());
2816 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2817 return true;
2818 }
2819 return false;
2820 };
2821 if (getLangOpts().OpenMP >= 52 &&
2822 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2823 return;
2824 // Diagnose nohost function called during host codegen.
2825 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2826 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2827 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2828 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2829 diag::note_omp_marked_device_type_here)
2830 << NoHostDevTy;
2831 }
2832}
2833
2835 const DeclarationNameInfo &DirName,
2836 Scope *CurScope, SourceLocation Loc) {
2837 DSAStack->push(DKind, DirName, CurScope, Loc);
2838 SemaRef.PushExpressionEvaluationContext(
2840}
2841
2843 DSAStack->setClauseParsingMode(K);
2844}
2845
2847 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2848 SemaRef.CleanupVarDeclMarking();
2849}
2850
2851static std::pair<ValueDecl *, bool>
2852getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2853 SourceRange &ERange, bool AllowArraySection = false,
2854 bool AllowAssumedSizeArray = false, StringRef DiagType = "");
2855
2856/// Check consistency of the reduction clauses.
2857static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2858 ArrayRef<OMPClause *> Clauses) {
2859 bool InscanFound = false;
2860 SourceLocation InscanLoc;
2861 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2862 // A reduction clause without the inscan reduction-modifier may not appear on
2863 // a construct on which a reduction clause with the inscan reduction-modifier
2864 // appears.
2865 for (OMPClause *C : Clauses) {
2866 if (C->getClauseKind() != OMPC_reduction)
2867 continue;
2868 auto *RC = cast<OMPReductionClause>(C);
2869 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2870 InscanFound = true;
2871 InscanLoc = RC->getModifierLoc();
2872 continue;
2873 }
2874 if (RC->getModifier() == OMPC_REDUCTION_task) {
2875 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2876 // A reduction clause with the task reduction-modifier may only appear on
2877 // a parallel construct, a worksharing construct or a combined or
2878 // composite construct for which any of the aforementioned constructs is a
2879 // constituent construct and simd or loop are not constituent constructs.
2880 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2881 if (!(isOpenMPParallelDirective(CurDir) ||
2883 isOpenMPSimdDirective(CurDir))
2884 S.Diag(RC->getModifierLoc(),
2885 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2886 continue;
2887 }
2888 }
2889 if (InscanFound) {
2890 for (OMPClause *C : Clauses) {
2891 if (C->getClauseKind() != OMPC_reduction)
2892 continue;
2893 auto *RC = cast<OMPReductionClause>(C);
2894 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2895 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2896 ? RC->getBeginLoc()
2897 : RC->getModifierLoc(),
2898 diag::err_omp_inscan_reduction_expected);
2899 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2900 continue;
2901 }
2902 for (Expr *Ref : RC->varlist()) {
2903 assert(Ref && "NULL expr in OpenMP reduction clause.");
2904 SourceLocation ELoc;
2905 SourceRange ERange;
2906 Expr *SimpleRefExpr = Ref;
2907 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2908 /*AllowArraySection=*/true);
2909 ValueDecl *D = Res.first;
2910 if (!D)
2911 continue;
2912 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2913 S.Diag(Ref->getExprLoc(),
2914 diag::err_omp_reduction_not_inclusive_exclusive)
2915 << Ref->getSourceRange();
2916 }
2917 }
2918 }
2919 }
2920}
2921
2922static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2923 ArrayRef<OMPClause *> Clauses);
2924static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2925 bool WithInit);
2926
2927static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2928 const ValueDecl *D,
2929 const DSAStackTy::DSAVarData &DVar,
2930 bool IsLoopIterVar = false);
2931
2933 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2934 // A variable of class type (or array thereof) that appears in a lastprivate
2935 // clause requires an accessible, unambiguous default constructor for the
2936 // class type, unless the list item is also specified in a firstprivate
2937 // clause.
2938
2939 auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) {
2940 SmallVector<Expr *, 8> PrivateCopies;
2941 for (Expr *DE : Clause->varlist()) {
2942 if (DE->isValueDependent() || DE->isTypeDependent()) {
2943 PrivateCopies.push_back(nullptr);
2944 continue;
2945 }
2946 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2947 auto *VD = cast<VarDecl>(DRE->getDecl());
2949 const DSAStackTy::DSAVarData DVar =
2950 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2951 if (DVar.CKind != OMPC_lastprivate) {
2952 // The variable is also a firstprivate, so initialization sequence
2953 // for private copy is generated already.
2954 PrivateCopies.push_back(nullptr);
2955 continue;
2956 }
2957 // Generate helper private variable and initialize it with the
2958 // default value. The address of the original variable is replaced
2959 // by the address of the new private variable in CodeGen. This new
2960 // variable is not added to IdResolver, so the code in the OpenMP
2961 // region uses original variable for proper diagnostics.
2962 VarDecl *VDPrivate = buildVarDecl(
2963 SemaRef, DE->getExprLoc(), Type.getUnqualifiedType(), VD->getName(),
2964 VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2965 SemaRef.ActOnUninitializedDecl(VDPrivate);
2966 if (VDPrivate->isInvalidDecl()) {
2967 PrivateCopies.push_back(nullptr);
2968 continue;
2969 }
2970 PrivateCopies.push_back(buildDeclRefExpr(
2971 SemaRef, VDPrivate, DE->getType(), DE->getExprLoc()));
2972 }
2973 Clause->setPrivateCopies(PrivateCopies);
2974 };
2975
2976 auto FinalizeNontemporal = [&](OMPNontemporalClause *Clause) {
2977 // Finalize nontemporal clause by handling private copies, if any.
2978 SmallVector<Expr *, 8> PrivateRefs;
2979 for (Expr *RefExpr : Clause->varlist()) {
2980 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2981 SourceLocation ELoc;
2982 SourceRange ERange;
2983 Expr *SimpleRefExpr = RefExpr;
2984 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
2985 if (Res.second)
2986 // It will be analyzed later.
2987 PrivateRefs.push_back(RefExpr);
2988 ValueDecl *D = Res.first;
2989 if (!D)
2990 continue;
2991
2992 const DSAStackTy::DSAVarData DVar =
2993 DSAStack->getTopDSA(D, /*FromParent=*/false);
2994 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2995 : SimpleRefExpr);
2996 }
2997 Clause->setPrivateRefs(PrivateRefs);
2998 };
2999
3000 auto FinalizeAllocators = [&](OMPUsesAllocatorsClause *Clause) {
3001 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
3002 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
3003 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
3004 if (!DRE)
3005 continue;
3006 ValueDecl *VD = DRE->getDecl();
3007 if (!VD || !isa<VarDecl>(VD))
3008 continue;
3009 DSAStackTy::DSAVarData DVar =
3010 DSAStack->getTopDSA(VD, /*FromParent=*/false);
3011 // OpenMP [2.12.5, target Construct]
3012 // Memory allocators that appear in a uses_allocators clause cannot
3013 // appear in other data-sharing attribute clauses or data-mapping
3014 // attribute clauses in the same construct.
3015 Expr *MapExpr = nullptr;
3016 if (DVar.RefExpr ||
3017 DSAStack->checkMappableExprComponentListsForDecl(
3018 VD, /*CurrentRegionOnly=*/true,
3019 [VD, &MapExpr](
3021 MapExprComponents,
3023 auto MI = MapExprComponents.rbegin();
3024 auto ME = MapExprComponents.rend();
3025 if (MI != ME &&
3026 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
3027 VD->getCanonicalDecl()) {
3028 MapExpr = MI->getAssociatedExpression();
3029 return true;
3030 }
3031 return false;
3032 })) {
3033 Diag(D.Allocator->getExprLoc(), diag::err_omp_allocator_used_in_clauses)
3034 << D.Allocator->getSourceRange();
3035 if (DVar.RefExpr)
3037 else
3038 Diag(MapExpr->getExprLoc(), diag::note_used_here)
3039 << MapExpr->getSourceRange();
3040 }
3041 }
3042 };
3043
3044 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
3045 for (OMPClause *C : D->clauses()) {
3046 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
3047 FinalizeLastprivate(Clause);
3048 } else if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
3049 FinalizeNontemporal(Clause);
3050 } else if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
3051 FinalizeAllocators(Clause);
3052 }
3053 }
3054 // Check allocate clauses.
3055 if (!SemaRef.CurContext->isDependentContext())
3056 checkAllocateClauses(SemaRef, DSAStack, D->clauses());
3057 checkReductionClauses(SemaRef, DSAStack, D->clauses());
3058 }
3059
3060 DSAStack->pop();
3063}
3064
3065static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
3066 Expr *NumIterations, Sema &SemaRef,
3067 Scope *S, DSAStackTy *Stack);
3068
3069static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
3070 OMPLoopBasedDirective::HelperExprs &B,
3071 DSAStackTy *Stack) {
3072 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
3073 "loop exprs were not built");
3074
3075 if (SemaRef.CurContext->isDependentContext())
3076 return false;
3077
3078 // Finalize the clauses that need pre-built expressions for CodeGen.
3079 for (OMPClause *C : Clauses) {
3080 auto *LC = dyn_cast<OMPLinearClause>(C);
3081 if (!LC)
3082 continue;
3083 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
3084 B.NumIterations, SemaRef,
3085 SemaRef.getCurScope(), Stack))
3086 return true;
3087 }
3088
3089 return false;
3090}
3091
3092namespace {
3093
3094class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3095private:
3096 Sema &SemaRef;
3097
3098public:
3099 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3100 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3101 NamedDecl *ND = Candidate.getCorrectionDecl();
3102 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3103 return VD->hasGlobalStorage() &&
3104 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3105 SemaRef.getCurScope());
3106 }
3107 return false;
3108 }
3109
3110 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3111 return std::make_unique<VarDeclFilterCCC>(*this);
3112 }
3113};
3114
3115class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3116private:
3117 Sema &SemaRef;
3118
3119public:
3120 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3121 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3122 NamedDecl *ND = Candidate.getCorrectionDecl();
3123 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3124 isa<FunctionDecl>(ND))) {
3125 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3126 SemaRef.getCurScope());
3127 }
3128 return false;
3129 }
3130
3131 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3132 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3133 }
3134};
3135
3136} // namespace
3137
3139 CXXScopeSpec &ScopeSpec,
3140 const DeclarationNameInfo &Id,
3141 OpenMPDirectiveKind Kind) {
3142 ASTContext &Context = getASTContext();
3143 unsigned OMPVersion = getLangOpts().OpenMP;
3145 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
3146 /*ObjectType=*/QualType(),
3147 /*AllowBuiltinCreation=*/true);
3148
3149 if (Lookup.isAmbiguous())
3150 return ExprError();
3151
3152 VarDecl *VD;
3153 if (!Lookup.isSingleResult()) {
3154 VarDeclFilterCCC CCC(SemaRef);
3155 if (TypoCorrection Corrected =
3156 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
3158 SemaRef.diagnoseTypo(
3159 Corrected,
3160 SemaRef.PDiag(Lookup.empty() ? diag::err_undeclared_var_use_suggest
3161 : diag::err_omp_expected_var_arg_suggest)
3162 << Id.getName());
3163 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3164 } else {
3165 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3166 : diag::err_omp_expected_var_arg)
3167 << Id.getName();
3168 return ExprError();
3169 }
3170 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3171 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3172 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3173 return ExprError();
3174 }
3175 Lookup.suppressDiagnostics();
3176
3177 // OpenMP [2.9.2, Syntax, C/C++]
3178 // Variables must be file-scope, namespace-scope, or static block-scope.
3179 if ((Kind == OMPD_threadprivate || Kind == OMPD_groupprivate) &&
3180 !VD->hasGlobalStorage()) {
3181 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3182 << getOpenMPDirectiveName(Kind, OMPVersion) << !VD->isStaticLocal();
3183 bool IsDecl =
3185 Diag(VD->getLocation(),
3186 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3187 << VD;
3188 return ExprError();
3189 }
3190
3191 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3192 NamedDecl *ND = CanonicalVD;
3193 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3194 // A threadprivate or groupprivate directive for file-scope variables must
3195 // appear outside any definition or declaration.
3196 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3197 !SemaRef.getCurLexicalContext()->isTranslationUnit()) {
3198 Diag(Id.getLoc(), diag::err_omp_var_scope)
3199 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3200 bool IsDecl =
3202 Diag(VD->getLocation(),
3203 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3204 << VD;
3205 return ExprError();
3206 }
3207 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3208 // A threadprivate or groupprivate directive for static class member
3209 // variables must appear in the class definition, in the same scope in which
3210 // the member variables are declared.
3211 if (CanonicalVD->isStaticDataMember() &&
3212 !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) {
3213 Diag(Id.getLoc(), diag::err_omp_var_scope)
3214 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3215 bool IsDecl =
3217 Diag(VD->getLocation(),
3218 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3219 << VD;
3220 return ExprError();
3221 }
3222 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3223 // A threadprivate or groupprivate directive for namespace-scope variables
3224 // must appear outside any definition or declaration other than the
3225 // namespace definition itself.
3226 if (CanonicalVD->getDeclContext()->isNamespace() &&
3227 (!SemaRef.getCurLexicalContext()->isFileContext() ||
3228 !SemaRef.getCurLexicalContext()->Encloses(
3229 CanonicalVD->getDeclContext()))) {
3230 Diag(Id.getLoc(), diag::err_omp_var_scope)
3231 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3232 bool IsDecl =
3234 Diag(VD->getLocation(),
3235 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3236 << VD;
3237 return ExprError();
3238 }
3239 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3240 // A threadprivate or groupprivate directive for static block-scope
3241 // variables must appear in the scope of the variable and not in a nested
3242 // scope.
3243 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3244 !SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(), CurScope)) {
3245 Diag(Id.getLoc(), diag::err_omp_var_scope)
3246 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3247 bool IsDecl =
3249 Diag(VD->getLocation(),
3250 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3251 << VD;
3252 return ExprError();
3253 }
3254
3255 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3256 // A threadprivate or groupprivate directive must lexically precede all
3257 // references to any of the variables in its list.
3258 if ((Kind == OMPD_threadprivate && VD->isUsed() &&
3259 !DSAStack->isThreadPrivate(VD)) ||
3260 (Kind == OMPD_groupprivate && VD->isUsed())) {
3261 Diag(Id.getLoc(), diag::err_omp_var_used)
3262 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3263 return ExprError();
3264 }
3265
3266 QualType ExprType = VD->getType().getNonReferenceType();
3268 SourceLocation(), VD,
3269 /*RefersToEnclosingVariableOrCapture=*/false,
3270 Id.getLoc(), ExprType, VK_LValue);
3271}
3272
3275 ArrayRef<Expr *> VarList) {
3276 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3277 SemaRef.CurContext->addDecl(D);
3279 }
3280 return nullptr;
3281}
3282
3285 ArrayRef<Expr *> VarList) {
3286 if (!getLangOpts().OpenMP || getLangOpts().OpenMP < 60) {
3287 Diag(Loc, diag::err_omp_unexpected_directive)
3288 << getOpenMPDirectiveName(OMPD_groupprivate, getLangOpts().OpenMP);
3289 return nullptr;
3290 }
3291 if (OMPGroupPrivateDecl *D = CheckOMPGroupPrivateDecl(Loc, VarList)) {
3292 SemaRef.CurContext->addDecl(D);
3294 }
3295 return nullptr;
3296}
3297
3298namespace {
3299class LocalVarRefChecker final
3300 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3301 Sema &SemaRef;
3302
3303public:
3304 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3305 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3306 if (VD->hasLocalStorage()) {
3307 SemaRef.Diag(E->getBeginLoc(),
3308 diag::err_omp_local_var_in_threadprivate_init)
3309 << E->getSourceRange();
3310 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3311 << VD << VD->getSourceRange();
3312 return true;
3313 }
3314 }
3315 return false;
3316 }
3317 bool VisitStmt(const Stmt *S) {
3318 for (const Stmt *Child : S->children()) {
3319 if (Child && Visit(Child))
3320 return true;
3321 }
3322 return false;
3323 }
3324 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3325};
3326} // namespace
3327
3328OMPThreadPrivateDecl *
3330 ArrayRef<Expr *> VarList) {
3331 ASTContext &Context = getASTContext();
3333 for (Expr *RefExpr : VarList) {
3334 auto *DE = cast<DeclRefExpr>(RefExpr);
3335 auto *VD = cast<VarDecl>(DE->getDecl());
3336 SourceLocation ILoc = DE->getExprLoc();
3337
3338 // Mark variable as used.
3339 VD->setReferenced();
3340 VD->markUsed(Context);
3341
3342 QualType QType = VD->getType();
3343 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3344 // It will be analyzed later.
3345 Vars.push_back(DE);
3346 continue;
3347 }
3348
3349 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3350 // A threadprivate variable must not have an incomplete type.
3351 if (SemaRef.RequireCompleteType(
3352 ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) {
3353 continue;
3354 }
3355
3356 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3357 // A threadprivate variable must not have a reference type.
3358 if (VD->getType()->isReferenceType()) {
3359 unsigned OMPVersion = getLangOpts().OpenMP;
3360 Diag(ILoc, diag::err_omp_ref_type_arg)
3361 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion)
3362 << VD->getType();
3363 bool IsDecl =
3365 Diag(VD->getLocation(),
3366 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3367 << VD;
3368 continue;
3369 }
3370
3371 // Check if this is a TLS variable. If TLS is not being supported, produce
3372 // the corresponding diagnostic.
3373 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3374 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3375 getLangOpts().OpenMPUseTLS &&
3376 getASTContext().getTargetInfo().isTLSSupported())) ||
3377 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3378 !VD->isLocalVarDecl())) {
3379 Diag(ILoc, diag::err_omp_var_thread_local)
3380 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3381 bool IsDecl =
3383 Diag(VD->getLocation(),
3384 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3385 << VD;
3386 continue;
3387 }
3388
3389 // Check if initial value of threadprivate variable reference variable with
3390 // local storage (it is not supported by runtime).
3391 if (const Expr *Init = VD->getAnyInitializer()) {
3392 LocalVarRefChecker Checker(SemaRef);
3393 if (Checker.Visit(Init))
3394 continue;
3395 }
3396
3397 Vars.push_back(RefExpr);
3398 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3399 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3400 Context, SourceRange(Loc, Loc)));
3401 if (ASTMutationListener *ML = Context.getASTMutationListener())
3402 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3403 }
3404 OMPThreadPrivateDecl *D = nullptr;
3405 if (!Vars.empty()) {
3406 D = OMPThreadPrivateDecl::Create(Context, SemaRef.getCurLexicalContext(),
3407 Loc, Vars);
3408 D->setAccess(AS_public);
3409 }
3410 return D;
3411}
3412
3415 ArrayRef<Expr *> VarList) {
3416 ASTContext &Context = getASTContext();
3418 for (Expr *RefExpr : VarList) {
3419 auto *DE = cast<DeclRefExpr>(RefExpr);
3420 auto *VD = cast<VarDecl>(DE->getDecl());
3421 SourceLocation ILoc = DE->getExprLoc();
3422
3423 // Mark variable as used.
3424 VD->setReferenced();
3425 VD->markUsed(Context);
3426
3427 QualType QType = VD->getType();
3428 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3429 // It will be analyzed later.
3430 Vars.push_back(DE);
3431 continue;
3432 }
3433
3434 // OpenMP groupprivate restrictions:
3435 // A groupprivate variable must not have an incomplete type.
3436 if (SemaRef.RequireCompleteType(
3437 ILoc, VD->getType(), diag::err_omp_groupprivate_incomplete_type)) {
3438 continue;
3439 }
3440
3441 // A groupprivate variable must not have a reference type.
3442 if (VD->getType()->isReferenceType()) {
3443 Diag(ILoc, diag::err_omp_ref_type_arg)
3444 << getOpenMPDirectiveName(OMPD_groupprivate) << VD->getType();
3445 bool IsDecl =
3447 Diag(VD->getLocation(),
3448 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3449 << VD;
3450 continue;
3451 }
3452
3453 // A variable that is declared with an initializer must not appear in a
3454 // groupprivate directive.
3455 if (VD->getAnyInitializer()) {
3456 Diag(ILoc, diag::err_omp_groupprivate_with_initializer)
3457 << VD->getDeclName();
3458 bool IsDecl =
3460 Diag(VD->getLocation(),
3461 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3462 << VD;
3463 continue;
3464 }
3465
3466 Vars.push_back(RefExpr);
3467 DSAStack->addDSA(VD, DE, OMPC_groupprivate);
3468 VD->addAttr(OMPGroupPrivateDeclAttr::CreateImplicit(Context,
3469 SourceRange(Loc, Loc)));
3470 if (ASTMutationListener *ML = Context.getASTMutationListener())
3471 ML->DeclarationMarkedOpenMPGroupPrivate(VD);
3472 }
3473 OMPGroupPrivateDecl *D = nullptr;
3474 if (!Vars.empty()) {
3475 D = OMPGroupPrivateDecl::Create(Context, SemaRef.getCurLexicalContext(),
3476 Loc, Vars);
3477 D->setAccess(AS_public);
3478 }
3479 return D;
3480}
3481
3482static OMPAllocateDeclAttr::AllocatorTypeTy
3483getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3484 if (!Allocator)
3485 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3486 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3487 Allocator->isInstantiationDependent() ||
3489 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3490 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3491 llvm::FoldingSetNodeID AEId;
3492 const Expr *AE = Allocator->IgnoreParenImpCasts();
3493 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3494 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3495 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3496 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3497 llvm::FoldingSetNodeID DAEId;
3498 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3499 /*Canonical=*/true);
3500 if (AEId == DAEId) {
3501 AllocatorKindRes = AllocatorKind;
3502 break;
3503 }
3504 }
3505 return AllocatorKindRes;
3506}
3507
3509 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3510 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3511 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3512 return false;
3513 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3514 Expr *PrevAllocator = A->getAllocator();
3515 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3516 getAllocatorKind(S, Stack, PrevAllocator);
3517 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3518 if (AllocatorsMatch &&
3519 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3520 Allocator && PrevAllocator) {
3521 const Expr *AE = Allocator->IgnoreParenImpCasts();
3522 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3523 llvm::FoldingSetNodeID AEId, PAEId;
3524 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3525 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3526 AllocatorsMatch = AEId == PAEId;
3527 }
3528 if (!AllocatorsMatch) {
3529 SmallString<256> AllocatorBuffer;
3530 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3531 if (Allocator)
3532 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3533 SmallString<256> PrevAllocatorBuffer;
3534 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3535 if (PrevAllocator)
3536 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3537 S.getPrintingPolicy());
3538
3539 SourceLocation AllocatorLoc =
3540 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3541 SourceRange AllocatorRange =
3542 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3543 SourceLocation PrevAllocatorLoc =
3544 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3545 SourceRange PrevAllocatorRange =
3546 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3547 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3548 << (Allocator ? 1 : 0) << AllocatorStream.str()
3549 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3550 << AllocatorRange;
3551 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3552 << PrevAllocatorRange;
3553 return true;
3554 }
3555 return false;
3556}
3557
3558static void
3560 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3561 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3562 if (VD->hasAttr<OMPAllocateDeclAttr>())
3563 return;
3564 if (Alignment &&
3565 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3566 Alignment->isInstantiationDependent() ||
3567 Alignment->containsUnexpandedParameterPack()))
3568 // Apply later when we have a usable value.
3569 return;
3570 if (Allocator &&
3571 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3572 Allocator->isInstantiationDependent() ||
3573 Allocator->containsUnexpandedParameterPack()))
3574 return;
3575 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3576 Allocator, Alignment, SR);
3577 VD->addAttr(A);
3579 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3580}
3581
3584 DeclContext *Owner) {
3585 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3586 Expr *Alignment = nullptr;
3587 Expr *Allocator = nullptr;
3588 if (Clauses.empty()) {
3589 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3590 // allocate directives that appear in a target region must specify an
3591 // allocator clause unless a requires directive with the dynamic_allocators
3592 // clause is present in the same compilation unit.
3593 if (getLangOpts().OpenMPIsTargetDevice &&
3594 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3595 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3596 } else {
3597 for (const OMPClause *C : Clauses)
3598 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3599 Allocator = AC->getAllocator();
3600 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3601 Alignment = AC->getAlignment();
3602 else
3603 llvm_unreachable("Unexpected clause on allocate directive");
3604 }
3605 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3606 getAllocatorKind(SemaRef, DSAStack, Allocator);
3608 for (Expr *RefExpr : VarList) {
3609 auto *DE = cast<DeclRefExpr>(RefExpr);
3610 auto *VD = cast<VarDecl>(DE->getDecl());
3611
3612 // Check if this is a TLS variable or global register.
3613 if (VD->getTLSKind() != VarDecl::TLS_None ||
3614 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3615 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3616 !VD->isLocalVarDecl()))
3617 continue;
3618
3619 // If the used several times in the allocate directive, the same allocator
3620 // must be used.
3622 AllocatorKind, Allocator))
3623 continue;
3624
3625 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3626 // If a list item has a static storage type, the allocator expression in the
3627 // allocator clause must be a constant expression that evaluates to one of
3628 // the predefined memory allocator values.
3629 if (Allocator && VD->hasGlobalStorage()) {
3630 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3631 Diag(Allocator->getExprLoc(),
3632 diag::err_omp_expected_predefined_allocator)
3633 << Allocator->getSourceRange();
3634 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3636 Diag(VD->getLocation(),
3637 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3638 << VD;
3639 continue;
3640 }
3641 }
3642
3643 Vars.push_back(RefExpr);
3644 applyOMPAllocateAttribute(SemaRef, VD, AllocatorKind, Allocator, Alignment,
3645 DE->getSourceRange());
3646 }
3647 if (Vars.empty())
3648 return nullptr;
3649 if (!Owner)
3650 Owner = SemaRef.getCurLexicalContext();
3651 auto *D = OMPAllocateDecl::Create(getASTContext(), Owner, Loc, Vars, Clauses);
3652 D->setAccess(AS_public);
3653 Owner->addDecl(D);
3655}
3656
3659 ArrayRef<OMPClause *> ClauseList) {
3660 OMPRequiresDecl *D = nullptr;
3661 if (!SemaRef.CurContext->isFileContext()) {
3662 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3663 } else {
3664 D = CheckOMPRequiresDecl(Loc, ClauseList);
3665 if (D) {
3666 SemaRef.CurContext->addDecl(D);
3667 DSAStack->addRequiresDecl(D);
3668 }
3669 }
3671}
3672
3674 OpenMPDirectiveKind DKind,
3675 ArrayRef<std::string> Assumptions,
3676 bool SkippedClauses) {
3677 if (!SkippedClauses && Assumptions.empty()) {
3678 unsigned OMPVersion = getLangOpts().OpenMP;
3679 Diag(Loc, diag::err_omp_no_clause_for_directive)
3680 << llvm::omp::getAllAssumeClauseOptions()
3681 << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion);
3682 }
3683
3684 auto *AA =
3685 OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc);
3686 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3687 OMPAssumeScoped.push_back(AA);
3688 return;
3689 }
3690
3691 // Global assumes without assumption clauses are ignored.
3692 if (Assumptions.empty())
3693 return;
3694
3695 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3696 "Unexpected omp assumption directive!");
3697 OMPAssumeGlobal.push_back(AA);
3698
3699 // The OMPAssumeGlobal scope above will take care of new declarations but
3700 // we also want to apply the assumption to existing ones, e.g., to
3701 // declarations in included headers. To this end, we traverse all existing
3702 // declaration contexts and annotate function declarations here.
3703 SmallVector<DeclContext *, 8> DeclContexts;
3704 auto *Ctx = SemaRef.CurContext;
3705 while (Ctx->getLexicalParent())
3706 Ctx = Ctx->getLexicalParent();
3707 DeclContexts.push_back(Ctx);
3708 while (!DeclContexts.empty()) {
3709 DeclContext *DC = DeclContexts.pop_back_val();
3710 for (auto *SubDC : DC->decls()) {
3711 if (SubDC->isInvalidDecl())
3712 continue;
3713 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3714 DeclContexts.push_back(CTD->getTemplatedDecl());
3715 llvm::append_range(DeclContexts, CTD->specializations());
3716 continue;
3717 }
3718 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3719 DeclContexts.push_back(DC);
3720 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3721 F->addAttr(AA);
3722 continue;
3723 }
3724 }
3725 }
3726}
3727
3729 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3730 OMPAssumeScoped.pop_back();
3731}
3732
3734 Stmt *AStmt,
3735 SourceLocation StartLoc,
3736 SourceLocation EndLoc) {
3737 if (!AStmt)
3738 return StmtError();
3739
3740 return OMPAssumeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
3741 AStmt);
3742}
3743
3746 ArrayRef<OMPClause *> ClauseList) {
3747 /// For target specific clauses, the requires directive cannot be
3748 /// specified after the handling of any of the target regions in the
3749 /// current compilation unit.
3750 ArrayRef<SourceLocation> TargetLocations =
3751 DSAStack->getEncounteredTargetLocs();
3752 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3753 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3754 for (const OMPClause *CNew : ClauseList) {
3755 // Check if any of the requires clauses affect target regions.
3760 Diag(Loc, diag::err_omp_directive_before_requires)
3761 << "target" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3762 for (SourceLocation TargetLoc : TargetLocations) {
3763 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3764 << "target";
3765 }
3766 } else if (!AtomicLoc.isInvalid() &&
3768 Diag(Loc, diag::err_omp_directive_before_requires)
3769 << "atomic" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3770 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3771 << "atomic";
3772 }
3773 }
3774 }
3775
3776 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3778 getASTContext(), SemaRef.getCurLexicalContext(), Loc, ClauseList);
3779 return nullptr;
3780}
3781
3782static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3783 const ValueDecl *D,
3784 const DSAStackTy::DSAVarData &DVar,
3785 bool IsLoopIterVar) {
3786 if (DVar.RefExpr) {
3787 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3788 << getOpenMPClauseNameForDiag(DVar.CKind);
3789 return;
3790 }
3791 enum {
3792 PDSA_StaticMemberShared,
3793 PDSA_StaticLocalVarShared,
3794 PDSA_LoopIterVarPrivate,
3795 PDSA_LoopIterVarLinear,
3796 PDSA_LoopIterVarLastprivate,
3797 PDSA_ConstVarShared,
3798 PDSA_GlobalVarShared,
3799 PDSA_TaskVarFirstprivate,
3800 PDSA_LocalVarPrivate,
3801 PDSA_Implicit
3802 } Reason = PDSA_Implicit;
3803 bool ReportHint = false;
3804 auto ReportLoc = D->getLocation();
3805 auto *VD = dyn_cast<VarDecl>(D);
3806 if (IsLoopIterVar) {
3807 if (DVar.CKind == OMPC_private)
3808 Reason = PDSA_LoopIterVarPrivate;
3809 else if (DVar.CKind == OMPC_lastprivate)
3810 Reason = PDSA_LoopIterVarLastprivate;
3811 else
3812 Reason = PDSA_LoopIterVarLinear;
3813 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3814 DVar.CKind == OMPC_firstprivate) {
3815 Reason = PDSA_TaskVarFirstprivate;
3816 ReportLoc = DVar.ImplicitDSALoc;
3817 } else if (VD && VD->isStaticLocal())
3818 Reason = PDSA_StaticLocalVarShared;
3819 else if (VD && VD->isStaticDataMember())
3820 Reason = PDSA_StaticMemberShared;
3821 else if (VD && VD->isFileVarDecl())
3822 Reason = PDSA_GlobalVarShared;
3823 else if (D->getType().isConstant(SemaRef.getASTContext()))
3824 Reason = PDSA_ConstVarShared;
3825 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3826 ReportHint = true;
3827 Reason = PDSA_LocalVarPrivate;
3828 }
3829 if (Reason != PDSA_Implicit) {
3830 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
3831 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3832 << Reason << ReportHint
3833 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
3834 } else if (DVar.ImplicitDSALoc.isValid()) {
3835 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3836 << getOpenMPClauseNameForDiag(DVar.CKind);
3837 }
3838}
3839
3842 bool IsAggregateOrDeclareTarget) {
3844 switch (M) {
3845 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3846 case OMPC_DEFAULTMAP_MODIFIER_storage:
3847 Kind = OMPC_MAP_alloc;
3848 break;
3849 case OMPC_DEFAULTMAP_MODIFIER_to:
3850 Kind = OMPC_MAP_to;
3851 break;
3852 case OMPC_DEFAULTMAP_MODIFIER_from:
3853 Kind = OMPC_MAP_from;
3854 break;
3855 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3856 Kind = OMPC_MAP_tofrom;
3857 break;
3858 case OMPC_DEFAULTMAP_MODIFIER_present:
3859 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3860 // If implicit-behavior is present, each variable referenced in the
3861 // construct in the category specified by variable-category is treated as if
3862 // it had been listed in a map clause with the map-type of alloc and
3863 // map-type-modifier of present.
3864 Kind = OMPC_MAP_alloc;
3865 break;
3866 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3867 case OMPC_DEFAULTMAP_MODIFIER_private:
3869 llvm_unreachable("Unexpected defaultmap implicit behavior");
3870 case OMPC_DEFAULTMAP_MODIFIER_none:
3871 case OMPC_DEFAULTMAP_MODIFIER_default:
3873 // IsAggregateOrDeclareTarget could be true if:
3874 // 1. the implicit behavior for aggregate is tofrom
3875 // 2. it's a declare target link
3876 if (IsAggregateOrDeclareTarget) {
3877 Kind = OMPC_MAP_tofrom;
3878 break;
3879 }
3880 llvm_unreachable("Unexpected defaultmap implicit behavior");
3881 }
3882 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3883 return Kind;
3884}
3885
3886namespace {
3887struct VariableImplicitInfo {
3888 static const unsigned MapKindNum = OMPC_MAP_unknown;
3889 static const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3890
3891 llvm::SetVector<Expr *> Privates;
3892 llvm::SetVector<Expr *> Firstprivates;
3893 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3894 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3895 MapModifiers[DefaultmapKindNum];
3896};
3897
3898class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3899 DSAStackTy *Stack;
3900 Sema &SemaRef;
3901 OpenMPDirectiveKind DKind = OMPD_unknown;
3902 bool ErrorFound = false;
3903 bool TryCaptureCXXThisMembers = false;
3904 CapturedStmt *CS = nullptr;
3905
3906 VariableImplicitInfo ImpInfo;
3907 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3908 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3909
3910 void VisitSubCaptures(OMPExecutableDirective *S) {
3911 // Check implicitly captured variables.
3912 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3913 return;
3914 if (S->getDirectiveKind() == OMPD_atomic ||
3915 S->getDirectiveKind() == OMPD_critical ||
3916 S->getDirectiveKind() == OMPD_section ||
3917 S->getDirectiveKind() == OMPD_master ||
3918 S->getDirectiveKind() == OMPD_masked ||
3919 S->getDirectiveKind() == OMPD_scope ||
3920 S->getDirectiveKind() == OMPD_assume ||
3921 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3922 Visit(S->getAssociatedStmt());
3923 return;
3924 }
3925 visitSubCaptures(S->getInnermostCapturedStmt());
3926 // Try to capture inner this->member references to generate correct mappings
3927 // and diagnostics.
3928 if (TryCaptureCXXThisMembers ||
3930 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3931 [](const CapturedStmt::Capture &C) {
3932 return C.capturesThis();
3933 }))) {
3934 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3935 TryCaptureCXXThisMembers = true;
3936 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3937 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3938 }
3939 // In tasks firstprivates are not captured anymore, need to analyze them
3940 // explicitly.
3941 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3942 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3943 for (OMPClause *C : S->clauses())
3944 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3945 for (Expr *Ref : FC->varlist())
3946 Visit(Ref);
3947 }
3948 }
3949 }
3950
3951public:
3952 void VisitDeclRefExpr(DeclRefExpr *E) {
3953 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3957 return;
3958 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3959 // Check the datasharing rules for the expressions in the clauses.
3960 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3961 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3962 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3963 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3964 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3965 Visit(CED->getInit());
3966 return;
3967 }
3968 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3969 // Do not analyze internal variables and do not enclose them into
3970 // implicit clauses.
3971 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3972 return;
3973 VD = VD->getCanonicalDecl();
3974 // Skip internally declared variables.
3975 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3976 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3977 !Stack->isImplicitTaskFirstprivate(VD))
3978 return;
3979 // Skip allocators in uses_allocators clauses.
3980 if (Stack->isUsesAllocatorsDecl(VD))
3981 return;
3982
3983 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3984 // Check if the variable has explicit DSA set and stop analysis if it so.
3985 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3986 return;
3987
3988 // Skip internally declared static variables.
3989 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3990 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3991 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3992 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3993 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3994 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3995 !Stack->isImplicitTaskFirstprivate(VD))
3996 return;
3997
3998 SourceLocation ELoc = E->getExprLoc();
3999 // The default(none) clause requires that each variable that is referenced
4000 // in the construct, and does not have a predetermined data-sharing
4001 // attribute, must have its data-sharing attribute explicitly determined
4002 // by being listed in a data-sharing attribute clause.
4003 if (DVar.CKind == OMPC_unknown &&
4004 (Stack->getDefaultDSA() == DSA_none ||
4005 Stack->getDefaultDSA() == DSA_private ||
4006 Stack->getDefaultDSA() == DSA_firstprivate) &&
4007 isImplicitOrExplicitTaskingRegion(DKind) &&
4008 VarsWithInheritedDSA.count(VD) == 0) {
4009 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
4010 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
4011 Stack->getDefaultDSA() == DSA_private)) {
4012 DSAStackTy::DSAVarData DVar =
4013 Stack->getImplicitDSA(VD, /*FromParent=*/false);
4014 InheritedDSA = DVar.CKind == OMPC_unknown;
4015 }
4016 if (InheritedDSA)
4017 VarsWithInheritedDSA[VD] = E;
4018 if (Stack->getDefaultDSA() == DSA_none)
4019 return;
4020 }
4021
4022 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
4023 // If implicit-behavior is none, each variable referenced in the
4024 // construct that does not have a predetermined data-sharing attribute
4025 // and does not appear in a to or link clause on a declare target
4026 // directive must be listed in a data-mapping attribute clause, a
4027 // data-sharing attribute clause (including a data-sharing attribute
4028 // clause on a combined construct where target. is one of the
4029 // constituent constructs), or an is_device_ptr clause.
4030 OpenMPDefaultmapClauseKind ClauseKind =
4032 if (SemaRef.getLangOpts().OpenMP >= 50) {
4033 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
4034 OMPC_DEFAULTMAP_MODIFIER_none;
4035 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
4036 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
4037 // Only check for data-mapping attribute and is_device_ptr here
4038 // since we have already make sure that the declaration does not
4039 // have a data-sharing attribute above
4040 if (!Stack->checkMappableExprComponentListsForDecl(
4041 VD, /*CurrentRegionOnly=*/true,
4043 MapExprComponents,
4045 auto MI = MapExprComponents.rbegin();
4046 auto ME = MapExprComponents.rend();
4047 return MI != ME && MI->getAssociatedDeclaration() == VD;
4048 })) {
4049 VarsWithInheritedDSA[VD] = E;
4050 return;
4051 }
4052 }
4053 }
4054 if (SemaRef.getLangOpts().OpenMP > 50) {
4055 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
4056 OMPC_DEFAULTMAP_MODIFIER_present;
4057 if (IsModifierPresent) {
4058 if (!llvm::is_contained(ImpInfo.MapModifiers[ClauseKind],
4059 OMPC_MAP_MODIFIER_present)) {
4060 ImpInfo.MapModifiers[ClauseKind].push_back(
4061 OMPC_MAP_MODIFIER_present);
4062 }
4063 }
4064 }
4065
4067 !Stack->isLoopControlVariable(VD).first) {
4068 if (!Stack->checkMappableExprComponentListsForDecl(
4069 VD, /*CurrentRegionOnly=*/true,
4071 StackComponents,
4073 if (SemaRef.LangOpts.OpenMP >= 50)
4074 return !StackComponents.empty();
4075 // Variable is used if it has been marked as an array, array
4076 // section, array shaping or the variable itself.
4077 return StackComponents.size() == 1 ||
4078 llvm::all_of(
4079 llvm::drop_begin(llvm::reverse(StackComponents)),
4080 [](const OMPClauseMappableExprCommon::
4081 MappableComponent &MC) {
4082 return MC.getAssociatedDeclaration() ==
4083 nullptr &&
4084 (isa<ArraySectionExpr>(
4085 MC.getAssociatedExpression()) ||
4086 isa<OMPArrayShapingExpr>(
4087 MC.getAssociatedExpression()) ||
4088 isa<ArraySubscriptExpr>(
4089 MC.getAssociatedExpression()));
4090 });
4091 })) {
4092 bool IsFirstprivate = false;
4093 // By default lambdas are captured as firstprivates.
4094 if (const auto *RD =
4096 IsFirstprivate = RD->isLambda();
4097 IsFirstprivate =
4098 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
4099 if (IsFirstprivate) {
4100 ImpInfo.Firstprivates.insert(E);
4101 } else {
4103 Stack->getDefaultmapModifier(ClauseKind);
4104 if (M == OMPC_DEFAULTMAP_MODIFIER_private) {
4105 ImpInfo.Privates.insert(E);
4106 } else {
4108 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
4109 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
4110 }
4111 }
4112 return;
4113 }
4114 }
4115
4116 // OpenMP [2.9.3.6, Restrictions, p.2]
4117 // A list item that appears in a reduction clause of the innermost
4118 // enclosing worksharing or parallel construct may not be accessed in an
4119 // explicit task.
4120 DVar = Stack->hasInnermostDSA(
4121 VD,
4122 [](OpenMPClauseKind C, bool AppliedToPointee) {
4123 return C == OMPC_reduction && !AppliedToPointee;
4124 },
4125 [](OpenMPDirectiveKind K) {
4126 return isOpenMPParallelDirective(K) ||
4128 },
4129 /*FromParent=*/true);
4130 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4131 ErrorFound = true;
4132 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4133 reportOriginalDsa(SemaRef, Stack, VD, DVar);
4134 return;
4135 }
4136
4137 // Define implicit data-sharing attributes for task.
4138 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
4139 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
4140 (((Stack->getDefaultDSA() == DSA_firstprivate &&
4141 DVar.CKind == OMPC_firstprivate) ||
4142 (Stack->getDefaultDSA() == DSA_private &&
4143 DVar.CKind == OMPC_private)) &&
4144 !DVar.RefExpr)) &&
4145 !Stack->isLoopControlVariable(VD).first) {
4146 if (Stack->getDefaultDSA() == DSA_private)
4147 ImpInfo.Privates.insert(E);
4148 else
4149 ImpInfo.Firstprivates.insert(E);
4150 return;
4151 }
4152
4153 // Store implicitly used globals with declare target link for parent
4154 // target.
4155 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
4156 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
4157 Stack->addToParentTargetRegionLinkGlobals(E);
4158 return;
4159 }
4160 }
4161 }
4162 void VisitMemberExpr(MemberExpr *E) {
4163 if (E->isTypeDependent() || E->isValueDependent() ||
4165 return;
4166 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
4167 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
4168 if (!FD)
4169 return;
4170 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
4171 // Check if the variable has explicit DSA set and stop analysis if it
4172 // so.
4173 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
4174 return;
4175
4177 !Stack->isLoopControlVariable(FD).first &&
4178 !Stack->checkMappableExprComponentListsForDecl(
4179 FD, /*CurrentRegionOnly=*/true,
4181 StackComponents,
4183 return isa<CXXThisExpr>(
4184 cast<MemberExpr>(
4185 StackComponents.back().getAssociatedExpression())
4186 ->getBase()
4187 ->IgnoreParens());
4188 })) {
4189 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
4190 // A bit-field cannot appear in a map clause.
4191 //
4192 if (FD->isBitField())
4193 return;
4194
4195 // Check to see if the member expression is referencing a class that
4196 // has already been explicitly mapped
4197 if (Stack->isClassPreviouslyMapped(TE->getType()))
4198 return;
4199
4201 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4202 OpenMPDefaultmapClauseKind ClauseKind =
4205 Modifier, /*IsAggregateOrDeclareTarget=*/true);
4206 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
4207 return;
4208 }
4209
4210 SourceLocation ELoc = E->getExprLoc();
4211 // OpenMP [2.9.3.6, Restrictions, p.2]
4212 // A list item that appears in a reduction clause of the innermost
4213 // enclosing worksharing or parallel construct may not be accessed in
4214 // an explicit task.
4215 DVar = Stack->hasInnermostDSA(
4216 FD,
4217 [](OpenMPClauseKind C, bool AppliedToPointee) {
4218 return C == OMPC_reduction && !AppliedToPointee;
4219 },
4220 [](OpenMPDirectiveKind K) {
4221 return isOpenMPParallelDirective(K) ||
4223 },
4224 /*FromParent=*/true);
4225 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4226 ErrorFound = true;
4227 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4228 reportOriginalDsa(SemaRef, Stack, FD, DVar);
4229 return;
4230 }
4231
4232 // Define implicit data-sharing attributes for task.
4233 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4234 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4235 !Stack->isLoopControlVariable(FD).first) {
4236 // Check if there is a captured expression for the current field in the
4237 // region. Do not mark it as firstprivate unless there is no captured
4238 // expression.
4239 // TODO: try to make it firstprivate.
4240 if (DVar.CKind != OMPC_unknown)
4241 ImpInfo.Firstprivates.insert(E);
4242 }
4243 return;
4244 }
4247 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4248 DKind, /*NoDiagnose=*/true))
4249 return;
4250 const auto *VD = cast<ValueDecl>(
4251 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4252 if (!Stack->checkMappableExprComponentListsForDecl(
4253 VD, /*CurrentRegionOnly=*/true,
4254 [&CurComponents](
4256 StackComponents,
4258 auto CCI = CurComponents.rbegin();
4259 auto CCE = CurComponents.rend();
4260 for (const auto &SC : llvm::reverse(StackComponents)) {
4261 // Do both expressions have the same kind?
4262 if (CCI->getAssociatedExpression()->getStmtClass() !=
4263 SC.getAssociatedExpression()->getStmtClass())
4264 if (!((isa<ArraySectionExpr>(
4265 SC.getAssociatedExpression()) ||
4266 isa<OMPArrayShapingExpr>(
4267 SC.getAssociatedExpression())) &&
4268 isa<ArraySubscriptExpr>(
4269 CCI->getAssociatedExpression())))
4270 return false;
4271
4272 const Decl *CCD = CCI->getAssociatedDeclaration();
4273 const Decl *SCD = SC.getAssociatedDeclaration();
4274 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4275 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4276 if (SCD != CCD)
4277 return false;
4278 std::advance(CCI, 1);
4279 if (CCI == CCE)
4280 break;
4281 }
4282 return true;
4283 })) {
4284 Visit(E->getBase());
4285 }
4286 } else if (!TryCaptureCXXThisMembers) {
4287 Visit(E->getBase());
4288 }
4289 }
4290 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4291 for (OMPClause *C : S->clauses()) {
4292 // Skip analysis of arguments of private clauses for task|target
4293 // directives.
4294 if (isa_and_nonnull<OMPPrivateClause>(C))
4295 continue;
4296 // Skip analysis of arguments of implicitly defined firstprivate clause
4297 // for task|target directives.
4298 // Skip analysis of arguments of implicitly defined map clause for target
4299 // directives.
4301 C->isImplicit() && !isOpenMPTaskingDirective(DKind))) {
4302 for (Stmt *CC : C->children()) {
4303 if (CC)
4304 Visit(CC);
4305 }
4306 }
4307 }
4308 // Check implicitly captured variables.
4309 VisitSubCaptures(S);
4310 }
4311
4312 void VisitOMPCanonicalLoopNestTransformationDirective(
4313 OMPCanonicalLoopNestTransformationDirective *S) {
4314 // Loop transformation directives do not introduce data sharing
4315 VisitStmt(S);
4316 }
4317
4318 void VisitCallExpr(CallExpr *S) {
4319 for (Stmt *C : S->arguments()) {
4320 if (C) {
4321 // Check implicitly captured variables in the task-based directives to
4322 // check if they must be firstprivatized.
4323 Visit(C);
4324 }
4325 }
4326 if (Expr *Callee = S->getCallee()) {
4327 auto *CI = Callee->IgnoreParenImpCasts();
4328 if (auto *CE = dyn_cast<MemberExpr>(CI))
4329 Visit(CE->getBase());
4330 else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4331 Visit(CE);
4332 }
4333 }
4334 void VisitStmt(Stmt *S) {
4335 for (Stmt *C : S->children()) {
4336 if (C) {
4337 // Check implicitly captured variables in the task-based directives to
4338 // check if they must be firstprivatized.
4339 Visit(C);
4340 }
4341 }
4342 }
4343
4344 void visitSubCaptures(CapturedStmt *S) {
4345 for (const CapturedStmt::Capture &Cap : S->captures()) {
4346 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4347 continue;
4348 VarDecl *VD = Cap.getCapturedVar();
4349 // Do not try to map the variable if it or its sub-component was mapped
4350 // already.
4352 Stack->checkMappableExprComponentListsForDecl(
4353 VD, /*CurrentRegionOnly=*/true,
4355 OpenMPClauseKind) { return true; }))
4356 continue;
4357 DeclRefExpr *DRE = buildDeclRefExpr(
4358 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4359 Cap.getLocation(), /*RefersToCapture=*/true);
4360 Visit(DRE);
4361 }
4362 }
4363 bool isErrorFound() const { return ErrorFound; }
4364 const VariableImplicitInfo &getImplicitInfo() const { return ImpInfo; }
4365 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4366 return VarsWithInheritedDSA;
4367 }
4368
4369 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4370 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4371 DKind = S->getCurrentDirective();
4372 // Process declare target link variables for the target directives.
4374 for (DeclRefExpr *E : Stack->getLinkGlobals())
4375 Visit(E);
4376 }
4377 }
4378};
4379} // namespace
4380
4381static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4382 OpenMPDirectiveKind DKind,
4383 bool ScopeEntry) {
4386 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4387 if (isOpenMPTeamsDirective(DKind))
4388 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4389 if (isOpenMPParallelDirective(DKind))
4390 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4392 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4393 if (isOpenMPSimdDirective(DKind))
4394 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4395 Stack->handleConstructTrait(Traits, ScopeEntry);
4396}
4397
4398static SmallVector<SemaOpenMP::CapturedParamNameType>
4399getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4400 ASTContext &Context = SemaRef.getASTContext();
4401 QualType KmpInt32Ty =
4402 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4403 QualType KmpInt32PtrTy =
4404 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4406 std::make_pair(".global_tid.", KmpInt32PtrTy),
4407 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4408 };
4409 if (LoopBoundSharing) {
4410 QualType KmpSizeTy = Context.getSizeType().withConst();
4411 Params.push_back(std::make_pair(".previous.lb.", KmpSizeTy));
4412 Params.push_back(std::make_pair(".previous.ub.", KmpSizeTy));
4413 }
4414
4415 // __context with shared vars
4416 Params.push_back(std::make_pair(StringRef(), QualType()));
4417 return Params;
4418}
4419
4420static SmallVector<SemaOpenMP::CapturedParamNameType>
4422 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4423}
4424
4425static SmallVector<SemaOpenMP::CapturedParamNameType>
4427 ASTContext &Context = SemaRef.getASTContext();
4428 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4429 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4430 QualType KmpInt32PtrTy =
4431 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4432 QualType Args[] = {VoidPtrTy};
4434 EPI.Variadic = true;
4435 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4437 std::make_pair(".global_tid.", KmpInt32Ty),
4438 std::make_pair(".part_id.", KmpInt32PtrTy),
4439 std::make_pair(".privates.", VoidPtrTy),
4440 std::make_pair(
4441 ".copy_fn.",
4442 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4443 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4444 std::make_pair(StringRef(), QualType()) // __context with shared vars
4445 };
4446 return Params;
4447}
4448
4449static SmallVector<SemaOpenMP::CapturedParamNameType>
4451 ASTContext &Context = SemaRef.getASTContext();
4453 if (SemaRef.getLangOpts().OpenMPIsTargetDevice) {
4454 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4455 Params.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4456 }
4457 // __context with shared vars
4458 Params.push_back(std::make_pair(StringRef(), QualType()));
4459 return Params;
4460}
4461
4462static SmallVector<SemaOpenMP::CapturedParamNameType>
4465 std::make_pair(StringRef(), QualType()) // __context with shared vars
4466 };
4467 return Params;
4468}
4469
4470static SmallVector<SemaOpenMP::CapturedParamNameType>
4472 ASTContext &Context = SemaRef.getASTContext();
4473 QualType KmpInt32Ty =
4474 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4475 QualType KmpUInt64Ty =
4476 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4477 QualType KmpInt64Ty =
4478 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4479 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4480 QualType KmpInt32PtrTy =
4481 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4482 QualType Args[] = {VoidPtrTy};
4484 EPI.Variadic = true;
4485 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4487 std::make_pair(".global_tid.", KmpInt32Ty),
4488 std::make_pair(".part_id.", KmpInt32PtrTy),
4489 std::make_pair(".privates.", VoidPtrTy),
4490 std::make_pair(
4491 ".copy_fn.",
4492 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4493 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4494 std::make_pair(".lb.", KmpUInt64Ty),
4495 std::make_pair(".ub.", KmpUInt64Ty),
4496 std::make_pair(".st.", KmpInt64Ty),
4497 std::make_pair(".liter.", KmpInt32Ty),
4498 std::make_pair(".reductions.", VoidPtrTy),
4499 std::make_pair(StringRef(), QualType()) // __context with shared vars
4500 };
4501 return Params;
4502}
4503
4505 Scope *CurScope, SourceLocation Loc) {
4507 getOpenMPCaptureRegions(Regions, DKind);
4508
4509 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(DKind);
4510
4511 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4512 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4513 SemaRef.getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4514 };
4515
4516 for (auto [Level, RKind] : llvm::enumerate(Regions)) {
4517 switch (RKind) {
4518 // All region kinds that can be returned from `getOpenMPCaptureRegions`
4519 // are listed here.
4520 case OMPD_parallel:
4522 Loc, CurScope, CR_OpenMP,
4523 getParallelRegionParams(SemaRef, LoopBoundSharing), Level);
4524 break;
4525 case OMPD_teams:
4526 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4527 getTeamsRegionParams(SemaRef), Level);
4528 break;
4529 case OMPD_task:
4530 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4531 getTaskRegionParams(SemaRef), Level);
4532 // Mark this captured region as inlined, because we don't use outlined
4533 // function directly.
4534 MarkAsInlined(SemaRef.getCurCapturedRegion());
4535 break;
4536 case OMPD_taskloop:
4537 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4538 getTaskloopRegionParams(SemaRef), Level);
4539 // Mark this captured region as inlined, because we don't use outlined
4540 // function directly.
4541 MarkAsInlined(SemaRef.getCurCapturedRegion());
4542 break;
4543 case OMPD_target:
4544 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4545 getTargetRegionParams(SemaRef), Level);
4546 break;
4547 case OMPD_unknown:
4548 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4549 getUnknownRegionParams(SemaRef));
4550 break;
4551 case OMPD_metadirective:
4552 case OMPD_nothing:
4553 default:
4554 llvm_unreachable("Unexpected capture region");
4555 }
4556 }
4557}
4558
4560 Scope *CurScope) {
4561 switch (DKind) {
4562 case OMPD_atomic:
4563 case OMPD_critical:
4564 case OMPD_masked:
4565 case OMPD_master:
4566 case OMPD_section:
4567 case OMPD_tile:
4568 case OMPD_stripe:
4569 case OMPD_unroll:
4570 case OMPD_reverse:
4571 case OMPD_interchange:
4572 case OMPD_assume:
4573 break;
4574 default:
4575 processCapturedRegions(SemaRef, DKind, CurScope,
4576 DSAStack->getConstructLoc());
4577 break;
4578 }
4579
4580 DSAStack->setContext(SemaRef.CurContext);
4581 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
4582}
4583
4584int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4585 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4586}
4587
4590 getOpenMPCaptureRegions(CaptureRegions, DKind);
4591 return CaptureRegions.size();
4592}
4593
4595 Expr *CaptureExpr, bool WithInit,
4596 DeclContext *CurContext,
4597 bool AsExpression) {
4598 assert(CaptureExpr);
4599 ASTContext &C = S.getASTContext();
4600 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4601 QualType Ty = Init->getType();
4602 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4603 if (S.getLangOpts().CPlusPlus) {
4604 Ty = C.getLValueReferenceType(Ty);
4605 } else {
4606 Ty = C.getPointerType(Ty);
4607 ExprResult Res =
4608 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4609 if (!Res.isUsable())
4610 return nullptr;
4611 Init = Res.get();
4612 }
4613 WithInit = true;
4614 }
4615 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4616 CaptureExpr->getBeginLoc());
4617 if (!WithInit)
4618 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4619 CurContext->addHiddenDecl(CED);
4621 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4622 return CED;
4623}
4624
4625static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4626 bool WithInit) {
4628 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4630 else
4631 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4632 S.CurContext,
4633 /*AsExpression=*/false);
4634 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4635 CaptureExpr->getExprLoc());
4636}
4637
4638static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4639 StringRef Name) {
4640 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4641 if (!Ref) {
4643 S, &S.getASTContext().Idents.get(Name), CaptureExpr,
4644 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4645 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4646 CaptureExpr->getExprLoc());
4647 }
4648 ExprResult Res = Ref;
4649 if (!S.getLangOpts().CPlusPlus &&
4650 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4651 Ref->getType()->isPointerType()) {
4652 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4653 if (!Res.isUsable())
4654 return ExprError();
4655 }
4656 return S.DefaultLvalueConversion(Res.get());
4657}
4658
4659namespace {
4660// OpenMP directives parsed in this section are represented as a
4661// CapturedStatement with an associated statement. If a syntax error
4662// is detected during the parsing of the associated statement, the
4663// compiler must abort processing and close the CapturedStatement.
4664//
4665// Combined directives such as 'target parallel' have more than one
4666// nested CapturedStatements. This RAII ensures that we unwind out
4667// of all the nested CapturedStatements when an error is found.
4668class CaptureRegionUnwinderRAII {
4669private:
4670 Sema &S;
4671 bool &ErrorFound;
4672 OpenMPDirectiveKind DKind = OMPD_unknown;
4673
4674public:
4675 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4676 OpenMPDirectiveKind DKind)
4677 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4678 ~CaptureRegionUnwinderRAII() {
4679 if (ErrorFound) {
4680 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4681 while (--ThisCaptureLevel >= 0)
4683 }
4684 }
4685};
4686} // namespace
4687
4689 // Capture variables captured by reference in lambdas for target-based
4690 // directives.
4691 if (!SemaRef.CurContext->isDependentContext() &&
4692 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4694 DSAStack->getCurrentDirective()))) {
4695 QualType Type = V->getType();
4696 if (const auto *RD = Type.getCanonicalType()
4697 .getNonReferenceType()
4698 ->getAsCXXRecordDecl()) {
4699 bool SavedForceCaptureByReferenceInTargetExecutable =
4700 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4701 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4702 /*V=*/true);
4703 if (RD->isLambda()) {
4704 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4705 FieldDecl *ThisCapture;
4706 RD->getCaptureFields(Captures, ThisCapture);
4707 for (const LambdaCapture &LC : RD->captures()) {
4708 if (LC.getCaptureKind() == LCK_ByRef) {
4709 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4710 DeclContext *VDC = VD->getDeclContext();
4711 if (!VDC->Encloses(SemaRef.CurContext))
4712 continue;
4713 SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
4714 } else if (LC.getCaptureKind() == LCK_This) {
4715 QualType ThisTy = SemaRef.getCurrentThisType();
4716 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4717 ThisTy, ThisCapture->getType()))
4718 SemaRef.CheckCXXThisCapture(LC.getLocation());
4719 }
4720 }
4721 }
4722 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4723 SavedForceCaptureByReferenceInTargetExecutable);
4724 }
4725 }
4726}
4727
4729 const ArrayRef<OMPClause *> Clauses) {
4730 const OMPOrderedClause *Ordered = nullptr;
4731 const OMPOrderClause *Order = nullptr;
4732
4733 for (const OMPClause *Clause : Clauses) {
4734 if (Clause->getClauseKind() == OMPC_ordered)
4735 Ordered = cast<OMPOrderedClause>(Clause);
4736 else if (Clause->getClauseKind() == OMPC_order) {
4737 Order = cast<OMPOrderClause>(Clause);
4738 if (Order->getKind() != OMPC_ORDER_concurrent)
4739 Order = nullptr;
4740 }
4741 if (Ordered && Order)
4742 break;
4743 }
4744
4745 if (Ordered && Order) {
4746 S.Diag(Order->getKindKwLoc(),
4747 diag::err_omp_simple_clause_incompatible_with_ordered)
4748 << getOpenMPClauseNameForDiag(OMPC_order)
4749 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4750 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4751 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4752 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4753 return true;
4754 }
4755 return false;
4756}
4757
4759 ArrayRef<OMPClause *> Clauses) {
4761 /*ScopeEntry=*/false);
4762 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
4763 return S;
4764
4765 bool ErrorFound = false;
4766 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4767 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4768 if (!S.isUsable()) {
4769 ErrorFound = true;
4770 return StmtError();
4771 }
4772
4774 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4775 OMPOrderedClause *OC = nullptr;
4776 OMPScheduleClause *SC = nullptr;
4779 // This is required for proper codegen.
4780 for (OMPClause *Clause : Clauses) {
4781 if (!getLangOpts().OpenMPSimd &&
4782 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4783 DSAStack->getCurrentDirective() == OMPD_target) &&
4784 Clause->getClauseKind() == OMPC_in_reduction) {
4785 // Capture taskgroup task_reduction descriptors inside the tasking regions
4786 // with the corresponding in_reduction items.
4787 auto *IRC = cast<OMPInReductionClause>(Clause);
4788 for (Expr *E : IRC->taskgroup_descriptors())
4789 if (E)
4790 SemaRef.MarkDeclarationsReferencedInExpr(E);
4791 }
4792 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4793 Clause->getClauseKind() == OMPC_copyprivate ||
4794 (getLangOpts().OpenMPUseTLS &&
4795 getASTContext().getTargetInfo().isTLSSupported() &&
4796 Clause->getClauseKind() == OMPC_copyin)) {
4797 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4798 // Mark all variables in private list clauses as used in inner region.
4799 for (Stmt *VarRef : Clause->children()) {
4800 if (auto *E = cast_or_null<Expr>(VarRef)) {
4801 SemaRef.MarkDeclarationsReferencedInExpr(E);
4802 }
4803 }
4804 DSAStack->setForceVarCapturing(/*V=*/false);
4805 } else if (CaptureRegions.size() > 1 ||
4806 CaptureRegions.back() != OMPD_unknown) {
4807 if (auto *C = OMPClauseWithPreInit::get(Clause))
4808 PICs.push_back(C);
4809 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4810 if (Expr *E = C->getPostUpdateExpr())
4811 SemaRef.MarkDeclarationsReferencedInExpr(E);
4812 }
4813 }
4814 if (Clause->getClauseKind() == OMPC_schedule)
4815 SC = cast<OMPScheduleClause>(Clause);
4816 else if (Clause->getClauseKind() == OMPC_ordered)
4817 OC = cast<OMPOrderedClause>(Clause);
4818 else if (Clause->getClauseKind() == OMPC_linear)
4819 LCs.push_back(cast<OMPLinearClause>(Clause));
4820 }
4821 // Capture allocator expressions if used.
4822 for (Expr *E : DSAStack->getInnerAllocators())
4823 SemaRef.MarkDeclarationsReferencedInExpr(E);
4824 // OpenMP, 2.7.1 Loop Construct, Restrictions
4825 // The nonmonotonic modifier cannot be specified if an ordered clause is
4826 // specified.
4827 if (SC &&
4828 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4830 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4831 OC) {
4832 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4835 diag::err_omp_simple_clause_incompatible_with_ordered)
4836 << getOpenMPClauseNameForDiag(OMPC_schedule)
4837 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4838 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4839 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4840 ErrorFound = true;
4841 }
4842 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4843 // If an order(concurrent) clause is present, an ordered clause may not appear
4844 // on the same directive.
4845 if (checkOrderedOrderSpecified(SemaRef, Clauses))
4846 ErrorFound = true;
4847 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4848 for (const OMPLinearClause *C : LCs) {
4849 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4850 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4851 }
4852 ErrorFound = true;
4853 }
4854 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4855 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4856 OC->getNumForLoops()) {
4857 unsigned OMPVersion = getLangOpts().OpenMP;
4858 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4859 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(), OMPVersion);
4860 ErrorFound = true;
4861 }
4862 if (ErrorFound) {
4863 return StmtError();
4864 }
4865 StmtResult SR = S;
4866 unsigned CompletedRegions = 0;
4867 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4868 // Mark all variables in private list clauses as used in inner region.
4869 // Required for proper codegen of combined directives.
4870 // TODO: add processing for other clauses.
4871 if (ThisCaptureRegion != OMPD_unknown) {
4872 for (const clang::OMPClauseWithPreInit *C : PICs) {
4873 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4874 // Find the particular capture region for the clause if the
4875 // directive is a combined one with multiple capture regions.
4876 // If the directive is not a combined one, the capture region
4877 // associated with the clause is OMPD_unknown and is generated
4878 // only once.
4879 if (CaptureRegion == ThisCaptureRegion ||
4880 CaptureRegion == OMPD_unknown) {
4881 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4882 for (Decl *D : DS->decls())
4883 SemaRef.MarkVariableReferenced(D->getLocation(),
4884 cast<VarDecl>(D));
4885 }
4886 }
4887 }
4888 }
4889 if (ThisCaptureRegion == OMPD_target) {
4890 // Capture allocator traits in the target region. They are used implicitly
4891 // and, thus, are not captured by default.
4892 for (OMPClause *C : Clauses) {
4893 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4894 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4895 ++I) {
4896 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4897 if (Expr *E = D.AllocatorTraits)
4898 SemaRef.MarkDeclarationsReferencedInExpr(E);
4899 }
4900 continue;
4901 }
4902 }
4903 }
4904 if (ThisCaptureRegion == OMPD_parallel) {
4905 // Capture temp arrays for inscan reductions and locals in aligned
4906 // clauses.
4907 for (OMPClause *C : Clauses) {
4908 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4909 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4910 continue;
4911 for (Expr *E : RC->copy_array_temps())
4912 if (E)
4913 SemaRef.MarkDeclarationsReferencedInExpr(E);
4914 }
4915 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4916 for (Expr *E : AC->varlist())
4917 SemaRef.MarkDeclarationsReferencedInExpr(E);
4918 }
4919 }
4920 }
4921 if (++CompletedRegions == CaptureRegions.size())
4922 DSAStack->setBodyComplete();
4923 SR = SemaRef.ActOnCapturedRegionEnd(SR.get());
4924 }
4925 return SR;
4926}
4927
4928static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4929 OpenMPDirectiveKind CancelRegion,
4930 SourceLocation StartLoc) {
4931 // CancelRegion is only needed for cancel and cancellation_point.
4932 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4933 return false;
4934
4935 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4936 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4937 return false;
4938
4939 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
4940 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4941 << getOpenMPDirectiveName(CancelRegion, OMPVersion);
4942 return true;
4943}
4944
4945static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4946 OpenMPDirectiveKind CurrentRegion,
4947 const DeclarationNameInfo &CurrentName,
4948 OpenMPDirectiveKind CancelRegion,
4949 OpenMPBindClauseKind BindKind,
4950 SourceLocation StartLoc) {
4951 if (!Stack->getCurScope())
4952 return false;
4953
4954 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4955 OpenMPDirectiveKind OffendingRegion = ParentRegion;
4956 bool NestingProhibited = false;
4957 bool CloseNesting = true;
4958 bool OrphanSeen = false;
4959 enum {
4960 NoRecommend,
4961 ShouldBeInParallelRegion,
4962 ShouldBeInOrderedRegion,
4963 ShouldBeInTargetRegion,
4964 ShouldBeInTeamsRegion,
4965 ShouldBeInLoopSimdRegion,
4966 } Recommend = NoRecommend;
4967
4970 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4971 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
4972 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
4973
4974 if (OMPVersion >= 50 && Stack->isParentOrderConcurrent() &&
4976 SemaRef.LangOpts)) {
4977 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
4978 << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
4979 return true;
4980 }
4981 if (isOpenMPSimdDirective(ParentRegion) &&
4982 ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered) ||
4983 (OMPVersion >= 50 && CurrentRegion != OMPD_ordered &&
4984 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4985 CurrentRegion != OMPD_scan))) {
4986 // OpenMP [2.16, Nesting of Regions]
4987 // OpenMP constructs may not be nested inside a simd region.
4988 // OpenMP [2.8.1,simd Construct, Restrictions]
4989 // An ordered construct with the simd clause is the only OpenMP
4990 // construct that can appear in the simd region.
4991 // Allowing a SIMD construct nested in another SIMD construct is an
4992 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
4993 // message.
4994 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
4995 // The only OpenMP constructs that can be encountered during execution of
4996 // a simd region are the atomic construct, the loop construct, the simd
4997 // construct and the ordered construct with the simd clause.
4998 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
4999 ? diag::err_omp_prohibited_region_simd
5000 : diag::warn_omp_nesting_simd)
5001 << (OMPVersion >= 50 ? 1 : 0);
5002 return CurrentRegion != OMPD_simd;
5003 }
5004 if (EnclosingConstruct == OMPD_atomic) {
5005 // OpenMP [2.16, Nesting of Regions]
5006 // OpenMP constructs may not be nested inside an atomic region.
5007 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
5008 return true;
5009 }
5010 if (CurrentRegion == OMPD_section) {
5011 // OpenMP [2.7.2, sections Construct, Restrictions]
5012 // Orphaned section directives are prohibited. That is, the section
5013 // directives must appear within the sections construct and must not be
5014 // encountered elsewhere in the sections region.
5015 if (EnclosingConstruct != OMPD_sections) {
5016 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
5017 << (ParentRegion != OMPD_unknown)
5018 << getOpenMPDirectiveName(ParentRegion, OMPVersion);
5019 return true;
5020 }
5021 return false;
5022 }
5023 // Allow some constructs (except teams and cancellation constructs) to be
5024 // orphaned (they could be used in functions, called from OpenMP regions
5025 // with the required preconditions).
5026 if (ParentRegion == OMPD_unknown &&
5027 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
5028 CurrentRegion != OMPD_cancellation_point &&
5029 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5030 return false;
5031 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
5032 // for a detailed explanation
5033 if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
5034 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
5035 (isOpenMPWorksharingDirective(ParentRegion) ||
5036 EnclosingConstruct == OMPD_loop)) {
5037 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
5038 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5039 << true << getOpenMPDirectiveName(ParentRegion, OMPVersion)
5040 << ErrorMsgNumber << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5041 return true;
5042 }
5043 if (CurrentRegion == OMPD_cancellation_point ||
5044 CurrentRegion == OMPD_cancel) {
5045 // OpenMP [2.16, Nesting of Regions]
5046 // A cancellation point construct for which construct-type-clause is
5047 // taskgroup must be nested inside a task construct. A cancellation
5048 // point construct for which construct-type-clause is not taskgroup must
5049 // be closely nested inside an OpenMP construct that matches the type
5050 // specified in construct-type-clause.
5051 // A cancel construct for which construct-type-clause is taskgroup must be
5052 // nested inside a task construct. A cancel construct for which
5053 // construct-type-clause is not taskgroup must be closely nested inside an
5054 // OpenMP construct that matches the type specified in
5055 // construct-type-clause.
5056 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(ParentRegion);
5057 if (CancelRegion == OMPD_taskgroup) {
5058 NestingProhibited =
5059 EnclosingConstruct != OMPD_task &&
5060 (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
5061 } else if (CancelRegion == OMPD_sections) {
5062 NestingProhibited = EnclosingConstruct != OMPD_section &&
5063 EnclosingConstruct != OMPD_sections;
5064 } else {
5065 NestingProhibited = CancelRegion != Leafs.back();
5066 }
5067 OrphanSeen = ParentRegion == OMPD_unknown;
5068 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5069 // OpenMP 5.1 [2.22, Nesting of Regions]
5070 // A masked region may not be closely nested inside a worksharing, loop,
5071 // atomic, task, or taskloop region.
5072 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5073 isOpenMPGenericLoopDirective(ParentRegion) ||
5074 isOpenMPTaskingDirective(ParentRegion);
5075 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5076 // OpenMP [2.16, Nesting of Regions]
5077 // A critical region may not be nested (closely or otherwise) inside a
5078 // critical region with the same name. Note that this restriction is not
5079 // sufficient to prevent deadlock.
5080 SourceLocation PreviousCriticalLoc;
5081 bool DeadLock = Stack->hasDirective(
5082 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5083 const DeclarationNameInfo &DNI,
5084 SourceLocation Loc) {
5085 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5086 PreviousCriticalLoc = Loc;
5087 return true;
5088 }
5089 return false;
5090 },
5091 false /* skip top directive */);
5092 if (DeadLock) {
5093 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
5094 << CurrentName.getName();
5095 if (PreviousCriticalLoc.isValid())
5096 SemaRef.Diag(PreviousCriticalLoc,
5097 diag::note_omp_previous_critical_region);
5098 return true;
5099 }
5100 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5101 // OpenMP 5.1 [2.22, Nesting of Regions]
5102 // A scope region may not be closely nested inside a worksharing, loop,
5103 // task, taskloop, critical, ordered, atomic, or masked region.
5104 // OpenMP 5.1 [2.22, Nesting of Regions]
5105 // A barrier region may not be closely nested inside a worksharing, loop,
5106 // task, taskloop, critical, ordered, atomic, or masked region.
5107 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5108 isOpenMPGenericLoopDirective(ParentRegion) ||
5109 isOpenMPTaskingDirective(ParentRegion) ||
5110 llvm::is_contained({OMPD_masked, OMPD_master,
5111 OMPD_critical, OMPD_ordered},
5112 EnclosingConstruct);
5113 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
5114 !isOpenMPParallelDirective(CurrentRegion) &&
5115 !isOpenMPTeamsDirective(CurrentRegion)) {
5116 // OpenMP 5.1 [2.22, Nesting of Regions]
5117 // A loop region that binds to a parallel region or a worksharing region
5118 // may not be closely nested inside a worksharing, loop, task, taskloop,
5119 // critical, ordered, atomic, or masked region.
5120 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5121 isOpenMPGenericLoopDirective(ParentRegion) ||
5122 isOpenMPTaskingDirective(ParentRegion) ||
5123 llvm::is_contained({OMPD_masked, OMPD_master,
5124 OMPD_critical, OMPD_ordered},
5125 EnclosingConstruct);
5126 Recommend = ShouldBeInParallelRegion;
5127 } else if (CurrentRegion == OMPD_ordered) {
5128 // OpenMP [2.16, Nesting of Regions]
5129 // An ordered region may not be closely nested inside a critical,
5130 // atomic, or explicit task region.
5131 // An ordered region must be closely nested inside a loop region (or
5132 // parallel loop region) with an ordered clause.
5133 // OpenMP [2.8.1,simd Construct, Restrictions]
5134 // An ordered construct with the simd clause is the only OpenMP construct
5135 // that can appear in the simd region.
5136 NestingProhibited = EnclosingConstruct == OMPD_critical ||
5137 isOpenMPTaskingDirective(ParentRegion) ||
5138 !(isOpenMPSimdDirective(ParentRegion) ||
5139 Stack->isParentOrderedRegion());
5140 Recommend = ShouldBeInOrderedRegion;
5141 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
5142 // OpenMP [2.16, Nesting of Regions]
5143 // If specified, a teams construct must be contained within a target
5144 // construct.
5145 NestingProhibited =
5146 (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
5147 (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
5148 EnclosingConstruct != OMPD_target);
5149 OrphanSeen = ParentRegion == OMPD_unknown;
5150 Recommend = ShouldBeInTargetRegion;
5151 } else if (CurrentRegion == OMPD_scan) {
5152 if (OMPVersion >= 50) {
5153 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
5154 // simd, or for simd. This has to take into account combined directives.
5155 // In 5.2 this seems to be implied by the fact that the specified
5156 // separated constructs are do, for, and simd.
5157 NestingProhibited = !llvm::is_contained(
5158 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
5159 } else {
5160 NestingProhibited = true;
5161 }
5162 OrphanSeen = ParentRegion == OMPD_unknown;
5163 Recommend = ShouldBeInLoopSimdRegion;
5164 }
5165 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5166 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5167 EnclosingConstruct == OMPD_teams) {
5168 // OpenMP [5.1, 2.22, Nesting of Regions]
5169 // distribute, distribute simd, distribute parallel worksharing-loop,
5170 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5171 // including any parallel regions arising from combined constructs,
5172 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5173 // only OpenMP regions that may be strictly nested inside the teams
5174 // region.
5175 //
5176 // As an extension, we permit atomic within teams as well.
5177 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5178 !isOpenMPDistributeDirective(CurrentRegion) &&
5179 CurrentRegion != OMPD_loop &&
5180 !(SemaRef.getLangOpts().OpenMPExtensions &&
5181 CurrentRegion == OMPD_atomic);
5182 Recommend = ShouldBeInParallelRegion;
5183 }
5184 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5185 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5186 // If the bind clause is present on the loop construct and binding is
5187 // teams then the corresponding loop region must be strictly nested inside
5188 // a teams region.
5189 NestingProhibited =
5190 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5191 Recommend = ShouldBeInTeamsRegion;
5192 }
5193 if (!NestingProhibited && isOpenMPNestingDistributeDirective(CurrentRegion)) {
5194 // OpenMP 4.5 [2.17 Nesting of Regions]
5195 // The region associated with the distribute construct must be strictly
5196 // nested inside a teams region
5197 NestingProhibited = EnclosingConstruct != OMPD_teams;
5198 Recommend = ShouldBeInTeamsRegion;
5199 }
5200 if (!NestingProhibited &&
5201 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5202 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5203 // OpenMP 4.5 [2.17 Nesting of Regions]
5204 // If a target, target update, target data, target enter data, or
5205 // target exit data construct is encountered during execution of a
5206 // target region, the behavior is unspecified.
5207 NestingProhibited = Stack->hasDirective(
5208 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5211 OffendingRegion = K;
5212 return true;
5213 }
5214 return false;
5215 },
5216 false /* don't skip top directive */);
5217 CloseNesting = false;
5218 }
5219 if (NestingProhibited) {
5220 if (OrphanSeen) {
5221 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5222 << getOpenMPDirectiveName(CurrentRegion, OMPVersion) << Recommend;
5223 } else {
5224 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5225 << CloseNesting << getOpenMPDirectiveName(OffendingRegion, OMPVersion)
5226 << Recommend << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5227 }
5228 return true;
5229 }
5230 return false;
5231}
5232
5238 ArrayRef<OMPClause *> Clauses,
5239 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5240 bool ErrorFound = false;
5241 unsigned NamedModifiersNumber = 0;
5242 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5243 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5244 SmallVector<SourceLocation, 4> NameModifierLoc;
5245 unsigned OMPVersion = S.getLangOpts().OpenMP;
5246 for (const OMPClause *C : Clauses) {
5247 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5248 // At most one if clause without a directive-name-modifier can appear on
5249 // the directive.
5250 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5251 auto &FNM = FoundNameModifiers[CurNM];
5252 if (FNM) {
5253 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5254 << getOpenMPDirectiveName(Kind, OMPVersion)
5255 << getOpenMPClauseNameForDiag(OMPC_if) << (CurNM != OMPD_unknown)
5256 << getOpenMPDirectiveName(CurNM, OMPVersion);
5257 ErrorFound = true;
5258 } else if (CurNM != OMPD_unknown) {
5259 NameModifierLoc.push_back(IC->getNameModifierLoc());
5260 ++NamedModifiersNumber;
5261 }
5262 FNM = IC;
5263 if (CurNM == OMPD_unknown)
5264 continue;
5265 // Check if the specified name modifier is allowed for the current
5266 // directive.
5267 // At most one if clause with the particular directive-name-modifier can
5268 // appear on the directive.
5269 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5270 S.Diag(IC->getNameModifierLoc(),
5271 diag::err_omp_wrong_if_directive_name_modifier)
5272 << getOpenMPDirectiveName(CurNM, OMPVersion)
5273 << getOpenMPDirectiveName(Kind, OMPVersion);
5274 ErrorFound = true;
5275 }
5276 }
5277 }
5278 // If any if clause on the directive includes a directive-name-modifier then
5279 // all if clauses on the directive must include a directive-name-modifier.
5280 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5281 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5282 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5283 diag::err_omp_no_more_if_clause);
5284 } else {
5285 std::string Values;
5286 std::string Sep(", ");
5287 unsigned AllowedCnt = 0;
5288 unsigned TotalAllowedNum =
5289 AllowedNameModifiers.size() - NamedModifiersNumber;
5290 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5291 ++Cnt) {
5292 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5293 if (!FoundNameModifiers[NM]) {
5294 Values += "'";
5295 Values += getOpenMPDirectiveName(NM, OMPVersion);
5296 Values += "'";
5297 if (AllowedCnt + 2 == TotalAllowedNum)
5298 Values += " or ";
5299 else if (AllowedCnt + 1 != TotalAllowedNum)
5300 Values += Sep;
5301 ++AllowedCnt;
5302 }
5303 }
5304 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5305 diag::err_omp_unnamed_if_clause)
5306 << (TotalAllowedNum > 1) << Values;
5307 }
5308 for (SourceLocation Loc : NameModifierLoc) {
5309 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5310 }
5311 ErrorFound = true;
5312 }
5313 return ErrorFound;
5314}
5315
5316static std::pair<ValueDecl *, bool>
5318 SourceRange &ERange, bool AllowArraySection,
5319 bool AllowAssumedSizeArray, StringRef DiagType) {
5320 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5322 return std::make_pair(nullptr, true);
5323
5324 // OpenMP [3.1, C/C++]
5325 // A list item is a variable name.
5326 // OpenMP [2.9.3.3, Restrictions, p.1]
5327 // A variable that is part of another variable (as an array or
5328 // structure element) cannot appear in a private clause.
5329 //
5330 // OpenMP [6.0]
5331 // 5.2.5 Array Sections, p. 166, L28-29
5332 // When the length is absent and the size of the dimension is not known,
5333 // the array section is an assumed-size array.
5334 // 2 Glossary, p. 23, L4-6
5335 // assumed-size array
5336 // For C/C++, an array section for which the length is absent and the
5337 // size of the dimensions is not known.
5338 // 5.2.5 Array Sections, p. 168, L11
5339 // An assumed-size array can appear only in clauses for which it is
5340 // explicitly allowed.
5341 // 7.4 List Item Privatization, Restrictions, p. 222, L15
5342 // Assumed-size arrays must not be privatized.
5343 RefExpr = RefExpr->IgnoreParens();
5344 enum {
5345 NoArrayExpr = -1,
5346 ArraySubscript = 0,
5347 OMPArraySection = 1
5348 } IsArrayExpr = NoArrayExpr;
5349 if (AllowArraySection) {
5350 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5351 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5352 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5353 Base = TempASE->getBase()->IgnoreParenImpCasts();
5354 RefExpr = Base;
5355 IsArrayExpr = ArraySubscript;
5356 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5357 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5358 if (S.getLangOpts().OpenMP >= 60 && !AllowAssumedSizeArray &&
5359 OASE->getColonLocFirst().isValid() && !OASE->getLength()) {
5361 if (BaseType.isNull() || (!BaseType->isConstantArrayType() &&
5362 !BaseType->isVariableArrayType())) {
5363 S.Diag(OASE->getColonLocFirst(),
5364 diag::err_omp_section_length_undefined)
5365 << (!BaseType.isNull() && BaseType->isArrayType());
5366 return std::make_pair(nullptr, false);
5367 }
5368 }
5369 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Base))
5370 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5371 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5372 Base = TempASE->getBase()->IgnoreParenImpCasts();
5373 RefExpr = Base;
5374 IsArrayExpr = OMPArraySection;
5375 }
5376 }
5377 ELoc = RefExpr->getExprLoc();
5378 ERange = RefExpr->getSourceRange();
5379 RefExpr = RefExpr->IgnoreParenImpCasts();
5380 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5381 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5382 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5383 (S.getCurrentThisType().isNull() || !ME ||
5384 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5385 !isa<FieldDecl>(ME->getMemberDecl()))) {
5386 if (IsArrayExpr != NoArrayExpr) {
5387 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5388 << IsArrayExpr << ERange;
5389 } else if (!DiagType.empty()) {
5390 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5391 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5392 : 0;
5393 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5394 << DiagSelect << DiagType << ERange;
5395 } else {
5396 S.Diag(ELoc,
5397 AllowArraySection
5398 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5399 : diag::err_omp_expected_var_name_member_expr)
5400 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5401 }
5402 return std::make_pair(nullptr, false);
5403 }
5404 return std::make_pair(
5405 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5406}
5407
5408namespace {
5409/// Checks if the allocator is used in uses_allocators clause to be allowed in
5410/// target regions.
5411class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5412 DSAStackTy *S = nullptr;
5413
5414public:
5415 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5416 return S->isUsesAllocatorsDecl(E->getDecl())
5417 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5418 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5419 }
5420 bool VisitStmt(const Stmt *S) {
5421 for (const Stmt *Child : S->children()) {
5422 if (Child && Visit(Child))
5423 return true;
5424 }
5425 return false;
5426 }
5427 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5428};
5429} // namespace
5430
5431static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5432 ArrayRef<OMPClause *> Clauses) {
5433 assert(!S.CurContext->isDependentContext() &&
5434 "Expected non-dependent context.");
5435 auto AllocateRange =
5436 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5437 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5438 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5439 return isOpenMPPrivate(C->getClauseKind());
5440 });
5441 for (OMPClause *Cl : PrivateRange) {
5443 if (Cl->getClauseKind() == OMPC_private) {
5444 auto *PC = cast<OMPPrivateClause>(Cl);
5445 I = PC->private_copies().begin();
5446 It = PC->varlist_begin();
5447 Et = PC->varlist_end();
5448 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5449 auto *PC = cast<OMPFirstprivateClause>(Cl);
5450 I = PC->private_copies().begin();
5451 It = PC->varlist_begin();
5452 Et = PC->varlist_end();
5453 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5454 auto *PC = cast<OMPLastprivateClause>(Cl);
5455 I = PC->private_copies().begin();
5456 It = PC->varlist_begin();
5457 Et = PC->varlist_end();
5458 } else if (Cl->getClauseKind() == OMPC_linear) {
5459 auto *PC = cast<OMPLinearClause>(Cl);
5460 I = PC->privates().begin();
5461 It = PC->varlist_begin();
5462 Et = PC->varlist_end();
5463 } else if (Cl->getClauseKind() == OMPC_reduction) {
5464 auto *PC = cast<OMPReductionClause>(Cl);
5465 I = PC->privates().begin();
5466 It = PC->varlist_begin();
5467 Et = PC->varlist_end();
5468 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5469 auto *PC = cast<OMPTaskReductionClause>(Cl);
5470 I = PC->privates().begin();
5471 It = PC->varlist_begin();
5472 Et = PC->varlist_end();
5473 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5474 auto *PC = cast<OMPInReductionClause>(Cl);
5475 I = PC->privates().begin();
5476 It = PC->varlist_begin();
5477 Et = PC->varlist_end();
5478 } else {
5479 llvm_unreachable("Expected private clause.");
5480 }
5481 for (Expr *E : llvm::make_range(It, Et)) {
5482 if (!*I) {
5483 ++I;
5484 continue;
5485 }
5486 SourceLocation ELoc;
5487 SourceRange ERange;
5488 Expr *SimpleRefExpr = E;
5489 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5490 /*AllowArraySection=*/true);
5491 DeclToCopy.try_emplace(Res.first,
5492 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5493 ++I;
5494 }
5495 }
5496 for (OMPClause *C : AllocateRange) {
5497 auto *AC = cast<OMPAllocateClause>(C);
5498 if (S.getLangOpts().OpenMP >= 50 &&
5499 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5500 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5501 AC->getAllocator()) {
5502 Expr *Allocator = AC->getAllocator();
5503 // OpenMP, 2.12.5 target Construct
5504 // Memory allocators that do not appear in a uses_allocators clause cannot
5505 // appear as an allocator in an allocate clause or be used in the target
5506 // region unless a requires directive with the dynamic_allocators clause
5507 // is present in the same compilation unit.
5508 AllocatorChecker Checker(Stack);
5509 if (Checker.Visit(Allocator))
5510 S.Diag(Allocator->getExprLoc(),
5511 diag::err_omp_allocator_not_in_uses_allocators)
5512 << Allocator->getSourceRange();
5513 }
5514 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5515 getAllocatorKind(S, Stack, AC->getAllocator());
5516 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5517 // For task, taskloop or target directives, allocation requests to memory
5518 // allocators with the trait access set to thread result in unspecified
5519 // behavior.
5520 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5521 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5522 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5523 unsigned OMPVersion = S.getLangOpts().OpenMP;
5524 S.Diag(AC->getAllocator()->getExprLoc(),
5525 diag::warn_omp_allocate_thread_on_task_target_directive)
5526 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
5527 }
5528 for (Expr *E : AC->varlist()) {
5529 SourceLocation ELoc;
5530 SourceRange ERange;
5531 Expr *SimpleRefExpr = E;
5532 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5533 ValueDecl *VD = Res.first;
5534 if (!VD)
5535 continue;
5536 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5537 if (!isOpenMPPrivate(Data.CKind)) {
5538 S.Diag(E->getExprLoc(),
5539 diag::err_omp_expected_private_copy_for_allocate);
5540 continue;
5541 }
5542 VarDecl *PrivateVD = DeclToCopy[VD];
5543 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5544 AllocatorKind, AC->getAllocator()))
5545 continue;
5546 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5547 AC->getAlignment(), E->getSourceRange());
5548 }
5549 }
5550}
5551
5552namespace {
5553/// Rewrite statements and expressions for Sema \p Actions CurContext.
5554///
5555/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5556/// context. DeclRefExpr used inside the new context are changed to refer to the
5557/// captured variable instead.
5558class CaptureVars : public TreeTransform<CaptureVars> {
5559 using BaseTransform = TreeTransform<CaptureVars>;
5560
5561public:
5562 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5563
5564 bool AlwaysRebuild() { return true; }
5565};
5566} // namespace
5567
5568static VarDecl *precomputeExpr(Sema &Actions,
5569 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5570 StringRef Name) {
5571 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5572 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5573 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5574 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5575 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5576 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5577 BodyStmts.push_back(NewDeclStmt);
5578 return NewVar;
5579}
5580
5581/// Create a closure that computes the number of iterations of a loop.
5582///
5583/// \param Actions The Sema object.
5584/// \param LogicalTy Type for the logical iteration number.
5585/// \param Rel Comparison operator of the loop condition.
5586/// \param StartExpr Value of the loop counter at the first iteration.
5587/// \param StopExpr Expression the loop counter is compared against in the loop
5588/// condition. \param StepExpr Amount of increment after each iteration.
5589///
5590/// \return Closure (CapturedStmt) of the distance calculation.
5591static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5593 Expr *StartExpr, Expr *StopExpr,
5594 Expr *StepExpr) {
5595 ASTContext &Ctx = Actions.getASTContext();
5596 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5597
5598 // Captured regions currently don't support return values, we use an
5599 // out-parameter instead. All inputs are implicit captures.
5600 // TODO: Instead of capturing each DeclRefExpr occurring in
5601 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5602 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5603 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5604 {StringRef(), QualType()}};
5605 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5606
5607 Stmt *Body;
5608 {
5609 Sema::CompoundScopeRAII CompoundScope(Actions);
5611
5612 // Get the LValue expression for the result.
5613 ImplicitParamDecl *DistParam = CS->getParam(0);
5614 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5615 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5616
5617 SmallVector<Stmt *, 4> BodyStmts;
5618
5619 // Capture all referenced variable references.
5620 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5621 // CapturedStmt, we could compute them before and capture the result, to be
5622 // used jointly with the LoopVar function.
5623 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5624 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5625 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5626 auto BuildVarRef = [&](VarDecl *VD) {
5627 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5628 };
5629
5631 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5633 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5634 Expr *Dist;
5635 if (Rel == BO_NE) {
5636 // When using a != comparison, the increment can be +1 or -1. This can be
5637 // dynamic at runtime, so we need to check for the direction.
5638 Expr *IsNegStep = AssertSuccess(
5639 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5640
5641 // Positive increment.
5642 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5643 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5644 ForwardRange = AssertSuccess(
5645 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5646 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5647 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5648
5649 // Negative increment.
5650 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5651 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5652 BackwardRange = AssertSuccess(
5653 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5654 Expr *NegIncAmount = AssertSuccess(
5655 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5656 Expr *BackwardDist = AssertSuccess(
5657 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5658
5659 // Use the appropriate case.
5660 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5661 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5662 } else {
5663 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5664 "Expected one of these relational operators");
5665
5666 // We can derive the direction from any other comparison operator. It is
5667 // non well-formed OpenMP if Step increments/decrements in the other
5668 // directions. Whether at least the first iteration passes the loop
5669 // condition.
5670 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5671 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5672
5673 // Compute the range between first and last counter value.
5674 Expr *Range;
5675 if (Rel == BO_GE || Rel == BO_GT)
5676 Range = AssertSuccess(Actions.BuildBinOp(
5677 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5678 else
5679 Range = AssertSuccess(Actions.BuildBinOp(
5680 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5681
5682 // Ensure unsigned range space.
5683 Range =
5684 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5685
5686 if (Rel == BO_LE || Rel == BO_GE) {
5687 // Add one to the range if the relational operator is inclusive.
5688 Range =
5689 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5690 }
5691
5692 // Divide by the absolute step amount. If the range is not a multiple of
5693 // the step size, rounding-up the effective upper bound ensures that the
5694 // last iteration is included.
5695 // Note that the rounding-up may cause an overflow in a temporary that
5696 // could be avoided, but would have occurred in a C-style for-loop as
5697 // well.
5698 Expr *Divisor = BuildVarRef(NewStep);
5699 if (Rel == BO_GE || Rel == BO_GT)
5700 Divisor =
5701 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5702 Expr *DivisorMinusOne =
5703 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5704 Expr *RangeRoundUp = AssertSuccess(
5705 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5706 Dist = AssertSuccess(
5707 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5708
5709 // If there is not at least one iteration, the range contains garbage. Fix
5710 // to zero in this case.
5711 Dist = AssertSuccess(
5712 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5713 }
5714
5715 // Assign the result to the out-parameter.
5716 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5717 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5718 BodyStmts.push_back(ResultAssign);
5719
5720 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5721 }
5722
5723 return cast<CapturedStmt>(
5724 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5725}
5726
5727/// Create a closure that computes the loop variable from the logical iteration
5728/// number.
5729///
5730/// \param Actions The Sema object.
5731/// \param LoopVarTy Type for the loop variable used for result value.
5732/// \param LogicalTy Type for the logical iteration number.
5733/// \param StartExpr Value of the loop counter at the first iteration.
5734/// \param Step Amount of increment after each iteration.
5735/// \param Deref Whether the loop variable is a dereference of the loop
5736/// counter variable.
5737///
5738/// \return Closure (CapturedStmt) of the loop value calculation.
5739static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5740 QualType LogicalTy,
5741 DeclRefExpr *StartExpr, Expr *Step,
5742 bool Deref) {
5743 ASTContext &Ctx = Actions.getASTContext();
5744
5745 // Pass the result as an out-parameter. Passing as return value would require
5746 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5747 // invoke a copy constructor.
5748 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5749 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5750 {"Logical", LogicalTy},
5751 {StringRef(), QualType()}};
5752 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5753
5754 // Capture the initial iterator which represents the LoopVar value at the
5755 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5756 // it in every iteration, capture it by value before it is modified.
5757 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5758 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5760 (void)Invalid;
5761 assert(!Invalid && "Expecting capture-by-value to work.");
5762
5763 Expr *Body;
5764 {
5765 Sema::CompoundScopeRAII CompoundScope(Actions);
5766 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5767
5768 ImplicitParamDecl *TargetParam = CS->getParam(0);
5769 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5770 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5771 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5772 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5773 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5774
5775 // Capture the Start expression.
5776 CaptureVars Recap(Actions);
5777 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5778 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5779
5781 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5782 // TODO: Explicitly cast to the iterator's difference_type instead of
5783 // relying on implicit conversion.
5784 Expr *Advanced =
5785 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5786
5787 if (Deref) {
5788 // For range-based for-loops convert the loop counter value to a concrete
5789 // loop variable value by dereferencing the iterator.
5790 Advanced =
5791 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5792 }
5793
5794 // Assign the result to the output parameter.
5795 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5796 BO_Assign, TargetRef, Advanced));
5797 }
5798 return cast<CapturedStmt>(
5799 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5800}
5801
5803 ASTContext &Ctx = getASTContext();
5804
5805 // Extract the common elements of ForStmt and CXXForRangeStmt:
5806 // Loop variable, repeat condition, increment
5807 Expr *Cond, *Inc;
5808 VarDecl *LIVDecl, *LUVDecl;
5809 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5810 Stmt *Init = For->getInit();
5811 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5812 // For statement declares loop variable.
5813 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5814 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5815 // For statement reuses variable.
5816 assert(LCAssign->getOpcode() == BO_Assign &&
5817 "init part must be a loop variable assignment");
5818 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5819 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5820 } else
5821 llvm_unreachable("Cannot determine loop variable");
5822 LUVDecl = LIVDecl;
5823
5824 Cond = For->getCond();
5825 Inc = For->getInc();
5826 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5827 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5828 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5829 LUVDecl = RangeFor->getLoopVariable();
5830
5831 Cond = RangeFor->getCond();
5832 Inc = RangeFor->getInc();
5833 } else
5834 llvm_unreachable("unhandled kind of loop");
5835
5836 QualType CounterTy = LIVDecl->getType();
5837 QualType LVTy = LUVDecl->getType();
5838
5839 // Analyze the loop condition.
5840 Expr *LHS, *RHS;
5841 BinaryOperator::Opcode CondRel;
5842 Cond = Cond->IgnoreImplicit();
5843 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5844 LHS = CondBinExpr->getLHS();
5845 RHS = CondBinExpr->getRHS();
5846 CondRel = CondBinExpr->getOpcode();
5847 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5848 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5849 LHS = CondCXXOp->getArg(0);
5850 RHS = CondCXXOp->getArg(1);
5851 switch (CondCXXOp->getOperator()) {
5852 case OO_ExclaimEqual:
5853 CondRel = BO_NE;
5854 break;
5855 case OO_Less:
5856 CondRel = BO_LT;
5857 break;
5858 case OO_LessEqual:
5859 CondRel = BO_LE;
5860 break;
5861 case OO_Greater:
5862 CondRel = BO_GT;
5863 break;
5864 case OO_GreaterEqual:
5865 CondRel = BO_GE;
5866 break;
5867 default:
5868 llvm_unreachable("unexpected iterator operator");
5869 }
5870 } else
5871 llvm_unreachable("unexpected loop condition");
5872
5873 // Normalize such that the loop counter is on the LHS.
5874 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5875 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5876 std::swap(LHS, RHS);
5877 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5878 }
5879 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5880
5881 // Decide the bit width for the logical iteration counter. By default use the
5882 // unsigned ptrdiff_t integer size (for iterators and pointers).
5883 // TODO: For iterators, use iterator::difference_type,
5884 // std::iterator_traits<>::difference_type or decltype(it - end).
5885 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5886 if (CounterTy->isIntegerType()) {
5887 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5888 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5889 }
5890
5891 // Analyze the loop increment.
5892 Expr *Step;
5893 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5894 int Direction;
5895 switch (IncUn->getOpcode()) {
5896 case UO_PreInc:
5897 case UO_PostInc:
5898 Direction = 1;
5899 break;
5900 case UO_PreDec:
5901 case UO_PostDec:
5902 Direction = -1;
5903 break;
5904 default:
5905 llvm_unreachable("unhandled unary increment operator");
5906 }
5908 Ctx,
5909 llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction, /*isSigned=*/true),
5910 LogicalTy, {});
5911 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5912 if (IncBin->getOpcode() == BO_AddAssign) {
5913 Step = IncBin->getRHS();
5914 } else if (IncBin->getOpcode() == BO_SubAssign) {
5915 Step = AssertSuccess(
5916 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5917 } else
5918 llvm_unreachable("unhandled binary increment operator");
5919 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5920 switch (CondCXXOp->getOperator()) {
5921 case OO_PlusPlus:
5923 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5924 break;
5925 case OO_MinusMinus:
5927 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5928 break;
5929 case OO_PlusEqual:
5930 Step = CondCXXOp->getArg(1);
5931 break;
5932 case OO_MinusEqual:
5933 Step = AssertSuccess(
5934 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5935 break;
5936 default:
5937 llvm_unreachable("unhandled overloaded increment operator");
5938 }
5939 } else
5940 llvm_unreachable("unknown increment expression");
5941
5942 CapturedStmt *DistanceFunc =
5943 buildDistanceFunc(SemaRef, LogicalTy, CondRel, LHS, RHS, Step);
5944 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5945 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5946 DeclRefExpr *LVRef =
5947 SemaRef.BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue, {},
5948 nullptr, nullptr, {}, nullptr);
5949 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
5950 LoopVarFunc, LVRef);
5951}
5952
5954 // Handle a literal loop.
5955 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5956 return ActOnOpenMPCanonicalLoop(AStmt);
5957
5958 // If not a literal loop, it must be the result of a loop transformation.
5960 assert(
5961 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
5962 "Loop transformation directive expected");
5963 return LoopTransform;
5964}
5965
5967 CXXScopeSpec &MapperIdScopeSpec,
5968 const DeclarationNameInfo &MapperId,
5969 QualType Type,
5970 Expr *UnresolvedMapper);
5971
5972/// Perform DFS through the structure/class data members trying to find
5973/// member(s) with user-defined 'default' mapper and generate implicit map
5974/// clauses for such members with the found 'default' mapper.
5975static void
5978 // Check for the default mapper for data members.
5979 if (S.getLangOpts().OpenMP < 50)
5980 return;
5981 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5982 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5983 if (!C)
5984 continue;
5985 SmallVector<Expr *, 4> SubExprs;
5986 auto *MI = C->mapperlist_begin();
5987 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
5988 ++I, ++MI) {
5989 // Expression is mapped using mapper - skip it.
5990 if (*MI)
5991 continue;
5992 Expr *E = *I;
5993 // Expression is dependent - skip it, build the mapper when it gets
5994 // instantiated.
5995 if (E->isTypeDependent() || E->isValueDependent() ||
5997 continue;
5998 // Array section - need to check for the mapping of the array section
5999 // element.
6000 QualType CanonType = E->getType().getCanonicalType();
6001 if (CanonType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
6002 const auto *OASE = cast<ArraySectionExpr>(E->IgnoreParenImpCasts());
6003 QualType BaseType =
6005 QualType ElemType;
6006 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6007 ElemType = ATy->getElementType();
6008 else
6009 ElemType = BaseType->getPointeeType();
6010 CanonType = ElemType;
6011 }
6012
6013 // DFS over data members in structures/classes.
6015 1, {CanonType, nullptr});
6016 llvm::DenseMap<const Type *, Expr *> Visited;
6018 1, {nullptr, 1});
6019 while (!Types.empty()) {
6020 QualType BaseType;
6021 FieldDecl *CurFD;
6022 std::tie(BaseType, CurFD) = Types.pop_back_val();
6023 while (ParentChain.back().second == 0)
6024 ParentChain.pop_back();
6025 --ParentChain.back().second;
6026 if (BaseType.isNull())
6027 continue;
6028 // Only structs/classes are allowed to have mappers.
6029 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6030 if (!RD)
6031 continue;
6032 auto It = Visited.find(BaseType.getTypePtr());
6033 if (It == Visited.end()) {
6034 // Try to find the associated user-defined mapper.
6035 CXXScopeSpec MapperIdScopeSpec;
6036 DeclarationNameInfo DefaultMapperId;
6038 &S.Context.Idents.get("default")));
6039 DefaultMapperId.setLoc(E->getExprLoc());
6041 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
6042 BaseType, /*UnresolvedMapper=*/nullptr);
6043 if (ER.isInvalid())
6044 continue;
6045 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
6046 }
6047 // Found default mapper.
6048 if (It->second) {
6049 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
6051 OE->setIsUnique(/*V=*/true);
6052 Expr *BaseExpr = OE;
6053 for (const auto &P : ParentChain) {
6054 if (P.first) {
6055 BaseExpr = S.BuildMemberExpr(
6056 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6058 DeclAccessPair::make(P.first, P.first->getAccess()),
6059 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6060 P.first->getType(), VK_LValue, OK_Ordinary);
6061 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
6062 }
6063 }
6064 if (CurFD)
6065 BaseExpr = S.BuildMemberExpr(
6066 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6068 DeclAccessPair::make(CurFD, CurFD->getAccess()),
6069 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6070 CurFD->getType(), VK_LValue, OK_Ordinary);
6071 SubExprs.push_back(BaseExpr);
6072 continue;
6073 }
6074 // Check for the "default" mapper for data members.
6075 bool FirstIter = true;
6076 for (FieldDecl *FD : RD->fields()) {
6077 if (!FD)
6078 continue;
6079 QualType FieldTy = FD->getType();
6080 if (FieldTy.isNull() ||
6081 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6082 continue;
6083 if (FirstIter) {
6084 FirstIter = false;
6085 ParentChain.emplace_back(CurFD, 1);
6086 } else {
6087 ++ParentChain.back().second;
6088 }
6089 Types.emplace_back(FieldTy, FD);
6090 }
6091 }
6092 }
6093 if (SubExprs.empty())
6094 continue;
6095 CXXScopeSpec MapperIdScopeSpec;
6096 DeclarationNameInfo MapperId;
6097 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
6098 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
6099 MapperIdScopeSpec, MapperId, C->getMapType(),
6100 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6101 SubExprs, OMPVarListLocTy()))
6102 Clauses.push_back(NewClause);
6103 }
6104}
6105
6106namespace {
6107/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
6108/// call in the associated loop-nest cannot be a 'parallel for'.
6109class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
6110 Sema &SemaRef;
6111
6112public:
6113 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
6114
6115 // Is there a nested OpenMP loop bind(parallel)
6116 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
6117 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
6118 if (const auto *C = D->getSingleClause<OMPBindClause>())
6119 if (C->getBindKind() == OMPC_BIND_parallel) {
6120 TeamsLoopCanBeParallelFor = false;
6121 // No need to continue visiting any more
6122 return;
6123 }
6124 }
6125 for (const Stmt *Child : D->children())
6126 if (Child)
6127 Visit(Child);
6128 }
6129
6130 void VisitCallExpr(const CallExpr *C) {
6131 // Function calls inhibit parallel loop translation of 'target teams loop'
6132 // unless the assume-no-nested-parallelism flag has been specified.
6133 // OpenMP API runtime library calls do not inhibit parallel loop
6134 // translation, regardless of the assume-no-nested-parallelism.
6135 bool IsOpenMPAPI = false;
6136 auto *FD = dyn_cast_or_null<FunctionDecl>(C->getCalleeDecl());
6137 if (FD) {
6138 std::string Name = FD->getNameInfo().getAsString();
6139 IsOpenMPAPI = Name.find("omp_") == 0;
6140 }
6141 TeamsLoopCanBeParallelFor =
6142 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
6143 if (!TeamsLoopCanBeParallelFor)
6144 return;
6145
6146 for (const Stmt *Child : C->children())
6147 if (Child)
6148 Visit(Child);
6149 }
6150
6151 void VisitCapturedStmt(const CapturedStmt *S) {
6152 if (!S)
6153 return;
6154 Visit(S->getCapturedDecl()->getBody());
6155 }
6156
6157 void VisitStmt(const Stmt *S) {
6158 if (!S)
6159 return;
6160 for (const Stmt *Child : S->children())
6161 if (Child)
6162 Visit(Child);
6163 }
6164 explicit TeamsLoopChecker(Sema &SemaRef)
6165 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
6166
6167private:
6168 bool TeamsLoopCanBeParallelFor;
6169};
6170} // namespace
6171
6172static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
6173 TeamsLoopChecker Checker(SemaRef);
6174 Checker.Visit(AStmt);
6175 return Checker.teamsLoopCanBeParallelFor();
6176}
6177
6179 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6180 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6181 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
6182 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
6183
6184 StmtResult Res = StmtError();
6186 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6187
6188 if (const OMPBindClause *BC =
6189 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6190 BindKind = BC->getBindKind();
6191
6192 if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
6193 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
6194
6195 // Setting the enclosing teams or parallel construct for the loop
6196 // directive without bind clause.
6197 // [5.0:129:25-28] If the bind clause is not present on the construct and
6198 // the loop construct is closely nested inside a teams or parallel
6199 // construct, the binding region is the corresponding teams or parallel
6200 // region. If none of those conditions hold, the binding region is not
6201 // defined.
6202 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6203 ArrayRef<OpenMPDirectiveKind> ParentLeafs =
6204 getLeafConstructsOrSelf(ParentDirective);
6205
6206 if (ParentDirective == OMPD_unknown) {
6207 Diag(DSAStack->getDefaultDSALocation(),
6208 diag::err_omp_bind_required_on_loop);
6209 } else if (ParentLeafs.back() == OMPD_parallel) {
6210 BindKind = OMPC_BIND_parallel;
6211 } else if (ParentLeafs.back() == OMPD_teams) {
6212 BindKind = OMPC_BIND_teams;
6213 }
6214
6215 assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind");
6216
6217 OMPClause *C =
6220 ClausesWithImplicit.push_back(C);
6221 }
6222
6223 // Diagnose "loop bind(teams)" with "reduction".
6224 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6225 for (OMPClause *C : Clauses) {
6226 if (C->getClauseKind() == OMPC_reduction)
6227 Diag(DSAStack->getDefaultDSALocation(),
6228 diag::err_omp_loop_reduction_clause);
6229 }
6230 }
6231
6232 // First check CancelRegion which is then used in checkNestingOfRegions.
6233 if (checkCancelRegion(SemaRef, Kind, CancelRegion, StartLoc) ||
6234 checkNestingOfRegions(SemaRef, DSAStack, Kind, DirName, CancelRegion,
6235 BindKind, StartLoc)) {
6236 return StmtError();
6237 }
6238
6239 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6242 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6243
6244 VarsWithInheritedDSAType VarsWithInheritedDSA;
6245 bool ErrorFound = false;
6246 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6247
6248 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6250 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6251
6252 // Check default data sharing attributes for referenced variables.
6253 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(AStmt));
6254 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6255 Stmt *S = AStmt;
6256 while (--ThisCaptureLevel >= 0)
6257 S = cast<CapturedStmt>(S)->getCapturedStmt();
6258 DSAChecker.Visit(S);
6260 !isOpenMPTaskingDirective(Kind)) {
6261 // Visit subcaptures to generate implicit clauses for captured vars.
6262 auto *CS = cast<CapturedStmt>(AStmt);
6264 getOpenMPCaptureRegions(CaptureRegions, Kind);
6265 // Ignore outer tasking regions for target directives.
6266 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6268 DSAChecker.visitSubCaptures(CS);
6269 }
6270 if (DSAChecker.isErrorFound())
6271 return StmtError();
6272 // Generate list of implicitly defined firstprivate variables.
6273 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6274 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6275
6277 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6278 // Get the original location of present modifier from Defaultmap clause.
6279 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6280 for (OMPClause *C : Clauses) {
6281 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6282 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6283 PresentModifierLocs[DMC->getDefaultmapKind()] =
6284 DMC->getDefaultmapModifierLoc();
6285 }
6286
6288 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6290 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[K]),
6291 ImpInfo.MapModifiers[K].size(), PresentModifierLocs[K]);
6292 }
6293 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6294 for (OMPClause *C : Clauses) {
6295 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6296 for (Expr *E : IRC->taskgroup_descriptors())
6297 if (E)
6298 ImpInfo.Firstprivates.insert(E);
6299 }
6300 // OpenMP 5.0, 2.10.1 task Construct
6301 // [detach clause]... The event-handle will be considered as if it was
6302 // specified on a firstprivate clause.
6303 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6304 ImpInfo.Firstprivates.insert(DC->getEventHandler());
6305 }
6306 if (!ImpInfo.Firstprivates.empty()) {
6308 ImpInfo.Firstprivates.getArrayRef(), SourceLocation(),
6310 ClausesWithImplicit.push_back(Implicit);
6311 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6312 ImpInfo.Firstprivates.size();
6313 } else {
6314 ErrorFound = true;
6315 }
6316 }
6317 if (!ImpInfo.Privates.empty()) {
6319 ImpInfo.Privates.getArrayRef(), SourceLocation(),
6321 ClausesWithImplicit.push_back(Implicit);
6322 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6323 ImpInfo.Privates.size();
6324 } else {
6325 ErrorFound = true;
6326 }
6327 }
6328 // OpenMP 5.0 [2.19.7]
6329 // If a list item appears in a reduction, lastprivate or linear
6330 // clause on a combined target construct then it is treated as
6331 // if it also appears in a map clause with a map-type of tofrom
6332 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6334 SmallVector<Expr *, 4> ImplicitExprs;
6335 for (OMPClause *C : Clauses) {
6336 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6337 for (Expr *E : RC->varlist())
6339 ImplicitExprs.emplace_back(E);
6340 }
6341 if (!ImplicitExprs.empty()) {
6342 ArrayRef<Expr *> Exprs = ImplicitExprs;
6343 CXXScopeSpec MapperIdScopeSpec;
6344 DeclarationNameInfo MapperId;
6347 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6348 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6349 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6350 ClausesWithImplicit.emplace_back(Implicit);
6351 }
6352 }
6353 for (unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6354 int ClauseKindCnt = -1;
6355 for (unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6356 ArrayRef<Expr *> ImplicitMap = ImpInfo.Mappings[I][J].getArrayRef();
6357 ++ClauseKindCnt;
6358 if (ImplicitMap.empty())
6359 continue;
6360 CXXScopeSpec MapperIdScopeSpec;
6361 DeclarationNameInfo MapperId;
6362 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6364 nullptr, ImpInfo.MapModifiers[I], ImplicitMapModifiersLoc[I],
6365 MapperIdScopeSpec, MapperId, K, /*IsMapTypeImplicit=*/true,
6366 SourceLocation(), SourceLocation(), ImplicitMap,
6367 OMPVarListLocTy())) {
6368 ClausesWithImplicit.emplace_back(Implicit);
6369 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6370 ImplicitMap.size();
6371 } else {
6372 ErrorFound = true;
6373 }
6374 }
6375 }
6376 // Build expressions for implicit maps of data members with 'default'
6377 // mappers.
6378 if (getLangOpts().OpenMP >= 50)
6380 ClausesWithImplicit);
6381 }
6382
6383 switch (Kind) {
6384 case OMPD_parallel:
6385 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6386 EndLoc);
6387 break;
6388 case OMPD_simd:
6389 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6390 VarsWithInheritedDSA);
6391 break;
6392 case OMPD_tile:
6393 Res =
6394 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6395 break;
6396 case OMPD_stripe:
6397 Res = ActOnOpenMPStripeDirective(ClausesWithImplicit, AStmt, StartLoc,
6398 EndLoc);
6399 break;
6400 case OMPD_unroll:
6401 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6402 EndLoc);
6403 break;
6404 case OMPD_reverse:
6405 assert(ClausesWithImplicit.empty() &&
6406 "reverse directive does not support any clauses");
6407 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6408 break;
6409 case OMPD_interchange:
6410 Res = ActOnOpenMPInterchangeDirective(ClausesWithImplicit, AStmt, StartLoc,
6411 EndLoc);
6412 break;
6413 case OMPD_for:
6414 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6415 VarsWithInheritedDSA);
6416 break;
6417 case OMPD_for_simd:
6418 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6419 EndLoc, VarsWithInheritedDSA);
6420 break;
6421 case OMPD_sections:
6422 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6423 EndLoc);
6424 break;
6425 case OMPD_section:
6426 assert(ClausesWithImplicit.empty() &&
6427 "No clauses are allowed for 'omp section' directive");
6428 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6429 break;
6430 case OMPD_single:
6431 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6432 EndLoc);
6433 break;
6434 case OMPD_master:
6435 assert(ClausesWithImplicit.empty() &&
6436 "No clauses are allowed for 'omp master' directive");
6437 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6438 break;
6439 case OMPD_masked:
6440 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6441 EndLoc);
6442 break;
6443 case OMPD_critical:
6444 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6445 StartLoc, EndLoc);
6446 break;
6447 case OMPD_parallel_for:
6448 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6449 EndLoc, VarsWithInheritedDSA);
6450 break;
6451 case OMPD_parallel_for_simd:
6453 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6454 break;
6455 case OMPD_scope:
6456 Res =
6457 ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6458 break;
6459 case OMPD_parallel_master:
6460 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6461 StartLoc, EndLoc);
6462 break;
6463 case OMPD_parallel_masked:
6464 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6465 StartLoc, EndLoc);
6466 break;
6467 case OMPD_parallel_sections:
6468 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6469 StartLoc, EndLoc);
6470 break;
6471 case OMPD_task:
6472 Res =
6473 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6474 break;
6475 case OMPD_taskyield:
6476 assert(ClausesWithImplicit.empty() &&
6477 "No clauses are allowed for 'omp taskyield' directive");
6478 assert(AStmt == nullptr &&
6479 "No associated statement allowed for 'omp taskyield' directive");
6480 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6481 break;
6482 case OMPD_error:
6483 assert(AStmt == nullptr &&
6484 "No associated statement allowed for 'omp error' directive");
6485 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6486 break;
6487 case OMPD_barrier:
6488 assert(ClausesWithImplicit.empty() &&
6489 "No clauses are allowed for 'omp barrier' directive");
6490 assert(AStmt == nullptr &&
6491 "No associated statement allowed for 'omp barrier' directive");
6492 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6493 break;
6494 case OMPD_taskwait:
6495 assert(AStmt == nullptr &&
6496 "No associated statement allowed for 'omp taskwait' directive");
6497 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6498 break;
6499 case OMPD_taskgroup:
6500 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6501 EndLoc);
6502 break;
6503 case OMPD_flush:
6504 assert(AStmt == nullptr &&
6505 "No associated statement allowed for 'omp flush' directive");
6506 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6507 break;
6508 case OMPD_depobj:
6509 assert(AStmt == nullptr &&
6510 "No associated statement allowed for 'omp depobj' directive");
6511 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6512 break;
6513 case OMPD_scan:
6514 assert(AStmt == nullptr &&
6515 "No associated statement allowed for 'omp scan' directive");
6516 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6517 break;
6518 case OMPD_ordered:
6519 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6520 EndLoc);
6521 break;
6522 case OMPD_atomic:
6523 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6524 EndLoc);
6525 break;
6526 case OMPD_teams:
6527 Res =
6528 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6529 break;
6530 case OMPD_target:
6531 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6532 EndLoc);
6533 break;
6534 case OMPD_target_parallel:
6535 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6536 StartLoc, EndLoc);
6537 break;
6538 case OMPD_target_parallel_for:
6540 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6541 break;
6542 case OMPD_cancellation_point:
6543 assert(ClausesWithImplicit.empty() &&
6544 "No clauses are allowed for 'omp cancellation point' directive");
6545 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6546 "cancellation point' directive");
6547 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6548 break;
6549 case OMPD_cancel:
6550 assert(AStmt == nullptr &&
6551 "No associated statement allowed for 'omp cancel' directive");
6552 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6553 CancelRegion);
6554 break;
6555 case OMPD_target_data:
6556 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6557 EndLoc);
6558 break;
6559 case OMPD_target_enter_data:
6560 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6561 EndLoc, AStmt);
6562 break;
6563 case OMPD_target_exit_data:
6564 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6565 EndLoc, AStmt);
6566 break;
6567 case OMPD_taskloop:
6568 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6569 EndLoc, VarsWithInheritedDSA);
6570 break;
6571 case OMPD_taskloop_simd:
6572 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6573 EndLoc, VarsWithInheritedDSA);
6574 break;
6575 case OMPD_master_taskloop:
6577 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6578 break;
6579 case OMPD_masked_taskloop:
6581 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6582 break;
6583 case OMPD_master_taskloop_simd:
6585 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6586 break;
6587 case OMPD_masked_taskloop_simd:
6589 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6590 break;
6591 case OMPD_parallel_master_taskloop:
6593 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6594 break;
6595 case OMPD_parallel_masked_taskloop:
6597 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6598 break;
6599 case OMPD_parallel_master_taskloop_simd:
6601 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6602 break;
6603 case OMPD_parallel_masked_taskloop_simd:
6605 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6606 break;
6607 case OMPD_distribute:
6608 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6609 EndLoc, VarsWithInheritedDSA);
6610 break;
6611 case OMPD_target_update:
6612 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6613 EndLoc, AStmt);
6614 break;
6615 case OMPD_distribute_parallel_for:
6617 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6618 break;
6619 case OMPD_distribute_parallel_for_simd:
6621 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6622 break;
6623 case OMPD_distribute_simd:
6625 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6626 break;
6627 case OMPD_target_parallel_for_simd:
6629 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6630 break;
6631 case OMPD_target_simd:
6632 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6633 EndLoc, VarsWithInheritedDSA);
6634 break;
6635 case OMPD_teams_distribute:
6637 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6638 break;
6639 case OMPD_teams_distribute_simd:
6641 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6642 break;
6643 case OMPD_teams_distribute_parallel_for_simd:
6645 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6646 break;
6647 case OMPD_teams_distribute_parallel_for:
6649 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6650 break;
6651 case OMPD_target_teams:
6652 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6653 EndLoc);
6654 break;
6655 case OMPD_target_teams_distribute:
6657 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6658 break;
6659 case OMPD_target_teams_distribute_parallel_for:
6661 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6662 break;
6663 case OMPD_target_teams_distribute_parallel_for_simd:
6665 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6666 break;
6667 case OMPD_target_teams_distribute_simd:
6669 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6670 break;
6671 case OMPD_interop:
6672 assert(AStmt == nullptr &&
6673 "No associated statement allowed for 'omp interop' directive");
6674 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6675 break;
6676 case OMPD_dispatch:
6677 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6678 EndLoc);
6679 break;
6680 case OMPD_loop:
6681 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6682 EndLoc, VarsWithInheritedDSA);
6683 break;
6684 case OMPD_teams_loop:
6686 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6687 break;
6688 case OMPD_target_teams_loop:
6690 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6691 break;
6692 case OMPD_parallel_loop:
6694 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6695 break;
6696 case OMPD_target_parallel_loop:
6698 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6699 break;
6700 case OMPD_declare_target:
6701 case OMPD_end_declare_target:
6702 case OMPD_threadprivate:
6703 case OMPD_allocate:
6704 case OMPD_declare_reduction:
6705 case OMPD_declare_mapper:
6706 case OMPD_declare_simd:
6707 case OMPD_requires:
6708 case OMPD_declare_variant:
6709 case OMPD_begin_declare_variant:
6710 case OMPD_end_declare_variant:
6711 llvm_unreachable("OpenMP Directive is not allowed");
6712 case OMPD_unknown:
6713 default:
6714 llvm_unreachable("Unknown OpenMP directive");
6715 }
6716
6717 ErrorFound = Res.isInvalid() || ErrorFound;
6718
6719 // Check variables in the clauses if default(none) or
6720 // default(firstprivate) was specified.
6721 if (DSAStack->getDefaultDSA() == DSA_none ||
6722 DSAStack->getDefaultDSA() == DSA_private ||
6723 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6724 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6725 for (OMPClause *C : Clauses) {
6726 switch (C->getClauseKind()) {
6727 case OMPC_num_threads:
6728 case OMPC_dist_schedule:
6729 // Do not analyze if no parent teams directive.
6730 if (isOpenMPTeamsDirective(Kind))
6731 break;
6732 continue;
6733 case OMPC_if:
6734 if (isOpenMPTeamsDirective(Kind) &&
6735 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6736 break;
6737 if (isOpenMPParallelDirective(Kind) &&
6739 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6740 break;
6741 continue;
6742 case OMPC_schedule:
6743 case OMPC_detach:
6744 break;
6745 case OMPC_grainsize:
6746 case OMPC_num_tasks:
6747 case OMPC_final:
6748 case OMPC_priority:
6749 case OMPC_novariants:
6750 case OMPC_nocontext:
6751 // Do not analyze if no parent parallel directive.
6752 if (isOpenMPParallelDirective(Kind))
6753 break;
6754 continue;
6755 case OMPC_ordered:
6756 case OMPC_device:
6757 case OMPC_num_teams:
6758 case OMPC_thread_limit:
6759 case OMPC_hint:
6760 case OMPC_collapse:
6761 case OMPC_safelen:
6762 case OMPC_simdlen:
6763 case OMPC_sizes:
6764 case OMPC_default:
6765 case OMPC_proc_bind:
6766 case OMPC_private:
6767 case OMPC_firstprivate:
6768 case OMPC_lastprivate:
6769 case OMPC_shared:
6770 case OMPC_reduction:
6771 case OMPC_task_reduction:
6772 case OMPC_in_reduction:
6773 case OMPC_linear:
6774 case OMPC_aligned:
6775 case OMPC_copyin:
6776 case OMPC_copyprivate:
6777 case OMPC_nowait:
6778 case OMPC_untied:
6779 case OMPC_mergeable:
6780 case OMPC_allocate:
6781 case OMPC_read:
6782 case OMPC_write:
6783 case OMPC_update:
6784 case OMPC_capture:
6785 case OMPC_compare:
6786 case OMPC_seq_cst:
6787 case OMPC_acq_rel:
6788 case OMPC_acquire:
6789 case OMPC_release:
6790 case OMPC_relaxed:
6791 case OMPC_depend:
6792 case OMPC_threads:
6793 case OMPC_simd:
6794 case OMPC_map:
6795 case OMPC_nogroup:
6796 case OMPC_defaultmap:
6797 case OMPC_to:
6798 case OMPC_from:
6799 case OMPC_use_device_ptr:
6800 case OMPC_use_device_addr:
6801 case OMPC_is_device_ptr:
6802 case OMPC_has_device_addr:
6803 case OMPC_nontemporal:
6804 case OMPC_order:
6805 case OMPC_destroy:
6806 case OMPC_inclusive:
6807 case OMPC_exclusive:
6808 case OMPC_uses_allocators:
6809 case OMPC_affinity:
6810 case OMPC_bind:
6811 case OMPC_filter:
6812 case OMPC_severity:
6813 case OMPC_message:
6814 continue;
6815 case OMPC_allocator:
6816 case OMPC_flush:
6817 case OMPC_depobj:
6818 case OMPC_threadprivate:
6819 case OMPC_groupprivate:
6820 case OMPC_uniform:
6821 case OMPC_unknown:
6822 case OMPC_unified_address:
6823 case OMPC_unified_shared_memory:
6824 case OMPC_reverse_offload:
6825 case OMPC_dynamic_allocators:
6826 case OMPC_atomic_default_mem_order:
6827 case OMPC_self_maps:
6828 case OMPC_device_type:
6829 case OMPC_match:
6830 case OMPC_when:
6831 case OMPC_at:
6832 default:
6833 llvm_unreachable("Unexpected clause");
6834 }
6835 for (Stmt *CC : C->children()) {
6836 if (CC)
6837 DSAChecker.Visit(CC);
6838 }
6839 }
6840 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6841 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6842 }
6843 for (const auto &P : VarsWithInheritedDSA) {
6844 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6845 continue;
6846 ErrorFound = true;
6847 if (DSAStack->getDefaultDSA() == DSA_none ||
6848 DSAStack->getDefaultDSA() == DSA_private ||
6849 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6850 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6851 << P.first << P.second->getSourceRange();
6852 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6853 } else if (getLangOpts().OpenMP >= 50) {
6854 Diag(P.second->getExprLoc(),
6855 diag::err_omp_defaultmap_no_attr_for_variable)
6856 << P.first << P.second->getSourceRange();
6857 Diag(DSAStack->getDefaultDSALocation(),
6858 diag::note_omp_defaultmap_attr_none);
6859 }
6860 }
6861
6862 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6863 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(Kind)) {
6864 if (isAllowedClauseForDirective(D, OMPC_if, getLangOpts().OpenMP))
6865 AllowedNameModifiers.push_back(D);
6866 }
6867 if (!AllowedNameModifiers.empty())
6868 ErrorFound = checkIfClauses(SemaRef, Kind, Clauses, AllowedNameModifiers) ||
6869 ErrorFound;
6870
6871 if (ErrorFound)
6872 return StmtError();
6873
6874 if (!SemaRef.CurContext->isDependentContext() &&
6876 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6877 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6878 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6879 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6880 // Register target to DSA Stack.
6881 DSAStack->addTargetDirLocation(StartLoc);
6882 }
6883
6884 return Res;
6885}
6886
6888 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6889 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6890 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6891 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6892 assert(Aligneds.size() == Alignments.size());
6893 assert(Linears.size() == LinModifiers.size());
6894 assert(Linears.size() == Steps.size());
6895 if (!DG || DG.get().isNull())
6896 return DeclGroupPtrTy();
6897
6898 const int SimdId = 0;
6899 if (!DG.get().isSingleDecl()) {
6900 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6901 << SimdId;
6902 return DG;
6903 }
6904 Decl *ADecl = DG.get().getSingleDecl();
6905 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6906 ADecl = FTD->getTemplatedDecl();
6907
6908 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6909 if (!FD) {
6910 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6911 return DeclGroupPtrTy();
6912 }
6913
6914 // OpenMP [2.8.2, declare simd construct, Description]
6915 // The parameter of the simdlen clause must be a constant positive integer
6916 // expression.
6917 ExprResult SL;
6918 if (Simdlen)
6919 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6920 // OpenMP [2.8.2, declare simd construct, Description]
6921 // The special this pointer can be used as if was one of the arguments to the
6922 // function in any of the linear, aligned, or uniform clauses.
6923 // The uniform clause declares one or more arguments to have an invariant
6924 // value for all concurrent invocations of the function in the execution of a
6925 // single SIMD loop.
6926 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6927 const Expr *UniformedLinearThis = nullptr;
6928 for (const Expr *E : Uniforms) {
6929 E = E->IgnoreParenImpCasts();
6930 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6931 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6932 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6933 FD->getParamDecl(PVD->getFunctionScopeIndex())
6934 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
6935 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6936 continue;
6937 }
6938 if (isa<CXXThisExpr>(E)) {
6939 UniformedLinearThis = E;
6940 continue;
6941 }
6942 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6943 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6944 }
6945 // OpenMP [2.8.2, declare simd construct, Description]
6946 // The aligned clause declares that the object to which each list item points
6947 // is aligned to the number of bytes expressed in the optional parameter of
6948 // the aligned clause.
6949 // The special this pointer can be used as if was one of the arguments to the
6950 // function in any of the linear, aligned, or uniform clauses.
6951 // The type of list items appearing in the aligned clause must be array,
6952 // pointer, reference to array, or reference to pointer.
6953 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6954 const Expr *AlignedThis = nullptr;
6955 for (const Expr *E : Aligneds) {
6956 E = E->IgnoreParenImpCasts();
6957 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6958 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6959 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6960 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6961 FD->getParamDecl(PVD->getFunctionScopeIndex())
6962 ->getCanonicalDecl() == CanonPVD) {
6963 // OpenMP [2.8.1, simd construct, Restrictions]
6964 // A list-item cannot appear in more than one aligned clause.
6965 auto [It, Inserted] = AlignedArgs.try_emplace(CanonPVD, E);
6966 if (!Inserted) {
6967 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6968 << 1 << getOpenMPClauseNameForDiag(OMPC_aligned)
6969 << E->getSourceRange();
6970 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
6971 << getOpenMPClauseNameForDiag(OMPC_aligned);
6972 continue;
6973 }
6974 QualType QTy = PVD->getType()
6975 .getNonReferenceType()
6976 .getUnqualifiedType()
6977 .getCanonicalType();
6978 const Type *Ty = QTy.getTypePtrOrNull();
6979 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
6980 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
6981 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
6982 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6983 }
6984 continue;
6985 }
6986 }
6987 if (isa<CXXThisExpr>(E)) {
6988 if (AlignedThis) {
6989 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6990 << 2 << getOpenMPClauseNameForDiag(OMPC_aligned)
6991 << E->getSourceRange();
6992 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
6993 << getOpenMPClauseNameForDiag(OMPC_aligned);
6994 }
6995 AlignedThis = E;
6996 continue;
6997 }
6998 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6999 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7000 }
7001 // The optional parameter of the aligned clause, alignment, must be a constant
7002 // positive integer expression. If no optional parameter is specified,
7003 // implementation-defined default alignments for SIMD instructions on the
7004 // target platforms are assumed.
7006 for (Expr *E : Alignments) {
7007 ExprResult Align;
7008 if (E)
7009 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
7010 NewAligns.push_back(Align.get());
7011 }
7012 // OpenMP [2.8.2, declare simd construct, Description]
7013 // The linear clause declares one or more list items to be private to a SIMD
7014 // lane and to have a linear relationship with respect to the iteration space
7015 // of a loop.
7016 // The special this pointer can be used as if was one of the arguments to the
7017 // function in any of the linear, aligned, or uniform clauses.
7018 // When a linear-step expression is specified in a linear clause it must be
7019 // either a constant integer expression or an integer-typed parameter that is
7020 // specified in a uniform clause on the directive.
7021 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7022 const bool IsUniformedThis = UniformedLinearThis != nullptr;
7023 auto MI = LinModifiers.begin();
7024 for (const Expr *E : Linears) {
7025 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
7026 ++MI;
7027 E = E->IgnoreParenImpCasts();
7028 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7029 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7030 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7031 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7032 FD->getParamDecl(PVD->getFunctionScopeIndex())
7033 ->getCanonicalDecl() == CanonPVD) {
7034 // OpenMP [2.15.3.7, linear Clause, Restrictions]
7035 // A list-item cannot appear in more than one linear clause.
7036 if (auto It = LinearArgs.find(CanonPVD); It != LinearArgs.end()) {
7037 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7038 << getOpenMPClauseNameForDiag(OMPC_linear)
7039 << getOpenMPClauseNameForDiag(OMPC_linear)
7040 << E->getSourceRange();
7041 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7042 << getOpenMPClauseNameForDiag(OMPC_linear);
7043 continue;
7044 }
7045 // Each argument can appear in at most one uniform or linear clause.
7046 if (auto It = UniformedArgs.find(CanonPVD);
7047 It != UniformedArgs.end()) {
7048 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7049 << getOpenMPClauseNameForDiag(OMPC_linear)
7050 << getOpenMPClauseNameForDiag(OMPC_uniform)
7051 << E->getSourceRange();
7052 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7053 << getOpenMPClauseNameForDiag(OMPC_uniform);
7054 continue;
7055 }
7056 LinearArgs[CanonPVD] = E;
7057 if (E->isValueDependent() || E->isTypeDependent() ||
7060 continue;
7061 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
7062 PVD->getOriginalType(),
7063 /*IsDeclareSimd=*/true);
7064 continue;
7065 }
7066 }
7067 if (isa<CXXThisExpr>(E)) {
7068 if (UniformedLinearThis) {
7069 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7070 << getOpenMPClauseNameForDiag(OMPC_linear)
7071 << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
7072 : OMPC_linear)
7073 << E->getSourceRange();
7074 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
7075 << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
7076 : OMPC_linear);
7077 continue;
7078 }
7079 UniformedLinearThis = E;
7080 if (E->isValueDependent() || E->isTypeDependent() ||
7082 continue;
7083 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
7084 E->getType(), /*IsDeclareSimd=*/true);
7085 continue;
7086 }
7087 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7088 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7089 }
7090 Expr *Step = nullptr;
7091 Expr *NewStep = nullptr;
7092 SmallVector<Expr *, 4> NewSteps;
7093 for (Expr *E : Steps) {
7094 // Skip the same step expression, it was checked already.
7095 if (Step == E || !E) {
7096 NewSteps.push_back(E ? NewStep : nullptr);
7097 continue;
7098 }
7099 Step = E;
7100 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
7101 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7102 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7103 if (UniformedArgs.count(CanonPVD) == 0) {
7104 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
7105 << Step->getSourceRange();
7106 } else if (E->isValueDependent() || E->isTypeDependent() ||
7109 CanonPVD->getType()->hasIntegerRepresentation()) {
7110 NewSteps.push_back(Step);
7111 } else {
7112 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
7113 << Step->getSourceRange();
7114 }
7115 continue;
7116 }
7117 NewStep = Step;
7118 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
7119 !Step->isInstantiationDependent() &&
7121 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
7122 .get();
7123 if (NewStep)
7124 NewStep = SemaRef
7125 .VerifyIntegerConstantExpression(
7126 NewStep, /*FIXME*/ AllowFoldKind::Allow)
7127 .get();
7128 }
7129 NewSteps.push_back(NewStep);
7130 }
7131 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7132 getASTContext(), BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
7133 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
7134 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
7135 const_cast<Expr **>(Linears.data()), Linears.size(),
7136 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
7137 NewSteps.data(), NewSteps.size(), SR);
7138 ADecl->addAttr(NewAttr);
7139 return DG;
7140}
7141
7143 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
7144 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
7145 SourceLocation EndLoc) {
7146 assert(isOpenMPInformationalDirective(Kind) &&
7147 "Unexpected directive category");
7148
7149 StmtResult Res = StmtError();
7150
7151 switch (Kind) {
7152 case OMPD_assume:
7153 Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc);
7154 break;
7155 default:
7156 llvm_unreachable("Unknown OpenMP directive");
7157 }
7158
7159 return Res;
7160}
7161
7162static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7163 QualType NewType) {
7164 assert(NewType->isFunctionProtoType() &&
7165 "Expected function type with prototype.");
7166 assert(FD->getType()->isFunctionNoProtoType() &&
7167 "Expected function with type with no prototype.");
7168 assert(FDWithProto->getType()->isFunctionProtoType() &&
7169 "Expected function with prototype.");
7170 // Synthesize parameters with the same types.
7171 FD->setType(NewType);
7173 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7174 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
7175 SourceLocation(), nullptr, P->getType(),
7176 /*TInfo=*/nullptr, SC_None, nullptr);
7177 Param->setScopeInfo(0, Params.size());
7178 Param->setImplicit();
7179 Params.push_back(Param);
7180 }
7181
7182 FD->setParams(Params);
7183}
7184
7186 if (D->isInvalidDecl())
7187 return;
7188 FunctionDecl *FD = nullptr;
7189 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7190 FD = UTemplDecl->getTemplatedDecl();
7191 else
7192 FD = cast<FunctionDecl>(D);
7193 assert(FD && "Expected a function declaration!");
7194
7195 // If we are instantiating templates we do *not* apply scoped assumptions but
7196 // only global ones. We apply scoped assumption to the template definition
7197 // though.
7198 if (!SemaRef.inTemplateInstantiation()) {
7199 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7200 FD->addAttr(AA);
7201 }
7202 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7203 FD->addAttr(AA);
7204}
7205
7206SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7207 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7208
7210 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7212 if (!D.getIdentifier())
7213 return;
7214
7215 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7216
7217 // Template specialization is an extension, check if we do it.
7218 bool IsTemplated = !TemplateParamLists.empty();
7219 if (IsTemplated &&
7220 !DVScope.TI->isExtensionActive(
7221 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7222 return;
7223
7224 const IdentifierInfo *BaseII = D.getIdentifier();
7227 SemaRef.LookupParsedName(Lookup, S, &D.getCXXScopeSpec(),
7228 /*ObjectType=*/QualType());
7229
7230 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
7231 QualType FType = TInfo->getType();
7232
7233 bool IsConstexpr =
7235 bool IsConsteval =
7237
7238 for (auto *Candidate : Lookup) {
7239 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7240 FunctionDecl *UDecl = nullptr;
7241 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7242 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7243 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7244 UDecl = FTD->getTemplatedDecl();
7245 } else if (!IsTemplated)
7246 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7247 if (!UDecl)
7248 continue;
7249
7250 // Don't specialize constexpr/consteval functions with
7251 // non-constexpr/consteval functions.
7252 if (UDecl->isConstexpr() && !IsConstexpr)
7253 continue;
7254 if (UDecl->isConsteval() && !IsConsteval)
7255 continue;
7256
7257 QualType UDeclTy = UDecl->getType();
7258 if (!UDeclTy->isDependentType()) {
7260 FType, UDeclTy, /*OfBlockPointer=*/false,
7261 /*Unqualified=*/false, /*AllowCXX=*/true);
7262 if (NewType.isNull())
7263 continue;
7264 }
7265
7266 // Found a base!
7267 Bases.push_back(UDecl);
7268 }
7269
7270 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7271 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7272 // If no base was found we create a declaration that we use as base.
7273 if (Bases.empty() && UseImplicitBase) {
7275 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7276 BaseD->setImplicit(true);
7277 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7278 Bases.push_back(BaseTemplD->getTemplatedDecl());
7279 else
7280 Bases.push_back(cast<FunctionDecl>(BaseD));
7281 }
7282
7283 std::string MangledName;
7284 MangledName += D.getIdentifier()->getName();
7285 MangledName += getOpenMPVariantManglingSeparatorStr();
7286 MangledName += DVScope.NameSuffix;
7287 IdentifierInfo &VariantII = getASTContext().Idents.get(MangledName);
7288
7289 VariantII.setMangledOpenMPVariantName(true);
7290 D.SetIdentifier(&VariantII, D.getBeginLoc());
7291}
7292
7295 // Do not mark function as is used to prevent its emission if this is the
7296 // only place where it is used.
7299
7300 FunctionDecl *FD = nullptr;
7301 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7302 FD = UTemplDecl->getTemplatedDecl();
7303 else
7304 FD = cast<FunctionDecl>(D);
7305 auto *VariantFuncRef = DeclRefExpr::Create(
7307 /*RefersToEnclosingVariableOrCapture=*/false,
7308 /*NameLoc=*/FD->getLocation(), FD->getType(), ExprValueKind::VK_PRValue);
7309
7310 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7311 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7312 getASTContext(), VariantFuncRef, DVScope.TI,
7313 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7314 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7315 /*NeedDeviceAddrArgs=*/nullptr, /*NeedDeviceAddrArgsSize=*/0,
7316 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7317 for (FunctionDecl *BaseFD : Bases)
7318 BaseFD->addAttr(OMPDeclareVariantA);
7319}
7320
7322 SourceLocation LParenLoc,
7323 MultiExprArg ArgExprs,
7324 SourceLocation RParenLoc,
7325 Expr *ExecConfig) {
7326 // The common case is a regular call we do not want to specialize at all. Try
7327 // to make that case fast by bailing early.
7328 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7329 if (!CE)
7330 return Call;
7331
7332 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7333 if (!CalleeFnDecl)
7334 return Call;
7335
7336 if (getLangOpts().OpenMP >= 50 && getLangOpts().OpenMP <= 60 &&
7337 CalleeFnDecl->getIdentifier() &&
7338 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7339 // checking for any calls inside an Order region
7341 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7342 }
7343
7344 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7345 return Call;
7346
7347 ASTContext &Context = getASTContext();
7348 std::function<void(StringRef)> DiagUnknownTrait = [this,
7349 CE](StringRef ISATrait) {
7350 // TODO Track the selector locations in a way that is accessible here to
7351 // improve the diagnostic location.
7352 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7353 << ISATrait;
7354 };
7355 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7356 SemaRef.getCurFunctionDecl(),
7357 DSAStack->getConstructTraits(), getOpenMPDeviceNum());
7358
7359 QualType CalleeFnType = CalleeFnDecl->getType();
7360
7363 while (CalleeFnDecl) {
7364 for (OMPDeclareVariantAttr *A :
7365 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7366 Expr *VariantRef = A->getVariantFuncRef();
7367
7368 VariantMatchInfo VMI;
7369 OMPTraitInfo &TI = A->getTraitInfo();
7370 TI.getAsVariantMatchInfo(Context, VMI);
7371 if (!isVariantApplicableInContext(VMI, OMPCtx,
7372 /*DeviceSetOnly=*/false))
7373 continue;
7374
7375 VMIs.push_back(VMI);
7376 Exprs.push_back(VariantRef);
7377 }
7378
7379 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7380 }
7381
7382 ExprResult NewCall;
7383 do {
7384 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7385 if (BestIdx < 0)
7386 return Call;
7387 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7388 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7389
7390 {
7391 // Try to build a (member) call expression for the current best applicable
7392 // variant expression. We allow this to fail in which case we continue
7393 // with the next best variant expression. The fail case is part of the
7394 // implementation defined behavior in the OpenMP standard when it talks
7395 // about what differences in the function prototypes: "Any differences
7396 // that the specific OpenMP context requires in the prototype of the
7397 // variant from the base function prototype are implementation defined."
7398 // This wording is there to allow the specialized variant to have a
7399 // different type than the base function. This is intended and OK but if
7400 // we cannot create a call the difference is not in the "implementation
7401 // defined range" we allow.
7403
7404 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7405 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7406 BestExpr = MemberExpr::CreateImplicit(
7407 Context, MemberCall->getImplicitObjectArgument(),
7408 /*IsArrow=*/false, SpecializedMethod, Context.BoundMemberTy,
7409 MemberCall->getValueKind(), MemberCall->getObjectKind());
7410 }
7411 NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs,
7412 RParenLoc, ExecConfig);
7413 if (NewCall.isUsable()) {
7414 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7415 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7417 CalleeFnType, NewCalleeFnDecl->getType(),
7418 /*OfBlockPointer=*/false,
7419 /*Unqualified=*/false, /*AllowCXX=*/true);
7420 if (!NewType.isNull())
7421 break;
7422 // Don't use the call if the function type was not compatible.
7423 NewCall = nullptr;
7424 }
7425 }
7426 }
7427
7428 VMIs.erase(VMIs.begin() + BestIdx);
7429 Exprs.erase(Exprs.begin() + BestIdx);
7430 } while (!VMIs.empty());
7431
7432 if (!NewCall.isUsable())
7433 return Call;
7434 return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
7435}
7436
7437std::optional<std::pair<FunctionDecl *, Expr *>>
7439 Expr *VariantRef,
7440 OMPTraitInfo &TI,
7441 unsigned NumAppendArgs,
7442 SourceRange SR) {
7443 ASTContext &Context = getASTContext();
7444 if (!DG || DG.get().isNull())
7445 return std::nullopt;
7446
7447 const int VariantId = 1;
7448 // Must be applied only to single decl.
7449 if (!DG.get().isSingleDecl()) {
7450 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7451 << VariantId << SR;
7452 return std::nullopt;
7453 }
7454 Decl *ADecl = DG.get().getSingleDecl();
7455 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7456 ADecl = FTD->getTemplatedDecl();
7457
7458 // Decl must be a function.
7459 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7460 if (!FD) {
7461 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7462 << VariantId << SR;
7463 return std::nullopt;
7464 }
7465
7466 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7467 // The 'target' attribute needs to be separately checked because it does
7468 // not always signify a multiversion function declaration.
7469 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7470 };
7471 // OpenMP is not compatible with multiversion function attributes.
7472 if (HasMultiVersionAttributes(FD)) {
7473 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7474 << SR;
7475 return std::nullopt;
7476 }
7477
7478 // Allow #pragma omp declare variant only if the function is not used.
7479 if (FD->isUsed(false))
7480 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7481 << FD->getLocation();
7482
7483 // Check if the function was emitted already.
7484 const FunctionDecl *Definition;
7485 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7486 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7487 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7488 << FD->getLocation();
7489
7490 // The VariantRef must point to function.
7491 if (!VariantRef) {
7492 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7493 return std::nullopt;
7494 }
7495
7496 auto ShouldDelayChecks = [](Expr *&E, bool) {
7497 return E && (E->isTypeDependent() || E->isValueDependent() ||
7500 };
7501 // Do not check templates, wait until instantiation.
7502 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7503 TI.anyScoreOrCondition(ShouldDelayChecks))
7504 return std::make_pair(FD, VariantRef);
7505
7506 // Deal with non-constant score and user condition expressions.
7507 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7508 bool IsScore) -> bool {
7509 if (!E || E->isIntegerConstantExpr(getASTContext()))
7510 return false;
7511
7512 if (IsScore) {
7513 // We warn on non-constant scores and pretend they were not present.
7514 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7515 << E;
7516 E = nullptr;
7517 } else {
7518 // We could replace a non-constant user condition with "false" but we
7519 // will soon need to handle these anyway for the dynamic version of
7520 // OpenMP context selectors.
7521 Diag(E->getExprLoc(),
7522 diag::err_omp_declare_variant_user_condition_not_constant)
7523 << E;
7524 }
7525 return true;
7526 };
7527 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7528 return std::nullopt;
7529
7530 QualType AdjustedFnType = FD->getType();
7531 if (NumAppendArgs) {
7532 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7533 if (!PTy) {
7534 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7535 << SR;
7536 return std::nullopt;
7537 }
7538 // Adjust the function type to account for an extra omp_interop_t for each
7539 // specified in the append_args clause.
7540 const TypeDecl *TD = nullptr;
7541 LookupResult Result(SemaRef, &Context.Idents.get("omp_interop_t"),
7543 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
7544 NamedDecl *ND = Result.getFoundDecl();
7545 TD = dyn_cast_or_null<TypeDecl>(ND);
7546 }
7547 if (!TD) {
7548 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7549 return std::nullopt;
7550 }
7551 QualType InteropType =
7552 Context.getTypeDeclType(ElaboratedTypeKeyword::None,
7553 /*Qualifier=*/std::nullopt, TD);
7554 if (PTy->isVariadic()) {
7555 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7556 return std::nullopt;
7557 }
7559 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7560 Params.insert(Params.end(), NumAppendArgs, InteropType);
7561 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7562 PTy->getExtProtoInfo());
7563 }
7564
7565 // Convert VariantRef expression to the type of the original function to
7566 // resolve possible conflicts.
7567 ExprResult VariantRefCast = VariantRef;
7568 if (getLangOpts().CPlusPlus) {
7569 QualType FnPtrType;
7570 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7571 if (Method && !Method->isStatic()) {
7572 FnPtrType = Context.getMemberPointerType(
7573 AdjustedFnType, /*Qualifier=*/std::nullopt, Method->getParent());
7574 ExprResult ER;
7575 {
7576 // Build addr_of unary op to correctly handle type checks for member
7577 // functions.
7579 ER = SemaRef.CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7580 VariantRef);
7581 }
7582 if (!ER.isUsable()) {
7583 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7584 << VariantId << VariantRef->getSourceRange();
7585 return std::nullopt;
7586 }
7587 VariantRef = ER.get();
7588 } else {
7589 FnPtrType = Context.getPointerType(AdjustedFnType);
7590 }
7591 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7592 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7593 ImplicitConversionSequence ICS = SemaRef.TryImplicitConversion(
7594 VariantRef, FnPtrType.getUnqualifiedType(),
7595 /*SuppressUserConversions=*/false, Sema::AllowedExplicit::None,
7596 /*InOverloadResolution=*/false,
7597 /*CStyle=*/false,
7598 /*AllowObjCWritebackConversion=*/false);
7599 if (ICS.isFailure()) {
7600 Diag(VariantRef->getExprLoc(),
7601 diag::err_omp_declare_variant_incompat_types)
7602 << VariantRef->getType()
7603 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7604 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7605 return std::nullopt;
7606 }
7607 VariantRefCast = SemaRef.PerformImplicitConversion(
7608 VariantRef, FnPtrType.getUnqualifiedType(),
7610 if (!VariantRefCast.isUsable())
7611 return std::nullopt;
7612 }
7613 // Drop previously built artificial addr_of unary op for member functions.
7614 if (Method && !Method->isStatic()) {
7615 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7616 if (auto *UO = dyn_cast<UnaryOperator>(
7617 PossibleAddrOfVariantRef->IgnoreImplicit()))
7618 VariantRefCast = UO->getSubExpr();
7619 }
7620 }
7621
7622 ExprResult ER = SemaRef.CheckPlaceholderExpr(VariantRefCast.get());
7623 if (!ER.isUsable() ||
7625 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7626 << VariantId << VariantRef->getSourceRange();
7627 return std::nullopt;
7628 }
7629
7630 // The VariantRef must point to function.
7631 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7632 if (!DRE) {
7633 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7634 << VariantId << VariantRef->getSourceRange();
7635 return std::nullopt;
7636 }
7637 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7638 if (!NewFD) {
7639 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7640 << VariantId << VariantRef->getSourceRange();
7641 return std::nullopt;
7642 }
7643
7644 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7645 Diag(VariantRef->getExprLoc(),
7646 diag::err_omp_declare_variant_same_base_function)
7647 << VariantRef->getSourceRange();
7648 return std::nullopt;
7649 }
7650
7651 // Check if function types are compatible in C.
7652 if (!getLangOpts().CPlusPlus) {
7653 QualType NewType =
7654 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7655 if (NewType.isNull()) {
7656 Diag(VariantRef->getExprLoc(),
7657 diag::err_omp_declare_variant_incompat_types)
7658 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7659 << VariantRef->getSourceRange();
7660 return std::nullopt;
7661 }
7662 if (NewType->isFunctionProtoType()) {
7663 if (FD->getType()->isFunctionNoProtoType())
7664 setPrototype(SemaRef, FD, NewFD, NewType);
7665 else if (NewFD->getType()->isFunctionNoProtoType())
7666 setPrototype(SemaRef, NewFD, FD, NewType);
7667 }
7668 }
7669
7670 // Check if variant function is not marked with declare variant directive.
7671 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7672 Diag(VariantRef->getExprLoc(),
7673 diag::warn_omp_declare_variant_marked_as_declare_variant)
7674 << VariantRef->getSourceRange();
7675 SourceRange SR =
7676 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7677 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7678 return std::nullopt;
7679 }
7680
7681 enum DoesntSupport {
7682 VirtFuncs = 1,
7683 Constructors = 3,
7684 Destructors = 4,
7685 DeletedFuncs = 5,
7686 DefaultedFuncs = 6,
7687 ConstexprFuncs = 7,
7688 ConstevalFuncs = 8,
7689 };
7690 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7691 if (CXXFD->isVirtual()) {
7692 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7693 << VirtFuncs;
7694 return std::nullopt;
7695 }
7696
7697 if (isa<CXXConstructorDecl>(FD)) {
7698 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7699 << Constructors;
7700 return std::nullopt;
7701 }
7702
7703 if (isa<CXXDestructorDecl>(FD)) {
7704 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7705 << Destructors;
7706 return std::nullopt;
7707 }
7708 }
7709
7710 if (FD->isDeleted()) {
7711 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7712 << DeletedFuncs;
7713 return std::nullopt;
7714 }
7715
7716 if (FD->isDefaulted()) {
7717 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7718 << DefaultedFuncs;
7719 return std::nullopt;
7720 }
7721
7722 if (FD->isConstexpr()) {
7723 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7724 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7725 return std::nullopt;
7726 }
7727
7728 // Check general compatibility.
7729 if (SemaRef.areMultiversionVariantFunctionsCompatible(
7734 VariantRef->getExprLoc(),
7735 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7736 PartialDiagnosticAt(VariantRef->getExprLoc(),
7737 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7738 << FD->getLocation()),
7739 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7740 /*CLinkageMayDiffer=*/true))
7741 return std::nullopt;
7742 return std::make_pair(FD, cast<Expr>(DRE));
7743}
7744
7746 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7747 ArrayRef<Expr *> AdjustArgsNothing,
7748 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7749 ArrayRef<Expr *> AdjustArgsNeedDeviceAddr,
7750 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7751 SourceLocation AppendArgsLoc, SourceRange SR) {
7752
7753 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7754 // An adjust_args clause or append_args clause can only be specified if the
7755 // dispatch selector of the construct selector set appears in the match
7756 // clause.
7757
7758 SmallVector<Expr *, 8> AllAdjustArgs;
7759 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7760 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7761 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDeviceAddr);
7762
7763 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7764 VariantMatchInfo VMI;
7766 if (!llvm::is_contained(
7767 VMI.ConstructTraits,
7768 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7769 if (!AllAdjustArgs.empty())
7770 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7771 << getOpenMPClauseNameForDiag(OMPC_adjust_args);
7772 if (!AppendArgs.empty())
7773 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7774 << getOpenMPClauseNameForDiag(OMPC_append_args);
7775 return;
7776 }
7777 }
7778
7779 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7780 // Each argument can only appear in a single adjust_args clause for each
7781 // declare variant directive.
7783
7784 for (Expr *E : AllAdjustArgs) {
7785 E = E->IgnoreParenImpCasts();
7786 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7787 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7788 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7789 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7790 FD->getParamDecl(PVD->getFunctionScopeIndex())
7791 ->getCanonicalDecl() == CanonPVD) {
7792 // It's a parameter of the function, check duplicates.
7793 if (!AdjustVars.insert(CanonPVD).second) {
7794 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7795 << PVD;
7796 return;
7797 }
7798 continue;
7799 }
7800 }
7801 }
7802 // Anything that is not a function parameter is an error.
7803 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7804 return;
7805 }
7806
7807 // OpenMP 6.0 [9.6.2 (page 332, line 31-33, adjust_args clause, Restrictions]
7808 // If the `need_device_addr` adjust-op modifier is present, each list item
7809 // that appears in the clause must refer to an argument in the declaration of
7810 // the function variant that has a reference type
7811 if (getLangOpts().OpenMP >= 60) {
7812 for (Expr *E : AdjustArgsNeedDeviceAddr) {
7813 E = E->IgnoreParenImpCasts();
7814 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7815 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
7816 if (!VD->getType()->isReferenceType())
7817 Diag(E->getExprLoc(),
7818 diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
7819 }
7820 }
7821 }
7822 }
7823
7824 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7825 getASTContext(), VariantRef, &TI,
7826 const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7827 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7828 AdjustArgsNeedDevicePtr.size(),
7829 const_cast<Expr **>(AdjustArgsNeedDeviceAddr.data()),
7830 AdjustArgsNeedDeviceAddr.size(),
7831 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7832 FD->addAttr(NewAttr);
7833}
7834
7835static CapturedStmt *
7837 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7838 assert(CS && "Captured statement expected");
7839 // 1.2.2 OpenMP Language Terminology
7840 // Structured block - An executable statement with a single entry at the
7841 // top and a single exit at the bottom.
7842 // The point of exit cannot be a branch out of the structured block.
7843 // longjmp() and throw() must not violate the entry/exit criteria.
7844 CS->getCapturedDecl()->setNothrow();
7845
7846 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
7847 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7849 // 1.2.2 OpenMP Language Terminology
7850 // Structured block - An executable statement with a single entry at the
7851 // top and a single exit at the bottom.
7852 // The point of exit cannot be a branch out of the structured block.
7853 // longjmp() and throw() must not violate the entry/exit criteria.
7854 CS->getCapturedDecl()->setNothrow();
7855 }
7857 return CS;
7858}
7859
7862 Stmt *AStmt, SourceLocation StartLoc,
7863 SourceLocation EndLoc) {
7864 if (!AStmt)
7865 return StmtError();
7866
7867 setBranchProtectedScope(SemaRef, OMPD_parallel, AStmt);
7868
7869 return OMPParallelDirective::Create(
7870 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
7871 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
7872}
7873
7874namespace {
7875/// Iteration space of a single for loop.
7876struct LoopIterationSpace final {
7877 /// True if the condition operator is the strict compare operator (<, > or
7878 /// !=).
7879 bool IsStrictCompare = false;
7880 /// Condition of the loop.
7881 Expr *PreCond = nullptr;
7882 /// This expression calculates the number of iterations in the loop.
7883 /// It is always possible to calculate it before starting the loop.
7884 Expr *NumIterations = nullptr;
7885 /// The loop counter variable.
7886 Expr *CounterVar = nullptr;
7887 /// Private loop counter variable.
7888 Expr *PrivateCounterVar = nullptr;
7889 /// This is initializer for the initial value of #CounterVar.
7890 Expr *CounterInit = nullptr;
7891 /// This is step for the #CounterVar used to generate its update:
7892 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7893 Expr *CounterStep = nullptr;
7894 /// Should step be subtracted?
7895 bool Subtract = false;
7896 /// Source range of the loop init.
7897 SourceRange InitSrcRange;
7898 /// Source range of the loop condition.
7899 SourceRange CondSrcRange;
7900 /// Source range of the loop increment.
7901 SourceRange IncSrcRange;
7902 /// Minimum value that can have the loop control variable. Used to support
7903 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7904 /// since only such variables can be used in non-loop invariant expressions.
7905 Expr *MinValue = nullptr;
7906 /// Maximum value that can have the loop control variable. Used to support
7907 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7908 /// since only such variables can be used in non-loop invariant expressions.
7909 Expr *MaxValue = nullptr;
7910 /// true, if the lower bound depends on the outer loop control var.
7911 bool IsNonRectangularLB = false;
7912 /// true, if the upper bound depends on the outer loop control var.
7913 bool IsNonRectangularUB = false;
7914 /// Index of the loop this loop depends on and forms non-rectangular loop
7915 /// nest.
7916 unsigned LoopDependentIdx = 0;
7917 /// Final condition for the non-rectangular loop nest support. It is used to
7918 /// check that the number of iterations for this particular counter must be
7919 /// finished.
7920 Expr *FinalCondition = nullptr;
7921};
7922
7923/// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls
7924/// set are referenced. Used for verifying loop nest structure before
7925/// performing a loop collapse operation.
7926class ForSubExprChecker : public DynamicRecursiveASTVisitor {
7927 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7928 VarDecl *ForbiddenVar = nullptr;
7929 SourceRange ErrLoc;
7930
7931public:
7932 explicit ForSubExprChecker(
7933 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7934 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
7935 // We want to visit implicit code, i.e. synthetic initialisation statements
7936 // created during range-for lowering.
7937 ShouldVisitImplicitCode = true;
7938 }
7939
7940 bool VisitDeclRefExpr(DeclRefExpr *E) override {
7941 ValueDecl *VD = E->getDecl();
7943 return true;
7944 VarDecl *V = VD->getPotentiallyDecomposedVarDecl();
7945 if (V->getType()->isReferenceType()) {
7946 VarDecl *VD = V->getDefinition();
7947 if (VD->hasInit()) {
7948 Expr *I = VD->getInit();
7949 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
7950 if (!DRE)
7951 return true;
7953 }
7954 }
7955 Decl *Canon = V->getCanonicalDecl();
7956 if (CollapsedLoopVarDecls.contains(Canon)) {
7957 ForbiddenVar = V;
7958 ErrLoc = E->getSourceRange();
7959 return false;
7960 }
7961
7962 return true;
7963 }
7964
7965 VarDecl *getForbiddenVar() const { return ForbiddenVar; }
7966 SourceRange getErrRange() const { return ErrLoc; }
7967};
7968
7969/// Helper class for checking canonical form of the OpenMP loops and
7970/// extracting iteration space of each loop in the loop nest, that will be used
7971/// for IR generation.
7972class OpenMPIterationSpaceChecker {
7973 /// Reference to Sema.
7974 Sema &SemaRef;
7975 /// Does the loop associated directive support non-rectangular loops?
7976 bool SupportsNonRectangular;
7977 /// Data-sharing stack.
7978 DSAStackTy &Stack;
7979 /// A location for diagnostics (when there is no some better location).
7980 SourceLocation DefaultLoc;
7981 /// A location for diagnostics (when increment is not compatible).
7982 SourceLocation ConditionLoc;
7983 /// The set of variables declared within the (to be collapsed) loop nest.
7984 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7985 /// A source location for referring to loop init later.
7986 SourceRange InitSrcRange;
7987 /// A source location for referring to condition later.
7988 SourceRange ConditionSrcRange;
7989 /// A source location for referring to increment later.
7990 SourceRange IncrementSrcRange;
7991 /// Loop variable.
7992 ValueDecl *LCDecl = nullptr;
7993 /// Reference to loop variable.
7994 Expr *LCRef = nullptr;
7995 /// Lower bound (initializer for the var).
7996 Expr *LB = nullptr;
7997 /// Upper bound.
7998 Expr *UB = nullptr;
7999 /// Loop step (increment).
8000 Expr *Step = nullptr;
8001 /// This flag is true when condition is one of:
8002 /// Var < UB
8003 /// Var <= UB
8004 /// UB > Var
8005 /// UB >= Var
8006 /// This will have no value when the condition is !=
8007 std::optional<bool> TestIsLessOp;
8008 /// This flag is true when condition is strict ( < or > ).
8009 bool TestIsStrictOp = false;
8010 /// This flag is true when step is subtracted on each iteration.
8011 bool SubtractStep = false;
8012 /// The outer loop counter this loop depends on (if any).
8013 const ValueDecl *DepDecl = nullptr;
8014 /// Contains number of loop (starts from 1) on which loop counter init
8015 /// expression of this loop depends on.
8016 std::optional<unsigned> InitDependOnLC;
8017 /// Contains number of loop (starts from 1) on which loop counter condition
8018 /// expression of this loop depends on.
8019 std::optional<unsigned> CondDependOnLC;
8020 /// Checks if the provide statement depends on the loop counter.
8021 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
8022 bool IsInitializer);
8023 /// Original condition required for checking of the exit condition for
8024 /// non-rectangular loop.
8025 Expr *Condition = nullptr;
8026
8027public:
8028 OpenMPIterationSpaceChecker(
8029 Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack,
8030 SourceLocation DefaultLoc,
8031 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
8032 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8033 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
8034 CollapsedLoopVarDecls(CollapsedLoopDecls) {}
8035 /// Check init-expr for canonical loop form and save loop counter
8036 /// variable - #Var and its initialization value - #LB.
8037 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
8038 /// Check test-expr for canonical form, save upper-bound (#UB), flags
8039 /// for less/greater and for strict/non-strict comparison.
8040 bool checkAndSetCond(Expr *S);
8041 /// Check incr-expr for canonical loop form and return true if it
8042 /// does not conform, otherwise save loop step (#Step).
8043 bool checkAndSetInc(Expr *S);
8044 /// Return the loop counter variable.
8045 ValueDecl *getLoopDecl() const { return LCDecl; }
8046 /// Return the reference expression to loop counter variable.
8047 Expr *getLoopDeclRefExpr() const { return LCRef; }
8048 /// Source range of the loop init.
8049 SourceRange getInitSrcRange() const { return InitSrcRange; }
8050 /// Source range of the loop condition.
8051 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
8052 /// Source range of the loop increment.
8053 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
8054 /// True if the step should be subtracted.
8055 bool shouldSubtractStep() const { return SubtractStep; }
8056 /// True, if the compare operator is strict (<, > or !=).
8057 bool isStrictTestOp() const { return TestIsStrictOp; }
8058 /// Build the expression to calculate the number of iterations.
8059 Expr *buildNumIterations(
8060 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8061 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8062 /// Build the precondition expression for the loops.
8063 Expr *
8064 buildPreCond(Scope *S, Expr *Cond,
8065 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8066 /// Build reference expression to the counter be used for codegen.
8067 DeclRefExpr *
8068 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8069 DSAStackTy &DSA) const;
8070 /// Build reference expression to the private counter be used for
8071 /// codegen.
8072 Expr *buildPrivateCounterVar() const;
8073 /// Build initialization of the counter be used for codegen.
8074 Expr *buildCounterInit() const;
8075 /// Build step of the counter be used for codegen.
8076 Expr *buildCounterStep() const;
8077 /// Build loop data with counter value for depend clauses in ordered
8078 /// directives.
8079 Expr *
8080 buildOrderedLoopData(Scope *S, Expr *Counter,
8081 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8082 SourceLocation Loc, Expr *Inc = nullptr,
8083 OverloadedOperatorKind OOK = OO_Amp);
8084 /// Builds the minimum value for the loop counter.
8085 std::pair<Expr *, Expr *> buildMinMaxValues(
8086 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8087 /// Builds final condition for the non-rectangular loops.
8088 Expr *buildFinalCondition(Scope *S) const;
8089 /// Return true if any expression is dependent.
8090 bool dependent() const;
8091 /// Returns true if the initializer forms non-rectangular loop.
8092 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
8093 /// Returns true if the condition forms non-rectangular loop.
8094 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
8095 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
8096 unsigned getLoopDependentIdx() const {
8097 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
8098 }
8099
8100private:
8101 /// Check the right-hand side of an assignment in the increment
8102 /// expression.
8103 bool checkAndSetIncRHS(Expr *RHS);
8104 /// Helper to set loop counter variable and its initializer.
8105 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8106 bool EmitDiags);
8107 /// Helper to set upper bound.
8108 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
8109 SourceRange SR, SourceLocation SL);
8110 /// Helper to set loop increment.
8111 bool setStep(Expr *NewStep, bool Subtract);
8112};
8113
8114bool OpenMPIterationSpaceChecker::dependent() const {
8115 if (!LCDecl) {
8116 assert(!LB && !UB && !Step);
8117 return false;
8118 }
8119 return LCDecl->getType()->isDependentType() ||
8120 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
8121 (Step && Step->isValueDependent());
8122}
8123
8124bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
8125 Expr *NewLCRefExpr,
8126 Expr *NewLB, bool EmitDiags) {
8127 // State consistency checking to ensure correct usage.
8128 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
8129 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8130 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
8131 return true;
8132 LCDecl = getCanonicalDecl(NewLCDecl);
8133 LCRef = NewLCRefExpr;
8134 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
8135 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8136 if ((Ctor->isCopyOrMoveConstructor() ||
8137 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8138 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8139 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
8140 LB = NewLB;
8141 if (EmitDiags)
8142 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
8143 return false;
8144}
8145
8146bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
8147 bool StrictOp, SourceRange SR,
8148 SourceLocation SL) {
8149 // State consistency checking to ensure correct usage.
8150 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
8151 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8152 if (!NewUB || NewUB->containsErrors())
8153 return true;
8154 UB = NewUB;
8155 if (LessOp)
8156 TestIsLessOp = LessOp;
8157 TestIsStrictOp = StrictOp;
8158 ConditionSrcRange = SR;
8159 ConditionLoc = SL;
8160 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
8161 return false;
8162}
8163
8164bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
8165 // State consistency checking to ensure correct usage.
8166 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
8167 if (!NewStep || NewStep->containsErrors())
8168 return true;
8169 if (!NewStep->isValueDependent()) {
8170 // Check that the step is integer expression.
8171 SourceLocation StepLoc = NewStep->getBeginLoc();
8173 StepLoc, getExprAsWritten(NewStep));
8174 if (Val.isInvalid())
8175 return true;
8176 NewStep = Val.get();
8177
8178 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8179 // If test-expr is of form var relational-op b and relational-op is < or
8180 // <= then incr-expr must cause var to increase on each iteration of the
8181 // loop. If test-expr is of form var relational-op b and relational-op is
8182 // > or >= then incr-expr must cause var to decrease on each iteration of
8183 // the loop.
8184 // If test-expr is of form b relational-op var and relational-op is < or
8185 // <= then incr-expr must cause var to decrease on each iteration of the
8186 // loop. If test-expr is of form b relational-op var and relational-op is
8187 // > or >= then incr-expr must cause var to increase on each iteration of
8188 // the loop.
8189 std::optional<llvm::APSInt> Result =
8190 NewStep->getIntegerConstantExpr(SemaRef.Context);
8191 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
8192 bool IsConstNeg =
8193 Result && Result->isSigned() && (Subtract != Result->isNegative());
8194 bool IsConstPos =
8195 Result && Result->isSigned() && (Subtract == Result->isNegative());
8196 bool IsConstZero = Result && !Result->getBoolValue();
8197
8198 // != with increment is treated as <; != with decrement is treated as >
8199 if (!TestIsLessOp)
8200 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8201 if (UB && (IsConstZero ||
8202 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8203 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8204 SemaRef.Diag(NewStep->getExprLoc(),
8205 diag::err_omp_loop_incr_not_compatible)
8206 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
8207 SemaRef.Diag(ConditionLoc,
8208 diag::note_omp_loop_cond_requires_compatible_incr)
8209 << *TestIsLessOp << ConditionSrcRange;
8210 return true;
8211 }
8212 if (*TestIsLessOp == Subtract) {
8213 NewStep =
8214 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
8215 .get();
8216 Subtract = !Subtract;
8217 }
8218 }
8219
8220 Step = NewStep;
8221 SubtractStep = Subtract;
8222 return false;
8223}
8224
8225namespace {
8226/// Checker for the non-rectangular loops. Checks if the initializer or
8227/// condition expression references loop counter variable.
8228class LoopCounterRefChecker final
8229 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8230 Sema &SemaRef;
8231 DSAStackTy &Stack;
8232 const ValueDecl *CurLCDecl = nullptr;
8233 const ValueDecl *DepDecl = nullptr;
8234 const ValueDecl *PrevDepDecl = nullptr;
8235 bool IsInitializer = true;
8236 bool SupportsNonRectangular;
8237 unsigned BaseLoopId = 0;
8238 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8239 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
8240 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8241 << (IsInitializer ? 0 : 1);
8242 return false;
8243 }
8244 const auto &&Data = Stack.isLoopControlVariable(VD);
8245 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8246 // The type of the loop iterator on which we depend may not have a random
8247 // access iterator type.
8248 if (Data.first && VD->getType()->isRecordType()) {
8249 SmallString<128> Name;
8250 llvm::raw_svector_ostream OS(Name);
8251 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8252 /*Qualified=*/true);
8253 SemaRef.Diag(E->getExprLoc(),
8254 diag::err_omp_wrong_dependency_iterator_type)
8255 << OS.str();
8256 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8257 return false;
8258 }
8259 if (Data.first && !SupportsNonRectangular) {
8260 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8261 return false;
8262 }
8263 if (Data.first &&
8264 (DepDecl || (PrevDepDecl &&
8265 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8266 if (!DepDecl && PrevDepDecl)
8267 DepDecl = PrevDepDecl;
8268 SmallString<128> Name;
8269 llvm::raw_svector_ostream OS(Name);
8270 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8271 /*Qualified=*/true);
8272 SemaRef.Diag(E->getExprLoc(),
8273 diag::err_omp_invariant_or_linear_dependency)
8274 << OS.str();
8275 return false;
8276 }
8277 if (Data.first) {
8278 DepDecl = VD;
8279 BaseLoopId = Data.first;
8280 }
8281 return Data.first;
8282 }
8283
8284public:
8285 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8286 const ValueDecl *VD = E->getDecl();
8287 if (isa<VarDecl>(VD))
8288 return checkDecl(E, VD);
8289 return false;
8290 }
8291 bool VisitMemberExpr(const MemberExpr *E) {
8292 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8293 const ValueDecl *VD = E->getMemberDecl();
8294 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8295 return checkDecl(E, VD);
8296 }
8297 return false;
8298 }
8299 bool VisitStmt(const Stmt *S) {
8300 bool Res = false;
8301 for (const Stmt *Child : S->children())
8302 Res = (Child && Visit(Child)) || Res;
8303 return Res;
8304 }
8305 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8306 const ValueDecl *CurLCDecl, bool IsInitializer,
8307 const ValueDecl *PrevDepDecl = nullptr,
8308 bool SupportsNonRectangular = true)
8309 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8310 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8311 SupportsNonRectangular(SupportsNonRectangular) {}
8312 unsigned getBaseLoopId() const {
8313 assert(CurLCDecl && "Expected loop dependency.");
8314 return BaseLoopId;
8315 }
8316 const ValueDecl *getDepDecl() const {
8317 assert(CurLCDecl && "Expected loop dependency.");
8318 return DepDecl;
8319 }
8320};
8321} // namespace
8322
8323std::optional<unsigned>
8324OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8325 bool IsInitializer) {
8326 // Check for the non-rectangular loops.
8327 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8328 DepDecl, SupportsNonRectangular);
8329 if (LoopStmtChecker.Visit(S)) {
8330 DepDecl = LoopStmtChecker.getDepDecl();
8331 return LoopStmtChecker.getBaseLoopId();
8332 }
8333 return std::nullopt;
8334}
8335
8336bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8337 // Check init-expr for canonical loop form and save loop counter
8338 // variable - #Var and its initialization value - #LB.
8339 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8340 // var = lb
8341 // integer-type var = lb
8342 // random-access-iterator-type var = lb
8343 // pointer-type var = lb
8344 //
8345 if (!S) {
8346 if (EmitDiags) {
8347 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8348 }
8349 return true;
8350 }
8351 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8352 if (!ExprTemp->cleanupsHaveSideEffects())
8353 S = ExprTemp->getSubExpr();
8354
8355 if (!CollapsedLoopVarDecls.empty()) {
8356 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8357 if (!FSEC.TraverseStmt(S)) {
8358 SourceRange Range = FSEC.getErrRange();
8359 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8360 << Range.getEnd() << 0 << FSEC.getForbiddenVar();
8361 return true;
8362 }
8363 }
8364
8365 InitSrcRange = S->getSourceRange();
8366 if (Expr *E = dyn_cast<Expr>(S))
8367 S = E->IgnoreParens();
8368 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8369 if (BO->getOpcode() == BO_Assign) {
8370 Expr *LHS = BO->getLHS()->IgnoreParens();
8371 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8372 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8373 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8374 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8375 EmitDiags);
8376 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8377 }
8378 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8379 if (ME->isArrow() &&
8380 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8381 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8382 EmitDiags);
8383 }
8384 }
8385 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8386 if (DS->isSingleDecl()) {
8387 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8388 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8389 // Accept non-canonical init form here but emit ext. warning.
8390 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8391 SemaRef.Diag(S->getBeginLoc(),
8392 diag::ext_omp_loop_not_canonical_init)
8393 << S->getSourceRange();
8394 return setLCDeclAndLB(
8395 Var,
8396 buildDeclRefExpr(SemaRef, Var,
8397 Var->getType().getNonReferenceType(),
8398 DS->getBeginLoc()),
8399 Var->getInit(), EmitDiags);
8400 }
8401 }
8402 }
8403 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8404 if (CE->getOperator() == OO_Equal) {
8405 Expr *LHS = CE->getArg(0);
8406 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8407 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8408 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8409 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8410 EmitDiags);
8411 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8412 }
8413 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8414 if (ME->isArrow() &&
8415 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8416 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8417 EmitDiags);
8418 }
8419 }
8420 }
8421
8422 if (dependent() || SemaRef.CurContext->isDependentContext())
8423 return false;
8424 if (EmitDiags) {
8425 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8426 << S->getSourceRange();
8427 }
8428 return true;
8429}
8430
8431/// Ignore parenthesizes, implicit casts, copy constructor and return the
8432/// variable (which may be the loop variable) if possible.
8433static const ValueDecl *getInitLCDecl(const Expr *E) {
8434 if (!E)
8435 return nullptr;
8436 E = getExprAsWritten(E);
8437 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8438 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8439 if ((Ctor->isCopyOrMoveConstructor() ||
8440 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8441 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8442 E = CE->getArg(0)->IgnoreParenImpCasts();
8443 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8444 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8445 return getCanonicalDecl(VD);
8446 }
8447 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8448 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8449 return getCanonicalDecl(ME->getMemberDecl());
8450 return nullptr;
8451}
8452
8453bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8454 // Check test-expr for canonical form, save upper-bound UB, flags for
8455 // less/greater and for strict/non-strict comparison.
8456 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8457 // var relational-op b
8458 // b relational-op var
8459 //
8460 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8461 if (!S) {
8462 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8463 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8464 return true;
8465 }
8466 Condition = S;
8467 S = getExprAsWritten(S);
8468
8469 if (!CollapsedLoopVarDecls.empty()) {
8470 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8471 if (!FSEC.TraverseStmt(S)) {
8472 SourceRange Range = FSEC.getErrRange();
8473 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8474 << Range.getEnd() << 1 << FSEC.getForbiddenVar();
8475 return true;
8476 }
8477 }
8478
8479 SourceLocation CondLoc = S->getBeginLoc();
8480 auto &&CheckAndSetCond =
8481 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8482 const Expr *RHS, SourceRange SR,
8483 SourceLocation OpLoc) -> std::optional<bool> {
8484 if (BinaryOperator::isRelationalOp(Opcode)) {
8485 if (getInitLCDecl(LHS) == LCDecl)
8486 return setUB(const_cast<Expr *>(RHS),
8487 (Opcode == BO_LT || Opcode == BO_LE),
8488 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8489 if (getInitLCDecl(RHS) == LCDecl)
8490 return setUB(const_cast<Expr *>(LHS),
8491 (Opcode == BO_GT || Opcode == BO_GE),
8492 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8493 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8494 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8495 /*LessOp=*/std::nullopt,
8496 /*StrictOp=*/true, SR, OpLoc);
8497 }
8498 return std::nullopt;
8499 };
8500 std::optional<bool> Res;
8501 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8502 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8503 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8504 RBO->getOperatorLoc());
8505 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8506 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8507 BO->getSourceRange(), BO->getOperatorLoc());
8508 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8509 if (CE->getNumArgs() == 2) {
8510 Res = CheckAndSetCond(
8511 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8512 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8513 }
8514 }
8515 if (Res)
8516 return *Res;
8517 if (dependent() || SemaRef.CurContext->isDependentContext())
8518 return false;
8519 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8520 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8521 return true;
8522}
8523
8524bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8525 // RHS of canonical loop form increment can be:
8526 // var + incr
8527 // incr + var
8528 // var - incr
8529 //
8530 RHS = RHS->IgnoreParenImpCasts();
8531 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8532 if (BO->isAdditiveOp()) {
8533 bool IsAdd = BO->getOpcode() == BO_Add;
8534 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8535 return setStep(BO->getRHS(), !IsAdd);
8536 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8537 return setStep(BO->getLHS(), /*Subtract=*/false);
8538 }
8539 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8540 bool IsAdd = CE->getOperator() == OO_Plus;
8541 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8542 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8543 return setStep(CE->getArg(1), !IsAdd);
8544 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8545 return setStep(CE->getArg(0), /*Subtract=*/false);
8546 }
8547 }
8548 if (dependent() || SemaRef.CurContext->isDependentContext())
8549 return false;
8550 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8551 << RHS->getSourceRange() << LCDecl;
8552 return true;
8553}
8554
8555bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8556 // Check incr-expr for canonical loop form and return true if it
8557 // does not conform.
8558 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8559 // ++var
8560 // var++
8561 // --var
8562 // var--
8563 // var += incr
8564 // var -= incr
8565 // var = var + incr
8566 // var = incr + var
8567 // var = var - incr
8568 //
8569 if (!S) {
8570 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8571 return true;
8572 }
8573 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8574 if (!ExprTemp->cleanupsHaveSideEffects())
8575 S = ExprTemp->getSubExpr();
8576
8577 if (!CollapsedLoopVarDecls.empty()) {
8578 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8579 if (!FSEC.TraverseStmt(S)) {
8580 SourceRange Range = FSEC.getErrRange();
8581 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8582 << Range.getEnd() << 2 << FSEC.getForbiddenVar();
8583 return true;
8584 }
8585 }
8586
8587 IncrementSrcRange = S->getSourceRange();
8588 S = S->IgnoreParens();
8589 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8590 if (UO->isIncrementDecrementOp() &&
8591 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8592 return setStep(SemaRef
8593 .ActOnIntegerConstant(UO->getBeginLoc(),
8594 (UO->isDecrementOp() ? -1 : 1))
8595 .get(),
8596 /*Subtract=*/false);
8597 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8598 switch (BO->getOpcode()) {
8599 case BO_AddAssign:
8600 case BO_SubAssign:
8601 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8602 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8603 break;
8604 case BO_Assign:
8605 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8606 return checkAndSetIncRHS(BO->getRHS());
8607 break;
8608 default:
8609 break;
8610 }
8611 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8612 switch (CE->getOperator()) {
8613 case OO_PlusPlus:
8614 case OO_MinusMinus:
8615 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8616 return setStep(SemaRef
8617 .ActOnIntegerConstant(
8618 CE->getBeginLoc(),
8619 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8620 .get(),
8621 /*Subtract=*/false);
8622 break;
8623 case OO_PlusEqual:
8624 case OO_MinusEqual:
8625 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8626 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8627 break;
8628 case OO_Equal:
8629 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8630 return checkAndSetIncRHS(CE->getArg(1));
8631 break;
8632 default:
8633 break;
8634 }
8635 }
8636 if (dependent() || SemaRef.CurContext->isDependentContext())
8637 return false;
8638 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8639 << S->getSourceRange() << LCDecl;
8640 return true;
8641}
8642
8643static ExprResult
8644tryBuildCapture(Sema &SemaRef, Expr *Capture,
8645 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8646 StringRef Name = ".capture_expr.") {
8647 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8648 return Capture;
8649 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8650 return SemaRef.PerformImplicitConversion(Capture->IgnoreImpCasts(),
8651 Capture->getType(),
8653 /*AllowExplicit=*/true);
8654 auto I = Captures.find(Capture);
8655 if (I != Captures.end())
8656 return buildCapture(SemaRef, Capture, I->second, Name);
8657 DeclRefExpr *Ref = nullptr;
8658 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8659 Captures[Capture] = Ref;
8660 return Res;
8661}
8662
8663/// Calculate number of iterations, transforming to unsigned, if number of
8664/// iterations may be larger than the original type.
8665static Expr *
8666calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8667 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8668 bool TestIsStrictOp, bool RoundToStep,
8669 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8670 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8671 if (!NewStep.isUsable())
8672 return nullptr;
8673 llvm::APSInt LRes, SRes;
8674 bool IsLowerConst = false, IsStepConst = false;
8675 if (std::optional<llvm::APSInt> Res =
8676 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8677 LRes = *Res;
8678 IsLowerConst = true;
8679 }
8680 if (std::optional<llvm::APSInt> Res =
8681 Step->getIntegerConstantExpr(SemaRef.Context)) {
8682 SRes = *Res;
8683 IsStepConst = true;
8684 }
8685 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8686 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8687 (TestIsStrictOp && LRes.isStrictlyPositive()));
8688 bool NeedToReorganize = false;
8689 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8690 if (!NoNeedToConvert && IsLowerConst &&
8691 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8692 NoNeedToConvert = true;
8693 if (RoundToStep) {
8694 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8695 ? LRes.getBitWidth()
8696 : SRes.getBitWidth();
8697 LRes = LRes.extend(BW + 1);
8698 LRes.setIsSigned(true);
8699 SRes = SRes.extend(BW + 1);
8700 SRes.setIsSigned(true);
8701 LRes -= SRes;
8702 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8703 LRes = LRes.trunc(BW);
8704 }
8705 if (TestIsStrictOp) {
8706 unsigned BW = LRes.getBitWidth();
8707 LRes = LRes.extend(BW + 1);
8708 LRes.setIsSigned(true);
8709 ++LRes;
8710 NoNeedToConvert =
8711 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8712 // truncate to the original bitwidth.
8713 LRes = LRes.trunc(BW);
8714 }
8715 NeedToReorganize = NoNeedToConvert;
8716 }
8717 llvm::APSInt URes;
8718 bool IsUpperConst = false;
8719 if (std::optional<llvm::APSInt> Res =
8720 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8721 URes = *Res;
8722 IsUpperConst = true;
8723 }
8724 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8725 (!RoundToStep || IsStepConst)) {
8726 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8727 : URes.getBitWidth();
8728 LRes = LRes.extend(BW + 1);
8729 LRes.setIsSigned(true);
8730 URes = URes.extend(BW + 1);
8731 URes.setIsSigned(true);
8732 URes -= LRes;
8733 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8734 NeedToReorganize = NoNeedToConvert;
8735 }
8736 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8737 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8738 // unsigned.
8739 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8740 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8741 QualType LowerTy = Lower->getType();
8742 QualType UpperTy = Upper->getType();
8743 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8744 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8745 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8746 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8748 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8749 Upper =
8750 SemaRef
8752 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8754 .get();
8755 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8756 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8757 }
8758 }
8759 if (!Lower || !Upper || NewStep.isInvalid())
8760 return nullptr;
8761
8762 ExprResult Diff;
8763 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8764 // 1]).
8765 if (NeedToReorganize) {
8766 Diff = Lower;
8767
8768 if (RoundToStep) {
8769 // Lower - Step
8770 Diff =
8771 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8772 if (!Diff.isUsable())
8773 return nullptr;
8774 }
8775
8776 // Lower - Step [+ 1]
8777 if (TestIsStrictOp)
8778 Diff = SemaRef.BuildBinOp(
8779 S, DefaultLoc, BO_Add, Diff.get(),
8780 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8781 if (!Diff.isUsable())
8782 return nullptr;
8783
8784 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8785 if (!Diff.isUsable())
8786 return nullptr;
8787
8788 // Upper - (Lower - Step [+ 1]).
8789 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8790 if (!Diff.isUsable())
8791 return nullptr;
8792 } else {
8793 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8794
8795 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8796 // BuildBinOp already emitted error, this one is to point user to upper
8797 // and lower bound, and to tell what is passed to 'operator-'.
8798 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8799 << Upper->getSourceRange() << Lower->getSourceRange();
8800 return nullptr;
8801 }
8802
8803 if (!Diff.isUsable())
8804 return nullptr;
8805
8806 // Upper - Lower [- 1]
8807 if (TestIsStrictOp)
8808 Diff = SemaRef.BuildBinOp(
8809 S, DefaultLoc, BO_Sub, Diff.get(),
8810 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8811 if (!Diff.isUsable())
8812 return nullptr;
8813
8814 if (RoundToStep) {
8815 // Upper - Lower [- 1] + Step
8816 Diff =
8817 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8818 if (!Diff.isUsable())
8819 return nullptr;
8820 }
8821 }
8822
8823 // Parentheses (for dumping/debugging purposes only).
8824 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8825 if (!Diff.isUsable())
8826 return nullptr;
8827
8828 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8829 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8830 if (!Diff.isUsable())
8831 return nullptr;
8832
8833 return Diff.get();
8834}
8835
8836/// Build the expression to calculate the number of iterations.
8837Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8838 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8839 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8840 QualType VarType = LCDecl->getType().getNonReferenceType();
8841 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8842 !SemaRef.getLangOpts().CPlusPlus)
8843 return nullptr;
8844 Expr *LBVal = LB;
8845 Expr *UBVal = UB;
8846 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8847 // max(LB(MinVal), LB(MaxVal)))
8848 if (InitDependOnLC) {
8849 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8850 if (!IS.MinValue || !IS.MaxValue)
8851 return nullptr;
8852 // OuterVar = Min
8853 ExprResult MinValue =
8854 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8855 if (!MinValue.isUsable())
8856 return nullptr;
8857
8858 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8859 IS.CounterVar, MinValue.get());
8860 if (!LBMinVal.isUsable())
8861 return nullptr;
8862 // OuterVar = Min, LBVal
8863 LBMinVal =
8864 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8865 if (!LBMinVal.isUsable())
8866 return nullptr;
8867 // (OuterVar = Min, LBVal)
8868 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8869 if (!LBMinVal.isUsable())
8870 return nullptr;
8871
8872 // OuterVar = Max
8873 ExprResult MaxValue =
8874 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8875 if (!MaxValue.isUsable())
8876 return nullptr;
8877
8878 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8879 IS.CounterVar, MaxValue.get());
8880 if (!LBMaxVal.isUsable())
8881 return nullptr;
8882 // OuterVar = Max, LBVal
8883 LBMaxVal =
8884 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8885 if (!LBMaxVal.isUsable())
8886 return nullptr;
8887 // (OuterVar = Max, LBVal)
8888 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8889 if (!LBMaxVal.isUsable())
8890 return nullptr;
8891
8892 Expr *LBMin =
8893 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
8894 Expr *LBMax =
8895 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
8896 if (!LBMin || !LBMax)
8897 return nullptr;
8898 // LB(MinVal) < LB(MaxVal)
8899 ExprResult MinLessMaxRes =
8900 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8901 if (!MinLessMaxRes.isUsable())
8902 return nullptr;
8903 Expr *MinLessMax =
8904 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
8905 .get();
8906 if (!MinLessMax)
8907 return nullptr;
8908 if (*TestIsLessOp) {
8909 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8910 // LB(MaxVal))
8911 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8912 MinLessMax, LBMin, LBMax);
8913 if (!MinLB.isUsable())
8914 return nullptr;
8915 LBVal = MinLB.get();
8916 } else {
8917 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8918 // LB(MaxVal))
8919 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8920 MinLessMax, LBMax, LBMin);
8921 if (!MaxLB.isUsable())
8922 return nullptr;
8923 LBVal = MaxLB.get();
8924 }
8925 // OuterVar = LB
8926 LBMinVal =
8927 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8928 if (!LBMinVal.isUsable())
8929 return nullptr;
8930 LBVal = LBMinVal.get();
8931 }
8932 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8933 // min(UB(MinVal), UB(MaxVal))
8934 if (CondDependOnLC) {
8935 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8936 if (!IS.MinValue || !IS.MaxValue)
8937 return nullptr;
8938 // OuterVar = Min
8939 ExprResult MinValue =
8940 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8941 if (!MinValue.isUsable())
8942 return nullptr;
8943
8944 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8945 IS.CounterVar, MinValue.get());
8946 if (!UBMinVal.isUsable())
8947 return nullptr;
8948 // OuterVar = Min, UBVal
8949 UBMinVal =
8950 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
8951 if (!UBMinVal.isUsable())
8952 return nullptr;
8953 // (OuterVar = Min, UBVal)
8954 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
8955 if (!UBMinVal.isUsable())
8956 return nullptr;
8957
8958 // OuterVar = Max
8959 ExprResult MaxValue =
8960 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8961 if (!MaxValue.isUsable())
8962 return nullptr;
8963
8964 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8965 IS.CounterVar, MaxValue.get());
8966 if (!UBMaxVal.isUsable())
8967 return nullptr;
8968 // OuterVar = Max, UBVal
8969 UBMaxVal =
8970 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
8971 if (!UBMaxVal.isUsable())
8972 return nullptr;
8973 // (OuterVar = Max, UBVal)
8974 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
8975 if (!UBMaxVal.isUsable())
8976 return nullptr;
8977
8978 Expr *UBMin =
8979 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
8980 Expr *UBMax =
8981 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
8982 if (!UBMin || !UBMax)
8983 return nullptr;
8984 // UB(MinVal) > UB(MaxVal)
8985 ExprResult MinGreaterMaxRes =
8986 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8987 if (!MinGreaterMaxRes.isUsable())
8988 return nullptr;
8989 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
8990 Captures, ".min_greater_max")
8991 .get();
8992 if (!MinGreaterMax)
8993 return nullptr;
8994 if (*TestIsLessOp) {
8995 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8996 // UB(MaxVal))
8997 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
8998 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8999 if (!MaxUB.isUsable())
9000 return nullptr;
9001 UBVal = MaxUB.get();
9002 } else {
9003 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
9004 // UB(MaxVal))
9005 ExprResult MinUB = SemaRef.ActOnConditionalOp(
9006 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
9007 if (!MinUB.isUsable())
9008 return nullptr;
9009 UBVal = MinUB.get();
9010 }
9011 }
9012 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9013 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9014 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
9015 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
9016 if (!Upper || !Lower)
9017 return nullptr;
9018
9019 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9020 Step, VarType, TestIsStrictOp,
9021 /*RoundToStep=*/true, Captures);
9022 if (!Diff.isUsable())
9023 return nullptr;
9024
9025 // OpenMP runtime requires 32-bit or 64-bit loop variables.
9026 QualType Type = Diff.get()->getType();
9027 ASTContext &C = SemaRef.Context;
9028 bool UseVarType = VarType->hasIntegerRepresentation() &&
9029 C.getTypeSize(Type) > C.getTypeSize(VarType);
9030 if (!Type->isIntegerType() || UseVarType) {
9031 unsigned NewSize =
9032 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
9033 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
9035 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
9036 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
9037 Diff = SemaRef.PerformImplicitConversion(Diff.get(), Type,
9039 /*AllowExplicit=*/true);
9040 if (!Diff.isUsable())
9041 return nullptr;
9042 }
9043 }
9044 if (LimitedType) {
9045 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
9046 if (NewSize != C.getTypeSize(Type)) {
9047 if (NewSize < C.getTypeSize(Type)) {
9048 assert(NewSize == 64 && "incorrect loop var size");
9049 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
9050 << InitSrcRange << ConditionSrcRange;
9051 }
9052 QualType NewType = C.getIntTypeForBitwidth(
9054 C.getTypeSize(Type) < NewSize);
9055 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
9056 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
9058 /*AllowExplicit=*/true);
9059 if (!Diff.isUsable())
9060 return nullptr;
9061 }
9062 }
9063 }
9064
9065 return Diff.get();
9066}
9067
9068std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9069 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9070 // Do not build for iterators, they cannot be used in non-rectangular loop
9071 // nests.
9072 if (LCDecl->getType()->isRecordType())
9073 return std::make_pair(nullptr, nullptr);
9074 // If we subtract, the min is in the condition, otherwise the min is in the
9075 // init value.
9076 Expr *MinExpr = nullptr;
9077 Expr *MaxExpr = nullptr;
9078 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9079 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9080 bool LBNonRect =
9081 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9082 bool UBNonRect =
9083 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9084 Expr *Lower =
9085 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
9086 Expr *Upper =
9087 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
9088 if (!Upper || !Lower)
9089 return std::make_pair(nullptr, nullptr);
9090
9091 if (*TestIsLessOp)
9092 MinExpr = Lower;
9093 else
9094 MaxExpr = Upper;
9095
9096 // Build minimum/maximum value based on number of iterations.
9097 QualType VarType = LCDecl->getType().getNonReferenceType();
9098
9099 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9100 Step, VarType, TestIsStrictOp,
9101 /*RoundToStep=*/false, Captures);
9102 if (!Diff.isUsable())
9103 return std::make_pair(nullptr, nullptr);
9104
9105 // ((Upper - Lower [- 1]) / Step) * Step
9106 // Parentheses (for dumping/debugging purposes only).
9107 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9108 if (!Diff.isUsable())
9109 return std::make_pair(nullptr, nullptr);
9110
9111 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
9112 if (!NewStep.isUsable())
9113 return std::make_pair(nullptr, nullptr);
9114 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
9115 if (!Diff.isUsable())
9116 return std::make_pair(nullptr, nullptr);
9117
9118 // Parentheses (for dumping/debugging purposes only).
9119 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9120 if (!Diff.isUsable())
9121 return std::make_pair(nullptr, nullptr);
9122
9123 // Convert to the ptrdiff_t, if original type is pointer.
9124 if (VarType->isAnyPointerType() &&
9125 !SemaRef.Context.hasSameType(
9126 Diff.get()->getType(),
9128 Diff = SemaRef.PerformImplicitConversion(
9129 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
9130 AssignmentAction::Converting, /*AllowExplicit=*/true);
9131 }
9132 if (!Diff.isUsable())
9133 return std::make_pair(nullptr, nullptr);
9134
9135 if (*TestIsLessOp) {
9136 // MinExpr = Lower;
9137 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
9138 Diff = SemaRef.BuildBinOp(
9139 S, DefaultLoc, BO_Add,
9140 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
9141 Diff.get());
9142 if (!Diff.isUsable())
9143 return std::make_pair(nullptr, nullptr);
9144 } else {
9145 // MaxExpr = Upper;
9146 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
9147 Diff = SemaRef.BuildBinOp(
9148 S, DefaultLoc, BO_Sub,
9149 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
9150 Diff.get());
9151 if (!Diff.isUsable())
9152 return std::make_pair(nullptr, nullptr);
9153 }
9154
9155 // Convert to the original type.
9156 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
9157 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
9159 /*AllowExplicit=*/true);
9160 if (!Diff.isUsable())
9161 return std::make_pair(nullptr, nullptr);
9162
9163 Sema::TentativeAnalysisScope Trap(SemaRef);
9164 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
9165 if (!Diff.isUsable())
9166 return std::make_pair(nullptr, nullptr);
9167
9168 if (*TestIsLessOp)
9169 MaxExpr = Diff.get();
9170 else
9171 MinExpr = Diff.get();
9172
9173 return std::make_pair(MinExpr, MaxExpr);
9174}
9175
9176Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
9177 if (InitDependOnLC || CondDependOnLC)
9178 return Condition;
9179 return nullptr;
9180}
9181
9182Expr *OpenMPIterationSpaceChecker::buildPreCond(
9183 Scope *S, Expr *Cond,
9184 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9185 // Do not build a precondition when the condition/initialization is dependent
9186 // to prevent pessimistic early loop exit.
9187 // TODO: this can be improved by calculating min/max values but not sure that
9188 // it will be very effective.
9189 if (CondDependOnLC || InitDependOnLC)
9190 return SemaRef
9192 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
9193 SemaRef.Context.BoolTy, /*Action=*/AssignmentAction::Casting,
9194 /*AllowExplicit=*/true)
9195 .get();
9196
9197 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
9198 Sema::TentativeAnalysisScope Trap(SemaRef);
9199
9200 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9201 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9202 if (!NewLB.isUsable() || !NewUB.isUsable())
9203 return nullptr;
9204
9205 ExprResult CondExpr =
9206 SemaRef.BuildBinOp(S, DefaultLoc,
9207 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9208 : (TestIsStrictOp ? BO_GT : BO_GE),
9209 NewLB.get(), NewUB.get());
9210 if (CondExpr.isUsable()) {
9211 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
9212 SemaRef.Context.BoolTy))
9213 CondExpr = SemaRef.PerformImplicitConversion(
9214 CondExpr.get(), SemaRef.Context.BoolTy,
9215 /*Action=*/AssignmentAction::Casting,
9216 /*AllowExplicit=*/true);
9217 }
9218
9219 // Otherwise use original loop condition and evaluate it in runtime.
9220 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9221}
9222
9223/// Build reference expression to the counter be used for codegen.
9224DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9225 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9226 DSAStackTy &DSA) const {
9227 auto *VD = dyn_cast<VarDecl>(LCDecl);
9228 if (!VD) {
9229 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(LCDecl);
9231 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
9232 const DSAStackTy::DSAVarData Data =
9233 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
9234 // If the loop control decl is explicitly marked as private, do not mark it
9235 // as captured again.
9236 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
9237 Captures.insert(std::make_pair(LCRef, Ref));
9238 return Ref;
9239 }
9240 return cast<DeclRefExpr>(LCRef);
9241}
9242
9243Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9244 if (LCDecl && !LCDecl->isInvalidDecl()) {
9246 VarDecl *PrivateVar = buildVarDecl(
9247 SemaRef, DefaultLoc, Type, LCDecl->getName(),
9248 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9249 isa<VarDecl>(LCDecl)
9250 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
9251 : nullptr);
9252 if (PrivateVar->isInvalidDecl())
9253 return nullptr;
9254 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
9255 }
9256 return nullptr;
9257}
9258
9259/// Build initialization of the counter to be used for codegen.
9260Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9261
9262/// Build step of the counter be used for codegen.
9263Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9264
9265Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9266 Scope *S, Expr *Counter,
9267 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9268 Expr *Inc, OverloadedOperatorKind OOK) {
9269 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
9270 if (!Cnt)
9271 return nullptr;
9272 if (Inc) {
9273 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9274 "Expected only + or - operations for depend clauses.");
9275 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9276 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
9277 if (!Cnt)
9278 return nullptr;
9279 }
9280 QualType VarType = LCDecl->getType().getNonReferenceType();
9281 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9282 !SemaRef.getLangOpts().CPlusPlus)
9283 return nullptr;
9284 // Upper - Lower
9285 Expr *Upper =
9286 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9287 Expr *Lower =
9288 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9289 if (!Upper || !Lower)
9290 return nullptr;
9291
9292 ExprResult Diff = calculateNumIters(
9293 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9294 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9295 if (!Diff.isUsable())
9296 return nullptr;
9297
9298 return Diff.get();
9299}
9300} // namespace
9301
9303 Stmt *Init) {
9304 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9305 assert(Init && "Expected loop in canonical form.");
9306 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9307 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9308 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
9309 return;
9310
9311 DSAStack->loopStart();
9313 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9314 *DSAStack, ForLoc, EmptyDeclSet);
9315 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9316 if (ValueDecl *D = ISC.getLoopDecl()) {
9317 auto *VD = dyn_cast<VarDecl>(D);
9318 DeclRefExpr *PrivateRef = nullptr;
9319 if (!VD) {
9321 VD = Private;
9322 } else {
9323 PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(),
9324 /*WithInit=*/false);
9325 VD = cast<VarDecl>(PrivateRef->getDecl());
9326 }
9327 }
9328 DSAStack->addLoopControlVariable(D, VD);
9329 const Decl *LD = DSAStack->getPossiblyLoopCounter();
9330 if (LD != D->getCanonicalDecl()) {
9331 DSAStack->resetPossibleLoopCounter();
9332 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9333 SemaRef.MarkDeclarationsReferencedInExpr(buildDeclRefExpr(
9334 SemaRef, const_cast<VarDecl *>(Var),
9335 Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
9336 /*RefersToCapture=*/true));
9337 }
9338 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9339 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9340 // associated for-loop of a simd construct with just one associated
9341 // for-loop may be listed in a linear clause with a constant-linear-step
9342 // that is the increment of the associated for-loop. The loop iteration
9343 // variable(s) in the associated for-loop(s) of a for or parallel for
9344 // construct may be listed in a private or lastprivate clause.
9345 DSAStackTy::DSAVarData DVar =
9346 DSAStack->getTopDSA(D, /*FromParent=*/false);
9347 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9348 // is declared in the loop and it is predetermined as a private.
9349 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9350 OpenMPClauseKind PredeterminedCKind =
9352 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9353 : OMPC_private;
9354 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
9355 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9356 };
9357 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9358 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9359 (getLangOpts().OpenMP <= 45 ||
9360 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9362 IsOpenMPTaskloopDirective(DKind) ||
9364 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9365 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9366 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9367 unsigned OMPVersion = getLangOpts().OpenMP;
9368 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9369 << getOpenMPClauseNameForDiag(DVar.CKind)
9370 << getOpenMPDirectiveName(DKind, OMPVersion)
9371 << getOpenMPClauseNameForDiag(PredeterminedCKind);
9372 if (DVar.RefExpr == nullptr)
9373 DVar.CKind = PredeterminedCKind;
9374 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
9375 } else if (LoopDeclRefExpr) {
9376 // Make the loop iteration variable private (for worksharing
9377 // constructs), linear (for simd directives with the only one
9378 // associated loop) or lastprivate (for simd directives with several
9379 // collapsed or ordered loops).
9380 if (DVar.CKind == OMPC_unknown)
9381 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9382 }
9383 }
9384 }
9385 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9386}
9387
9388namespace {
9389// Utility for OpenMP doacross clause kind
9390class OMPDoacrossKind {
9391public:
9392 bool isSource(const OMPDoacrossClause *C) {
9393 return C->getDependenceType() == OMPC_DOACROSS_source ||
9394 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9395 }
9396 bool isSink(const OMPDoacrossClause *C) {
9397 return C->getDependenceType() == OMPC_DOACROSS_sink;
9398 }
9399 bool isSinkIter(const OMPDoacrossClause *C) {
9400 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9401 }
9402};
9403} // namespace
9404/// Called on a for stmt to check and extract its iteration space
9405/// for further processing (such as collapsing).
9407 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9408 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9409 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9410 Expr *OrderedLoopCountExpr,
9411 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9413 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9414 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9415 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9416 // OpenMP [2.9.1, Canonical Loop Form]
9417 // for (init-expr; test-expr; incr-expr) structured-block
9418 // for (range-decl: range-expr) structured-block
9419 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9420 S = CanonLoop->getLoopStmt();
9421 auto *For = dyn_cast_or_null<ForStmt>(S);
9422 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9423 // Ranged for is supported only in OpenMP 5.0.
9424 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9425 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
9426 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9427 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9428 << getOpenMPDirectiveName(DKind, OMPVersion) << TotalNestedLoopCount
9429 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9430 if (TotalNestedLoopCount > 1) {
9431 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9432 SemaRef.Diag(DSA.getConstructLoc(),
9433 diag::note_omp_collapse_ordered_expr)
9434 << 2 << CollapseLoopCountExpr->getSourceRange()
9435 << OrderedLoopCountExpr->getSourceRange();
9436 else if (CollapseLoopCountExpr)
9437 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9438 diag::note_omp_collapse_ordered_expr)
9439 << 0 << CollapseLoopCountExpr->getSourceRange();
9440 else if (OrderedLoopCountExpr)
9441 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9442 diag::note_omp_collapse_ordered_expr)
9443 << 1 << OrderedLoopCountExpr->getSourceRange();
9444 }
9445 return true;
9446 }
9447 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9448 "No loop body.");
9449 // Postpone analysis in dependent contexts for ranged for loops.
9450 if (CXXFor && SemaRef.CurContext->isDependentContext())
9451 return false;
9452
9453 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9454 For ? For->getForLoc() : CXXFor->getForLoc(),
9455 CollapsedLoopVarDecls);
9456
9457 // Check init.
9458 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9459 if (ISC.checkAndSetInit(Init))
9460 return true;
9461
9462 bool HasErrors = false;
9463
9464 // Check loop variable's type.
9465 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9466 // OpenMP [2.6, Canonical Loop Form]
9467 // Var is one of the following:
9468 // A variable of signed or unsigned integer type.
9469 // For C++, a variable of a random access iterator type.
9470 // For C, a variable of a pointer type.
9471 QualType VarType = LCDecl->getType().getNonReferenceType();
9472 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9473 !VarType->isPointerType() &&
9474 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9475 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9476 << SemaRef.getLangOpts().CPlusPlus;
9477 HasErrors = true;
9478 }
9479
9480 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9481 // a Construct
9482 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9483 // parallel for construct is (are) private.
9484 // The loop iteration variable in the associated for-loop of a simd
9485 // construct with just one associated for-loop is linear with a
9486 // constant-linear-step that is the increment of the associated for-loop.
9487 // Exclude loop var from the list of variables with implicitly defined data
9488 // sharing attributes.
9489 VarsWithImplicitDSA.erase(LCDecl);
9490
9491 assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
9492
9493 // Check test-expr.
9494 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9495
9496 // Check incr-expr.
9497 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9498 }
9499
9500 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9501 return HasErrors;
9502
9503 // Build the loop's iteration space representation.
9504 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9505 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9506 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9507 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9513 Captures);
9514 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9515 ISC.buildCounterVar(Captures, DSA);
9516 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9517 ISC.buildPrivateCounterVar();
9518 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9519 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9520 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9521 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9522 ISC.getConditionSrcRange();
9523 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9524 ISC.getIncrementSrcRange();
9525 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9526 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9527 ISC.isStrictTestOp();
9528 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9529 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9530 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9531 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9532 ISC.buildFinalCondition(DSA.getCurScope());
9533 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9534 ISC.doesInitDependOnLC();
9535 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9536 ISC.doesCondDependOnLC();
9537 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9538 ISC.getLoopDependentIdx();
9539
9540 HasErrors |=
9541 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9542 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9543 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9544 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9545 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9546 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9547 if (!HasErrors && DSA.isOrderedRegion()) {
9548 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9549 if (CurrentNestedLoopCount <
9550 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9551 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9552 CurrentNestedLoopCount,
9553 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9554 DSA.getOrderedRegionParam().second->setLoopCounter(
9555 CurrentNestedLoopCount,
9556 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9557 }
9558 }
9559 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9560 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9561 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9562 unsigned NumLoops =
9563 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9564 if (CurrentNestedLoopCount >= NumLoops) {
9565 // Erroneous case - clause has some problems.
9566 continue;
9567 }
9568 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9569 Pair.second.size() <= CurrentNestedLoopCount) {
9570 // Erroneous case - clause has some problems.
9571 DependC->setLoopData(CurrentNestedLoopCount, nullptr);
9572 continue;
9573 }
9574 OMPDoacrossKind ODK;
9575 if (DoacrossC && ODK.isSink(DoacrossC) &&
9576 Pair.second.size() <= CurrentNestedLoopCount) {
9577 // Erroneous case - clause has some problems.
9578 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
9579 continue;
9580 }
9581 Expr *CntValue;
9582 SourceLocation DepLoc =
9583 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9584 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9585 (DoacrossC && ODK.isSource(DoacrossC)))
9586 CntValue = ISC.buildOrderedLoopData(
9587 DSA.getCurScope(),
9588 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9589 DepLoc);
9590 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9591 Expr *Cnt = SemaRef
9593 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9594 .get();
9595 if (!Cnt)
9596 continue;
9597 // build CounterVar - 1
9598 Expr *Inc =
9599 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
9600 .get();
9601 CntValue = ISC.buildOrderedLoopData(
9602 DSA.getCurScope(),
9603 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9604 DepLoc, Inc, clang::OO_Minus);
9605 } else
9606 CntValue = ISC.buildOrderedLoopData(
9607 DSA.getCurScope(),
9608 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9609 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9610 Pair.second[CurrentNestedLoopCount].second);
9611 if (DependC)
9612 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9613 else
9614 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9615 }
9616 }
9617
9618 return HasErrors;
9619}
9620
9621/// Build 'VarRef = Start.
9622static ExprResult
9624 ExprResult Start, bool IsNonRectangularLB,
9625 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9626 // Build 'VarRef = Start.
9627 ExprResult NewStart = IsNonRectangularLB
9628 ? Start.get()
9629 : tryBuildCapture(SemaRef, Start.get(), Captures);
9630 if (!NewStart.isUsable())
9631 return ExprError();
9632 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9633 VarRef.get()->getType())) {
9634 NewStart = SemaRef.PerformImplicitConversion(
9635 NewStart.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9636 /*AllowExplicit=*/true);
9637 if (!NewStart.isUsable())
9638 return ExprError();
9639 }
9640
9642 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9643 return Init;
9644}
9645
9646/// Build 'VarRef = Start + Iter * Step'.
9648 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9649 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9650 bool IsNonRectangularLB,
9651 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9652 // Add parentheses (for debugging purposes only).
9653 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9654 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9655 !Step.isUsable())
9656 return ExprError();
9657
9658 ExprResult NewStep = Step;
9659 if (Captures)
9660 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9661 if (NewStep.isInvalid())
9662 return ExprError();
9664 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9665 if (!Update.isUsable())
9666 return ExprError();
9667
9668 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9669 // 'VarRef = Start (+|-) Iter * Step'.
9670 if (!Start.isUsable())
9671 return ExprError();
9672 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9673 if (!NewStart.isUsable())
9674 return ExprError();
9675 if (Captures && !IsNonRectangularLB)
9676 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9677 if (NewStart.isInvalid())
9678 return ExprError();
9679
9680 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9681 ExprResult SavedUpdate = Update;
9682 ExprResult UpdateVal;
9683 if (VarRef.get()->getType()->isOverloadableType() ||
9684 NewStart.get()->getType()->isOverloadableType() ||
9685 Update.get()->getType()->isOverloadableType()) {
9686 Sema::TentativeAnalysisScope Trap(SemaRef);
9687
9688 Update =
9689 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9690 if (Update.isUsable()) {
9691 UpdateVal =
9692 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9693 VarRef.get(), SavedUpdate.get());
9694 if (UpdateVal.isUsable()) {
9695 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9696 UpdateVal.get());
9697 }
9698 }
9699 }
9700
9701 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9702 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9703 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9704 NewStart.get(), SavedUpdate.get());
9705 if (!Update.isUsable())
9706 return ExprError();
9707
9708 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9709 VarRef.get()->getType())) {
9711 Update.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9712 /*AllowExplicit=*/true);
9713 if (!Update.isUsable())
9714 return ExprError();
9715 }
9716
9717 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9718 }
9719 return Update;
9720}
9721
9722/// Convert integer expression \a E to make it have at least \a Bits
9723/// bits.
9724static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9725 if (E == nullptr)
9726 return ExprError();
9727 ASTContext &C = SemaRef.Context;
9728 QualType OldType = E->getType();
9729 unsigned HasBits = C.getTypeSize(OldType);
9730 if (HasBits >= Bits)
9731 return ExprResult(E);
9732 // OK to convert to signed, because new type has more bits than old.
9733 QualType NewType = C.getIntTypeForBitwidth(Bits, /*Signed=*/true);
9734 return SemaRef.PerformImplicitConversion(
9735 E, NewType, AssignmentAction::Converting, /*AllowExplicit=*/true);
9736}
9737
9738/// Check if the given expression \a E is a constant integer that fits
9739/// into \a Bits bits.
9740static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9741 if (E == nullptr)
9742 return false;
9743 if (std::optional<llvm::APSInt> Result =
9744 E->getIntegerConstantExpr(SemaRef.Context))
9745 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9746 return false;
9747}
9748
9749/// Build preinits statement for the given declarations.
9751 MutableArrayRef<Decl *> PreInits) {
9752 if (!PreInits.empty()) {
9753 return new (Context) DeclStmt(
9754 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9756 }
9757 return nullptr;
9758}
9759
9760/// Append the \p Item or the content of a CompoundStmt to the list \p
9761/// TargetList.
9762///
9763/// A CompoundStmt is used as container in case multiple statements need to be
9764/// stored in lieu of using an explicit list. Flattening is necessary because
9765/// contained DeclStmts need to be visible after the execution of the list. Used
9766/// for OpenMP pre-init declarations/statements.
9768 Stmt *Item) {
9769 // nullptr represents an empty list.
9770 if (!Item)
9771 return;
9772
9773 if (auto *CS = dyn_cast<CompoundStmt>(Item))
9774 llvm::append_range(TargetList, CS->body());
9775 else
9776 TargetList.push_back(Item);
9777}
9778
9779/// Build preinits statement for the given declarations.
9780static Stmt *
9782 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9783 if (!Captures.empty()) {
9784 SmallVector<Decl *, 16> PreInits;
9785 for (const auto &Pair : Captures)
9786 PreInits.push_back(Pair.second->getDecl());
9787 return buildPreInits(Context, PreInits);
9788 }
9789 return nullptr;
9790}
9791
9792/// Build pre-init statement for the given statements.
9793static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
9794 if (PreInits.empty())
9795 return nullptr;
9796
9797 SmallVector<Stmt *> Stmts;
9798 for (Stmt *S : PreInits)
9799 appendFlattenedStmtList(Stmts, S);
9800 return CompoundStmt::Create(Context, PreInits, FPOptionsOverride(), {}, {});
9801}
9802
9803/// Build postupdate expression for the given list of postupdates expressions.
9804static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9805 Expr *PostUpdate = nullptr;
9806 if (!PostUpdates.empty()) {
9807 for (Expr *E : PostUpdates) {
9808 Expr *ConvE = S.BuildCStyleCastExpr(
9809 E->getExprLoc(),
9811 E->getExprLoc(), E)
9812 .get();
9813 PostUpdate = PostUpdate
9814 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9815 PostUpdate, ConvE)
9816 .get()
9817 : ConvE;
9818 }
9819 }
9820 return PostUpdate;
9821}
9822
9823/// Look for variables declared in the body parts of a for-loop nest. Used
9824/// for verifying loop nest structure before performing a loop collapse
9825/// operation.
9827 int NestingDepth = 0;
9828 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9829
9830public:
9831 explicit ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl *> &VD)
9832 : VarDecls(VD) {}
9833
9834 bool VisitForStmt(ForStmt *F) override {
9835 ++NestingDepth;
9836 TraverseStmt(F->getBody());
9837 --NestingDepth;
9838 return false;
9839 }
9840
9842 ++NestingDepth;
9843 TraverseStmt(RF->getBody());
9844 --NestingDepth;
9845 return false;
9846 }
9847
9848 bool VisitVarDecl(VarDecl *D) override {
9849 Decl *C = D->getCanonicalDecl();
9850 if (NestingDepth > 0)
9851 VarDecls.insert(C);
9852 return true;
9853 }
9854};
9855
9856/// Called on a for stmt to check itself and nested loops (if any).
9857/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9858/// number of collapsed loops otherwise.
9859static unsigned
9860checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9861 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9862 DSAStackTy &DSA,
9863 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9864 OMPLoopBasedDirective::HelperExprs &Built) {
9865 // If either of the loop expressions exist and contain errors, we bail out
9866 // early because diagnostics have already been emitted and we can't reliably
9867 // check more about the loop.
9868 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->containsErrors()) ||
9869 (OrderedLoopCountExpr && OrderedLoopCountExpr->containsErrors()))
9870 return 0;
9871
9872 unsigned NestedLoopCount = 1;
9873 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9875 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopVarDecls;
9876
9877 if (CollapseLoopCountExpr) {
9878 // Found 'collapse' clause - calculate collapse number.
9879 Expr::EvalResult Result;
9880 if (!CollapseLoopCountExpr->isValueDependent() &&
9881 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9882 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9883
9884 ForVarDeclFinder FVDF{CollapsedLoopVarDecls};
9885 FVDF.TraverseStmt(AStmt);
9886 } else {
9887 Built.clear(/*Size=*/1);
9888 return 1;
9889 }
9890 }
9891 unsigned OrderedLoopCount = 1;
9892 if (OrderedLoopCountExpr) {
9893 // Found 'ordered' clause - calculate collapse number.
9894 Expr::EvalResult EVResult;
9895 if (!OrderedLoopCountExpr->isValueDependent() &&
9896 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9897 SemaRef.getASTContext())) {
9898 llvm::APSInt Result = EVResult.Val.getInt();
9899 if (Result.getLimitedValue() < NestedLoopCount) {
9900 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9901 diag::err_omp_wrong_ordered_loop_count)
9902 << OrderedLoopCountExpr->getSourceRange();
9903 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9904 diag::note_collapse_loop_count)
9905 << CollapseLoopCountExpr->getSourceRange();
9906 }
9907 OrderedLoopCount = Result.getLimitedValue();
9908 } else {
9909 Built.clear(/*Size=*/1);
9910 return 1;
9911 }
9912 }
9913 // This is helper routine for loop directives (e.g., 'for', 'simd',
9914 // 'for simd', etc.).
9915 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9916 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9917 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9918 if (!OMPLoopBasedDirective::doForAllLoops(
9920 SupportsNonPerfectlyNested, NumLoops,
9921 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9922 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9923 &IterSpaces, &Captures,
9924 &CollapsedLoopVarDecls](unsigned Cnt, Stmt *CurStmt) {
9926 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9927 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9928 VarsWithImplicitDSA, IterSpaces, Captures,
9929 CollapsedLoopVarDecls))
9930 return true;
9931 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9932 IterSpaces[Cnt].CounterVar) {
9933 // Handle initialization of captured loop iterator variables.
9934 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9935 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9936 Captures[DRE] = DRE;
9937 }
9938 }
9939 return false;
9940 },
9941 [&SemaRef,
9942 &Captures](OMPCanonicalLoopNestTransformationDirective *Transform) {
9943 Stmt *DependentPreInits = Transform->getPreInits();
9944 if (!DependentPreInits)
9945 return;
9946
9947 // Search for pre-init declared variables that need to be captured
9948 // to be referenceable inside the directive.
9949 SmallVector<Stmt *> Constituents;
9950 appendFlattenedStmtList(Constituents, DependentPreInits);
9951 for (Stmt *S : Constituents) {
9952 if (auto *DC = dyn_cast<DeclStmt>(S)) {
9953 for (Decl *C : DC->decls()) {
9954 auto *D = cast<VarDecl>(C);
9956 SemaRef, D, D->getType().getNonReferenceType(),
9957 Transform->getBeginLoc());
9958 Captures[Ref] = Ref;
9959 }
9960 }
9961 }
9962 }))
9963 return 0;
9964
9965 Built.clear(/*size=*/NestedLoopCount);
9966
9967 if (SemaRef.CurContext->isDependentContext())
9968 return NestedLoopCount;
9969
9970 // An example of what is generated for the following code:
9971 //
9972 // #pragma omp simd collapse(2) ordered(2)
9973 // for (i = 0; i < NI; ++i)
9974 // for (k = 0; k < NK; ++k)
9975 // for (j = J0; j < NJ; j+=2) {
9976 // <loop body>
9977 // }
9978 //
9979 // We generate the code below.
9980 // Note: the loop body may be outlined in CodeGen.
9981 // Note: some counters may be C++ classes, operator- is used to find number of
9982 // iterations and operator+= to calculate counter value.
9983 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9984 // or i64 is currently supported).
9985 //
9986 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9987 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9988 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9989 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9990 // // similar updates for vars in clauses (e.g. 'linear')
9991 // <loop body (using local i and j)>
9992 // }
9993 // i = NI; // assign final values of counters
9994 // j = NJ;
9995 //
9996
9997 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9998 // the iteration counts of the collapsed for loops.
9999 // Precondition tests if there is at least one iteration (all conditions are
10000 // true).
10001 auto PreCond = ExprResult(IterSpaces[0].PreCond);
10002 Expr *N0 = IterSpaces[0].NumIterations;
10003 ExprResult LastIteration32 = widenIterationCount(
10004 /*Bits=*/32,
10005 SemaRef
10006 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
10008 /*AllowExplicit=*/true)
10009 .get(),
10010 SemaRef);
10011 ExprResult LastIteration64 = widenIterationCount(
10012 /*Bits=*/64,
10013 SemaRef
10014 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
10016 /*AllowExplicit=*/true)
10017 .get(),
10018 SemaRef);
10019
10020 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
10021 return NestedLoopCount;
10022
10023 ASTContext &C = SemaRef.Context;
10024 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
10025
10026 Scope *CurScope = DSA.getCurScope();
10027 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
10028 if (PreCond.isUsable()) {
10029 PreCond =
10030 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
10031 PreCond.get(), IterSpaces[Cnt].PreCond);
10032 }
10033 Expr *N = IterSpaces[Cnt].NumIterations;
10034 SourceLocation Loc = N->getExprLoc();
10035 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
10036 if (LastIteration32.isUsable())
10037 LastIteration32 = SemaRef.BuildBinOp(
10038 CurScope, Loc, BO_Mul, LastIteration32.get(),
10039 SemaRef
10042 /*AllowExplicit=*/true)
10043 .get());
10044 if (LastIteration64.isUsable())
10045 LastIteration64 = SemaRef.BuildBinOp(
10046 CurScope, Loc, BO_Mul, LastIteration64.get(),
10047 SemaRef
10050 /*AllowExplicit=*/true)
10051 .get());
10052 }
10053
10054 // Choose either the 32-bit or 64-bit version.
10055 ExprResult LastIteration = LastIteration64;
10056 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
10057 (LastIteration32.isUsable() &&
10058 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
10059 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
10060 fitsInto(
10061 /*Bits=*/32,
10062 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
10063 LastIteration64.get(), SemaRef))))
10064 LastIteration = LastIteration32;
10065 QualType VType = LastIteration.get()->getType();
10066 QualType RealVType = VType;
10067 QualType StrideVType = VType;
10068 if (isOpenMPTaskLoopDirective(DKind)) {
10069 VType =
10070 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
10071 StrideVType =
10072 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
10073 }
10074
10075 if (!LastIteration.isUsable())
10076 return 0;
10077
10078 // Save the number of iterations.
10079 ExprResult NumIterations = LastIteration;
10080 {
10081 LastIteration = SemaRef.BuildBinOp(
10082 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
10083 LastIteration.get(),
10084 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
10085 if (!LastIteration.isUsable())
10086 return 0;
10087 }
10088
10089 // Calculate the last iteration number beforehand instead of doing this on
10090 // each iteration. Do not do this if the number of iterations may be kfold-ed.
10091 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
10092 ExprResult CalcLastIteration;
10093 if (!IsConstant) {
10094 ExprResult SaveRef =
10095 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
10096 LastIteration = SaveRef;
10097
10098 // Prepare SaveRef + 1.
10099 NumIterations = SemaRef.BuildBinOp(
10100 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
10101 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
10102 if (!NumIterations.isUsable())
10103 return 0;
10104 }
10105
10106 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
10107
10108 // Build variables passed into runtime, necessary for worksharing directives.
10109 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
10114 // Lower bound variable, initialized with zero.
10115 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
10116 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
10117 SemaRef.AddInitializerToDecl(LBDecl,
10118 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10119 /*DirectInit=*/false);
10120
10121 // Upper bound variable, initialized with last iteration number.
10122 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
10123 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
10124 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
10125 /*DirectInit=*/false);
10126
10127 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
10128 // This will be used to implement clause 'lastprivate'.
10129 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
10130 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
10131 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
10132 SemaRef.AddInitializerToDecl(ILDecl,
10133 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10134 /*DirectInit=*/false);
10135
10136 // Stride variable returned by runtime (we initialize it to 1 by default).
10137 VarDecl *STDecl =
10138 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
10139 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
10140 SemaRef.AddInitializerToDecl(STDecl,
10141 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
10142 /*DirectInit=*/false);
10143
10144 // Build expression: UB = min(UB, LastIteration)
10145 // It is necessary for CodeGen of directives with static scheduling.
10146 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
10147 UB.get(), LastIteration.get());
10148 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10149 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
10150 LastIteration.get(), UB.get());
10151 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
10152 CondOp.get());
10153 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue=*/false);
10154
10155 // If we have a combined directive that combines 'distribute', 'for' or
10156 // 'simd' we need to be able to access the bounds of the schedule of the
10157 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
10158 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
10160 // Lower bound variable, initialized with zero.
10161 VarDecl *CombLBDecl =
10162 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
10163 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
10164 SemaRef.AddInitializerToDecl(
10165 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10166 /*DirectInit=*/false);
10167
10168 // Upper bound variable, initialized with last iteration number.
10169 VarDecl *CombUBDecl =
10170 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
10171 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
10172 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
10173 /*DirectInit=*/false);
10174
10175 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
10176 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
10177 ExprResult CombCondOp =
10178 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
10179 LastIteration.get(), CombUB.get());
10180 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
10181 CombCondOp.get());
10182 CombEUB =
10183 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue=*/false);
10184
10185 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
10186 // We expect to have at least 2 more parameters than the 'parallel'
10187 // directive does - the lower and upper bounds of the previous schedule.
10188 assert(CD->getNumParams() >= 4 &&
10189 "Unexpected number of parameters in loop combined directive");
10190
10191 // Set the proper type for the bounds given what we learned from the
10192 // enclosed loops.
10193 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
10194 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
10195
10196 // Previous lower and upper bounds are obtained from the region
10197 // parameters.
10198 PrevLB =
10199 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
10200 PrevUB =
10201 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
10202 }
10203 }
10204
10205 // Build the iteration variable and its initialization before loop.
10206 ExprResult IV;
10207 ExprResult Init, CombInit;
10208 {
10209 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
10210 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
10211 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
10216 ? LB.get()
10217 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10218 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
10219 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue=*/false);
10220
10222 Expr *CombRHS =
10227 ? CombLB.get()
10228 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10229 CombInit =
10230 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
10231 CombInit =
10232 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue=*/false);
10233 }
10234 }
10235
10236 bool UseStrictCompare =
10237 RealVType->hasUnsignedIntegerRepresentation() &&
10238 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
10239 return LIS.IsStrictCompare;
10240 });
10241 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10242 // unsigned IV)) for worksharing loops.
10243 SourceLocation CondLoc = AStmt->getBeginLoc();
10244 Expr *BoundUB = UB.get();
10245 if (UseStrictCompare) {
10246 BoundUB =
10247 SemaRef
10248 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10249 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10250 .get();
10251 BoundUB =
10252 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue=*/false).get();
10253 }
10259 ? SemaRef.BuildBinOp(CurScope, CondLoc,
10260 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
10261 BoundUB)
10262 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10263 NumIterations.get());
10264 ExprResult CombDistCond;
10266 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10267 NumIterations.get());
10268 }
10269
10270 ExprResult CombCond;
10272 Expr *BoundCombUB = CombUB.get();
10273 if (UseStrictCompare) {
10274 BoundCombUB =
10275 SemaRef
10276 .BuildBinOp(
10277 CurScope, CondLoc, BO_Add, BoundCombUB,
10278 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10279 .get();
10280 BoundCombUB =
10281 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue=*/false)
10282 .get();
10283 }
10284 CombCond =
10285 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10286 IV.get(), BoundCombUB);
10287 }
10288 // Loop increment (IV = IV + 1)
10289 SourceLocation IncLoc = AStmt->getBeginLoc();
10290 ExprResult Inc =
10291 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
10292 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
10293 if (!Inc.isUsable())
10294 return 0;
10295 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
10296 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue=*/false);
10297 if (!Inc.isUsable())
10298 return 0;
10299
10300 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10301 // Used for directives with static scheduling.
10302 // In combined construct, add combined version that use CombLB and CombUB
10303 // base variables for the update
10304 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10309 // LB + ST
10310 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
10311 if (!NextLB.isUsable())
10312 return 0;
10313 // LB = LB + ST
10314 NextLB =
10315 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
10316 NextLB =
10317 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue=*/false);
10318 if (!NextLB.isUsable())
10319 return 0;
10320 // UB + ST
10321 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
10322 if (!NextUB.isUsable())
10323 return 0;
10324 // UB = UB + ST
10325 NextUB =
10326 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
10327 NextUB =
10328 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue=*/false);
10329 if (!NextUB.isUsable())
10330 return 0;
10332 CombNextLB =
10333 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
10334 if (!NextLB.isUsable())
10335 return 0;
10336 // LB = LB + ST
10337 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
10338 CombNextLB.get());
10339 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
10340 /*DiscardedValue=*/false);
10341 if (!CombNextLB.isUsable())
10342 return 0;
10343 // UB + ST
10344 CombNextUB =
10345 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
10346 if (!CombNextUB.isUsable())
10347 return 0;
10348 // UB = UB + ST
10349 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
10350 CombNextUB.get());
10351 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
10352 /*DiscardedValue=*/false);
10353 if (!CombNextUB.isUsable())
10354 return 0;
10355 }
10356 }
10357
10358 // Create increment expression for distribute loop when combined in a same
10359 // directive with for as IV = IV + ST; ensure upper bound expression based
10360 // on PrevUB instead of NumIterations - used to implement 'for' when found
10361 // in combination with 'distribute', like in 'distribute parallel for'
10362 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10363 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10365 DistCond = SemaRef.BuildBinOp(
10366 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10367 assert(DistCond.isUsable() && "distribute cond expr was not built");
10368
10369 DistInc =
10370 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10371 assert(DistInc.isUsable() && "distribute inc expr was not built");
10372 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10373 DistInc.get());
10374 DistInc =
10375 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue=*/false);
10376 assert(DistInc.isUsable() && "distribute inc expr was not built");
10377
10378 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10379 // construct
10380 ExprResult NewPrevUB = PrevUB;
10381 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10382 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10383 PrevUB.get()->getType())) {
10384 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10385 DistEUBLoc,
10387 DistEUBLoc, NewPrevUB.get());
10388 if (!NewPrevUB.isUsable())
10389 return 0;
10390 }
10391 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10392 UB.get(), NewPrevUB.get());
10393 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10394 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10395 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10396 CondOp.get());
10397 PrevEUB =
10398 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue=*/false);
10399
10400 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10401 // parallel for is in combination with a distribute directive with
10402 // schedule(static, 1)
10403 Expr *BoundPrevUB = PrevUB.get();
10404 if (UseStrictCompare) {
10405 BoundPrevUB =
10406 SemaRef
10407 .BuildBinOp(
10408 CurScope, CondLoc, BO_Add, BoundPrevUB,
10409 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10410 .get();
10411 BoundPrevUB =
10412 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue=*/false)
10413 .get();
10414 }
10415 ParForInDistCond =
10416 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10417 IV.get(), BoundPrevUB);
10418 }
10419
10420 // Build updates and final values of the loop counters.
10421 bool HasErrors = false;
10422 Built.Counters.resize(NestedLoopCount);
10423 Built.Inits.resize(NestedLoopCount);
10424 Built.Updates.resize(NestedLoopCount);
10425 Built.Finals.resize(NestedLoopCount);
10426 Built.DependentCounters.resize(NestedLoopCount);
10427 Built.DependentInits.resize(NestedLoopCount);
10428 Built.FinalsConditions.resize(NestedLoopCount);
10429 {
10430 // We implement the following algorithm for obtaining the
10431 // original loop iteration variable values based on the
10432 // value of the collapsed loop iteration variable IV.
10433 //
10434 // Let n+1 be the number of collapsed loops in the nest.
10435 // Iteration variables (I0, I1, .... In)
10436 // Iteration counts (N0, N1, ... Nn)
10437 //
10438 // Acc = IV;
10439 //
10440 // To compute Ik for loop k, 0 <= k <= n, generate:
10441 // Prod = N(k+1) * N(k+2) * ... * Nn;
10442 // Ik = Acc / Prod;
10443 // Acc -= Ik * Prod;
10444 //
10445 ExprResult Acc = IV;
10446 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10447 LoopIterationSpace &IS = IterSpaces[Cnt];
10448 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10449 ExprResult Iter;
10450
10451 // Compute prod
10452 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10453 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10454 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10455 IterSpaces[K].NumIterations);
10456
10457 // Iter = Acc / Prod
10458 // If there is at least one more inner loop to avoid
10459 // multiplication by 1.
10460 if (Cnt + 1 < NestedLoopCount)
10461 Iter =
10462 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10463 else
10464 Iter = Acc;
10465 if (!Iter.isUsable()) {
10466 HasErrors = true;
10467 break;
10468 }
10469
10470 // Update Acc:
10471 // Acc -= Iter * Prod
10472 // Check if there is at least one more inner loop to avoid
10473 // multiplication by 1.
10474 if (Cnt + 1 < NestedLoopCount)
10475 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10476 Prod.get());
10477 else
10478 Prod = Iter;
10479 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10480
10481 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10482 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10483 DeclRefExpr *CounterVar = buildDeclRefExpr(
10484 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10485 /*RefersToCapture=*/true);
10487 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10488 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10489 if (!Init.isUsable()) {
10490 HasErrors = true;
10491 break;
10492 }
10494 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10495 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10496 if (!Update.isUsable()) {
10497 HasErrors = true;
10498 break;
10499 }
10500
10501 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10502 ExprResult Final =
10503 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10504 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10505 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10506 if (!Final.isUsable()) {
10507 HasErrors = true;
10508 break;
10509 }
10510
10511 if (!Update.isUsable() || !Final.isUsable()) {
10512 HasErrors = true;
10513 break;
10514 }
10515 // Save results
10516 Built.Counters[Cnt] = IS.CounterVar;
10517 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10518 Built.Inits[Cnt] = Init.get();
10519 Built.Updates[Cnt] = Update.get();
10520 Built.Finals[Cnt] = Final.get();
10521 Built.DependentCounters[Cnt] = nullptr;
10522 Built.DependentInits[Cnt] = nullptr;
10523 Built.FinalsConditions[Cnt] = nullptr;
10524 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10525 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10526 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10527 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10528 }
10529 }
10530 }
10531
10532 if (HasErrors)
10533 return 0;
10534
10535 // Save results
10536 Built.IterationVarRef = IV.get();
10537 Built.LastIteration = LastIteration.get();
10538 Built.NumIterations = NumIterations.get();
10539 Built.CalcLastIteration = SemaRef
10540 .ActOnFinishFullExpr(CalcLastIteration.get(),
10541 /*DiscardedValue=*/false)
10542 .get();
10543 Built.PreCond = PreCond.get();
10544 Built.PreInits = buildPreInits(C, Captures);
10545 Built.Cond = Cond.get();
10546 Built.Init = Init.get();
10547 Built.Inc = Inc.get();
10548 Built.LB = LB.get();
10549 Built.UB = UB.get();
10550 Built.IL = IL.get();
10551 Built.ST = ST.get();
10552 Built.EUB = EUB.get();
10553 Built.NLB = NextLB.get();
10554 Built.NUB = NextUB.get();
10555 Built.PrevLB = PrevLB.get();
10556 Built.PrevUB = PrevUB.get();
10557 Built.DistInc = DistInc.get();
10558 Built.PrevEUB = PrevEUB.get();
10559 Built.DistCombinedFields.LB = CombLB.get();
10560 Built.DistCombinedFields.UB = CombUB.get();
10561 Built.DistCombinedFields.EUB = CombEUB.get();
10562 Built.DistCombinedFields.Init = CombInit.get();
10563 Built.DistCombinedFields.Cond = CombCond.get();
10564 Built.DistCombinedFields.NLB = CombNextLB.get();
10565 Built.DistCombinedFields.NUB = CombNextUB.get();
10566 Built.DistCombinedFields.DistCond = CombDistCond.get();
10567 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10568
10569 return NestedLoopCount;
10570}
10571
10573 auto CollapseClauses =
10574 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10575 if (CollapseClauses.begin() != CollapseClauses.end())
10576 return (*CollapseClauses.begin())->getNumForLoops();
10577 return nullptr;
10578}
10579
10581 auto OrderedClauses =
10582 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10583 if (OrderedClauses.begin() != OrderedClauses.end())
10584 return (*OrderedClauses.begin())->getNumForLoops();
10585 return nullptr;
10586}
10587
10589 const ArrayRef<OMPClause *> Clauses) {
10590 const OMPSafelenClause *Safelen = nullptr;
10591 const OMPSimdlenClause *Simdlen = nullptr;
10592
10593 for (const OMPClause *Clause : Clauses) {
10594 if (Clause->getClauseKind() == OMPC_safelen)
10595 Safelen = cast<OMPSafelenClause>(Clause);
10596 else if (Clause->getClauseKind() == OMPC_simdlen)
10597 Simdlen = cast<OMPSimdlenClause>(Clause);
10598 if (Safelen && Simdlen)
10599 break;
10600 }
10601
10602 if (Simdlen && Safelen) {
10603 const Expr *SimdlenLength = Simdlen->getSimdlen();
10604 const Expr *SafelenLength = Safelen->getSafelen();
10605 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10606 SimdlenLength->isInstantiationDependent() ||
10607 SimdlenLength->containsUnexpandedParameterPack())
10608 return false;
10609 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10610 SafelenLength->isInstantiationDependent() ||
10611 SafelenLength->containsUnexpandedParameterPack())
10612 return false;
10613 Expr::EvalResult SimdlenResult, SafelenResult;
10614 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10615 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10616 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10617 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10618 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10619 // If both simdlen and safelen clauses are specified, the value of the
10620 // simdlen parameter must be less than or equal to the value of the safelen
10621 // parameter.
10622 if (SimdlenRes > SafelenRes) {
10623 S.Diag(SimdlenLength->getExprLoc(),
10624 diag::err_omp_wrong_simdlen_safelen_values)
10625 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10626 return true;
10627 }
10628 }
10629 return false;
10630}
10631
10633 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10634 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10635 if (!AStmt)
10636 return StmtError();
10637
10638 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_simd, AStmt);
10639
10640 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10641 OMPLoopBasedDirective::HelperExprs B;
10642 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10643 // define the nested loops number.
10644 unsigned NestedLoopCount = checkOpenMPLoop(
10645 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10646 CS, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10647 if (NestedLoopCount == 0)
10648 return StmtError();
10649
10650 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10651 return StmtError();
10652
10654 return StmtError();
10655
10656 auto *SimdDirective = OMPSimdDirective::Create(
10657 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10658 return SimdDirective;
10659}
10660
10662 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10663 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10664 if (!AStmt)
10665 return StmtError();
10666
10667 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10668 OMPLoopBasedDirective::HelperExprs B;
10669 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10670 // define the nested loops number.
10671 unsigned NestedLoopCount = checkOpenMPLoop(
10672 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10673 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10674 if (NestedLoopCount == 0)
10675 return StmtError();
10676
10677 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10678 return StmtError();
10679
10680 auto *ForDirective = OMPForDirective::Create(
10681 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10682 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10683 return ForDirective;
10684}
10685
10687 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10688 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10689 if (!AStmt)
10690 return StmtError();
10691
10692 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_for_simd, AStmt);
10693
10694 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10695 OMPLoopBasedDirective::HelperExprs B;
10696 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10697 // define the nested loops number.
10698 unsigned NestedLoopCount =
10699 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10700 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10701 VarsWithImplicitDSA, B);
10702 if (NestedLoopCount == 0)
10703 return StmtError();
10704
10705 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10706 return StmtError();
10707
10709 return StmtError();
10710
10711 return OMPForSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
10712 NestedLoopCount, Clauses, AStmt, B);
10713}
10714
10716 Stmt *AStmt, DSAStackTy *Stack) {
10717 if (!AStmt)
10718 return true;
10719
10720 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10721 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
10722 auto BaseStmt = AStmt;
10723 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10724 BaseStmt = CS->getCapturedStmt();
10725 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10726 auto S = C->children();
10727 if (S.begin() == S.end())
10728 return true;
10729 // All associated statements must be '#pragma omp section' except for
10730 // the first one.
10731 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10732 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10733 if (SectionStmt)
10734 SemaRef.Diag(SectionStmt->getBeginLoc(),
10735 diag::err_omp_sections_substmt_not_section)
10736 << getOpenMPDirectiveName(DKind, OMPVersion);
10737 return true;
10738 }
10739 cast<OMPSectionDirective>(SectionStmt)
10740 ->setHasCancel(Stack->isCancelRegion());
10741 }
10742 } else {
10743 SemaRef.Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10744 << getOpenMPDirectiveName(DKind, OMPVersion);
10745 return true;
10746 }
10747 return false;
10748}
10749
10752 Stmt *AStmt, SourceLocation StartLoc,
10753 SourceLocation EndLoc) {
10754 if (checkSectionsDirective(SemaRef, OMPD_sections, AStmt, DSAStack))
10755 return StmtError();
10756
10757 SemaRef.setFunctionHasBranchProtectedScope();
10758
10759 return OMPSectionsDirective::Create(
10760 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10761 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10762}
10763
10765 SourceLocation StartLoc,
10766 SourceLocation EndLoc) {
10767 if (!AStmt)
10768 return StmtError();
10769
10770 SemaRef.setFunctionHasBranchProtectedScope();
10771 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10772
10773 return OMPSectionDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt,
10774 DSAStack->isCancelRegion());
10775}
10776
10778 E = E->IgnoreParenCasts()->IgnoreImplicit();
10779 if (auto *CE = dyn_cast<CallExpr>(E))
10780 if (CE->getDirectCallee())
10781 return E;
10782 return nullptr;
10783}
10784
10787 Stmt *AStmt, SourceLocation StartLoc,
10788 SourceLocation EndLoc) {
10789 if (!AStmt)
10790 return StmtError();
10791
10792 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10793
10794 // 5.1 OpenMP
10795 // expression-stmt : an expression statement with one of the following forms:
10796 // expression = target-call ( [expression-list] );
10797 // target-call ( [expression-list] );
10798
10799 SourceLocation TargetCallLoc;
10800
10801 if (!SemaRef.CurContext->isDependentContext()) {
10802 Expr *TargetCall = nullptr;
10803
10804 auto *E = dyn_cast<Expr>(S);
10805 if (!E) {
10806 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10807 return StmtError();
10808 }
10809
10810 E = E->IgnoreParenCasts()->IgnoreImplicit();
10811
10812 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10813 if (BO->getOpcode() == BO_Assign)
10814 TargetCall = getDirectCallExpr(BO->getRHS());
10815 } else {
10816 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10817 if (COCE->getOperator() == OO_Equal)
10818 TargetCall = getDirectCallExpr(COCE->getArg(1));
10819 if (!TargetCall)
10820 TargetCall = getDirectCallExpr(E);
10821 }
10822 if (!TargetCall) {
10823 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10824 return StmtError();
10825 }
10826 TargetCallLoc = TargetCall->getExprLoc();
10827 }
10828
10829 SemaRef.setFunctionHasBranchProtectedScope();
10830
10831 return OMPDispatchDirective::Create(getASTContext(), StartLoc, EndLoc,
10832 Clauses, AStmt, TargetCallLoc);
10833}
10834
10837 DSAStackTy *Stack) {
10838 bool ErrorFound = false;
10839 for (OMPClause *C : Clauses) {
10840 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10841 for (Expr *RefExpr : LPC->varlist()) {
10842 SourceLocation ELoc;
10843 SourceRange ERange;
10844 Expr *SimpleRefExpr = RefExpr;
10845 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10846 if (ValueDecl *D = Res.first) {
10847 auto &&Info = Stack->isLoopControlVariable(D);
10848 if (!Info.first) {
10849 unsigned OMPVersion = S.getLangOpts().OpenMP;
10850 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10851 << getOpenMPDirectiveName(K, OMPVersion);
10852 ErrorFound = true;
10853 }
10854 }
10855 }
10856 }
10857 }
10858 return ErrorFound;
10859}
10860
10862 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10863 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10864 if (!AStmt)
10865 return StmtError();
10866
10867 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10868 // A list item may not appear in a lastprivate clause unless it is the
10869 // loop iteration variable of a loop that is associated with the construct.
10870 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack))
10871 return StmtError();
10872
10873 setBranchProtectedScope(SemaRef, OMPD_loop, AStmt);
10874
10875 OMPLoopDirective::HelperExprs B;
10876 // In presence of clause 'collapse', it will define the nested loops number.
10877 unsigned NestedLoopCount = checkOpenMPLoop(
10878 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10879 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10880 if (NestedLoopCount == 0)
10881 return StmtError();
10882
10883 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10884 "omp loop exprs were not built");
10885
10886 return OMPGenericLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
10887 NestedLoopCount, Clauses, AStmt, B);
10888}
10889
10891 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10892 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10893 if (!AStmt)
10894 return StmtError();
10895
10896 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10897 // A list item may not appear in a lastprivate clause unless it is the
10898 // loop iteration variable of a loop that is associated with the construct.
10899 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack))
10900 return StmtError();
10901
10902 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_teams_loop, AStmt);
10903
10904 OMPLoopDirective::HelperExprs B;
10905 // In presence of clause 'collapse', it will define the nested loops number.
10906 unsigned NestedLoopCount =
10907 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10908 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10909 VarsWithImplicitDSA, B);
10910 if (NestedLoopCount == 0)
10911 return StmtError();
10912
10913 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10914 "omp loop exprs were not built");
10915
10916 DSAStack->setParentTeamsRegionLoc(StartLoc);
10917
10919 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10920}
10921
10923 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10924 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10925 if (!AStmt)
10926 return StmtError();
10927
10928 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10929 // A list item may not appear in a lastprivate clause unless it is the
10930 // loop iteration variable of a loop that is associated with the construct.
10931 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop,
10932 DSAStack))
10933 return StmtError();
10934
10935 CapturedStmt *CS =
10936 setBranchProtectedScope(SemaRef, OMPD_target_teams_loop, AStmt);
10937
10938 OMPLoopDirective::HelperExprs B;
10939 // In presence of clause 'collapse', it will define the nested loops number.
10940 unsigned NestedLoopCount =
10941 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10942 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10943 VarsWithImplicitDSA, B);
10944 if (NestedLoopCount == 0)
10945 return StmtError();
10946
10947 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10948 "omp loop exprs were not built");
10949
10951 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10953}
10954
10956 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10957 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10958 if (!AStmt)
10959 return StmtError();
10960
10961 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10962 // A list item may not appear in a lastprivate clause unless it is the
10963 // loop iteration variable of a loop that is associated with the construct.
10964 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_parallel_loop,
10965 DSAStack))
10966 return StmtError();
10967
10968 CapturedStmt *CS =
10969 setBranchProtectedScope(SemaRef, OMPD_parallel_loop, AStmt);
10970
10971 OMPLoopDirective::HelperExprs B;
10972 // In presence of clause 'collapse', it will define the nested loops number.
10973 unsigned NestedLoopCount =
10974 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
10975 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10976 VarsWithImplicitDSA, B);
10977 if (NestedLoopCount == 0)
10978 return StmtError();
10979
10980 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10981 "omp loop exprs were not built");
10982
10984 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10985}
10986
10988 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10989 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10990 if (!AStmt)
10991 return StmtError();
10992
10993 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10994 // A list item may not appear in a lastprivate clause unless it is the
10995 // loop iteration variable of a loop that is associated with the construct.
10996 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_parallel_loop,
10997 DSAStack))
10998 return StmtError();
10999
11000 CapturedStmt *CS =
11001 setBranchProtectedScope(SemaRef, OMPD_target_parallel_loop, AStmt);
11002
11003 OMPLoopDirective::HelperExprs B;
11004 // In presence of clause 'collapse', it will define the nested loops number.
11005 unsigned NestedLoopCount =
11006 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
11007 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
11008 VarsWithImplicitDSA, B);
11009 if (NestedLoopCount == 0)
11010 return StmtError();
11011
11012 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11013 "omp loop exprs were not built");
11014
11016 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11017}
11018
11020 Stmt *AStmt,
11021 SourceLocation StartLoc,
11022 SourceLocation EndLoc) {
11023 if (!AStmt)
11024 return StmtError();
11025
11026 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11027
11028 SemaRef.setFunctionHasBranchProtectedScope();
11029
11030 // OpenMP [2.7.3, single Construct, Restrictions]
11031 // The copyprivate clause must not be used with the nowait clause.
11032 const OMPClause *Nowait = nullptr;
11033 const OMPClause *Copyprivate = nullptr;
11034 for (const OMPClause *Clause : Clauses) {
11035 if (Clause->getClauseKind() == OMPC_nowait)
11036 Nowait = Clause;
11037 else if (Clause->getClauseKind() == OMPC_copyprivate)
11038 Copyprivate = Clause;
11039 if (Copyprivate && Nowait) {
11040 Diag(Copyprivate->getBeginLoc(),
11041 diag::err_omp_single_copyprivate_with_nowait);
11042 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
11043 return StmtError();
11044 }
11045 }
11046
11047 return OMPSingleDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11048 AStmt);
11049}
11050
11052 SourceLocation StartLoc,
11053 SourceLocation EndLoc) {
11054 if (!AStmt)
11055 return StmtError();
11056
11057 SemaRef.setFunctionHasBranchProtectedScope();
11058
11059 return OMPMasterDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt);
11060}
11061
11063 Stmt *AStmt,
11064 SourceLocation StartLoc,
11065 SourceLocation EndLoc) {
11066 if (!AStmt)
11067 return StmtError();
11068
11069 SemaRef.setFunctionHasBranchProtectedScope();
11070
11071 return OMPMaskedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11072 AStmt);
11073}
11074
11076 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
11077 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
11078 if (!AStmt)
11079 return StmtError();
11080
11081 bool ErrorFound = false;
11082 llvm::APSInt Hint;
11083 SourceLocation HintLoc;
11084 bool DependentHint = false;
11085 for (const OMPClause *C : Clauses) {
11086 if (C->getClauseKind() == OMPC_hint) {
11087 if (!DirName.getName()) {
11088 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
11089 ErrorFound = true;
11090 }
11091 Expr *E = cast<OMPHintClause>(C)->getHint();
11092 if (E->isTypeDependent() || E->isValueDependent() ||
11094 DependentHint = true;
11095 } else {
11097 HintLoc = C->getBeginLoc();
11098 }
11099 }
11100 }
11101 if (ErrorFound)
11102 return StmtError();
11103 const auto Pair = DSAStack->getCriticalWithHint(DirName);
11104 if (Pair.first && DirName.getName() && !DependentHint) {
11105 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
11106 Diag(StartLoc, diag::err_omp_critical_with_hint);
11107 if (HintLoc.isValid())
11108 Diag(HintLoc, diag::note_omp_critical_hint_here)
11109 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
11110 else
11111 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
11112 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
11113 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
11114 << 1
11115 << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()),
11116 /*Radix=*/10, /*Signed=*/false);
11117 } else {
11118 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
11119 }
11120 }
11121 }
11122
11123 SemaRef.setFunctionHasBranchProtectedScope();
11124
11125 auto *Dir = OMPCriticalDirective::Create(getASTContext(), DirName, StartLoc,
11126 EndLoc, Clauses, AStmt);
11127 if (!Pair.first && DirName.getName() && !DependentHint)
11128 DSAStack->addCriticalWithHint(Dir, Hint);
11129 return Dir;
11130}
11131
11133 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11134 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11135 if (!AStmt)
11136 return StmtError();
11137
11138 setBranchProtectedScope(SemaRef, OMPD_parallel_for, AStmt);
11139
11140 OMPLoopBasedDirective::HelperExprs B;
11141 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11142 // define the nested loops number.
11143 unsigned NestedLoopCount =
11144 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
11145 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
11146 VarsWithImplicitDSA, B);
11147 if (NestedLoopCount == 0)
11148 return StmtError();
11149
11150 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11151 return StmtError();
11152
11153 return OMPParallelForDirective::Create(
11154 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11155 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11156}
11157
11159 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11160 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11161 if (!AStmt)
11162 return StmtError();
11163
11164 CapturedStmt *CS =
11165 setBranchProtectedScope(SemaRef, OMPD_parallel_for_simd, AStmt);
11166
11167 OMPLoopBasedDirective::HelperExprs B;
11168 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11169 // define the nested loops number.
11170 unsigned NestedLoopCount =
11171 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
11172 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
11173 VarsWithImplicitDSA, B);
11174 if (NestedLoopCount == 0)
11175 return StmtError();
11176
11177 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11178 return StmtError();
11179
11181 return StmtError();
11182
11183 return OMPParallelForSimdDirective::Create(
11184 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11185}
11186
11188 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11189 SourceLocation EndLoc) {
11190 if (!AStmt)
11191 return StmtError();
11192
11193 setBranchProtectedScope(SemaRef, OMPD_parallel_master, AStmt);
11194
11195 return OMPParallelMasterDirective::Create(
11196 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11197 DSAStack->getTaskgroupReductionRef());
11198}
11199
11201 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11202 SourceLocation EndLoc) {
11203 if (!AStmt)
11204 return StmtError();
11205
11206 setBranchProtectedScope(SemaRef, OMPD_parallel_masked, AStmt);
11207
11208 return OMPParallelMaskedDirective::Create(
11209 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11210 DSAStack->getTaskgroupReductionRef());
11211}
11212
11214 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11215 SourceLocation EndLoc) {
11216 if (checkSectionsDirective(SemaRef, OMPD_parallel_sections, AStmt, DSAStack))
11217 return StmtError();
11218
11219 SemaRef.setFunctionHasBranchProtectedScope();
11220
11221 return OMPParallelSectionsDirective::Create(
11222 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11223 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11224}
11225
11226/// Find and diagnose mutually exclusive clause kinds.
11228 Sema &S, ArrayRef<OMPClause *> Clauses,
11229 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11230 const OMPClause *PrevClause = nullptr;
11231 bool ErrorFound = false;
11232 for (const OMPClause *C : Clauses) {
11233 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
11234 if (!PrevClause) {
11235 PrevClause = C;
11236 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11237 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11238 << getOpenMPClauseNameForDiag(C->getClauseKind())
11239 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11240 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
11241 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11242 ErrorFound = true;
11243 }
11244 }
11245 }
11246 return ErrorFound;
11247}
11248
11250 Stmt *AStmt,
11251 SourceLocation StartLoc,
11252 SourceLocation EndLoc) {
11253 if (!AStmt)
11254 return StmtError();
11255
11256 // OpenMP 5.0, 2.10.1 task Construct
11257 // If a detach clause appears on the directive, then a mergeable clause cannot
11258 // appear on the same directive.
11260 {OMPC_detach, OMPC_mergeable}))
11261 return StmtError();
11262
11263 setBranchProtectedScope(SemaRef, OMPD_task, AStmt);
11264
11265 return OMPTaskDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11266 AStmt, DSAStack->isCancelRegion());
11267}
11268
11270 SourceLocation EndLoc) {
11271 return OMPTaskyieldDirective::Create(getASTContext(), StartLoc, EndLoc);
11272}
11273
11275 SourceLocation EndLoc) {
11276 return OMPBarrierDirective::Create(getASTContext(), StartLoc, EndLoc);
11277}
11278
11280 SourceLocation StartLoc,
11281 SourceLocation EndLoc,
11282 bool InExContext) {
11283 const OMPAtClause *AtC =
11284 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11285
11286 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11287 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11288 return StmtError();
11289 }
11290
11291 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11292 const OMPSeverityClause *SeverityC =
11293 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11294 const OMPMessageClause *MessageC =
11295 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11296 std::optional<std::string> SL =
11297 MessageC ? MessageC->tryEvaluateString(getASTContext()) : std::nullopt;
11298
11299 if (MessageC && !SL)
11300 Diag(MessageC->getMessageString()->getBeginLoc(),
11301 diag::warn_clause_expected_string)
11302 << getOpenMPClauseNameForDiag(OMPC_message) << 1;
11303 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11304 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11305 << SL.value_or("WARNING");
11306 else
11307 Diag(StartLoc, diag::err_diagnose_if_succeeded) << SL.value_or("ERROR");
11308 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11309 return StmtError();
11310 }
11311
11312 return OMPErrorDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11313}
11314
11317 SourceLocation StartLoc,
11318 SourceLocation EndLoc) {
11319 const OMPNowaitClause *NowaitC =
11320 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11321 bool HasDependC =
11322 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11323 .empty();
11324 if (NowaitC && !HasDependC) {
11325 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11326 return StmtError();
11327 }
11328
11329 return OMPTaskwaitDirective::Create(getASTContext(), StartLoc, EndLoc,
11330 Clauses);
11331}
11332
11335 Stmt *AStmt, SourceLocation StartLoc,
11336 SourceLocation EndLoc) {
11337 if (!AStmt)
11338 return StmtError();
11339
11340 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11341
11342 SemaRef.setFunctionHasBranchProtectedScope();
11343
11344 return OMPTaskgroupDirective::Create(getASTContext(), StartLoc, EndLoc,
11345 Clauses, AStmt,
11346 DSAStack->getTaskgroupReductionRef());
11347}
11348
11350 SourceLocation StartLoc,
11351 SourceLocation EndLoc) {
11352 OMPFlushClause *FC = nullptr;
11353 OMPClause *OrderClause = nullptr;
11354 for (OMPClause *C : Clauses) {
11355 if (C->getClauseKind() == OMPC_flush)
11356 FC = cast<OMPFlushClause>(C);
11357 else
11358 OrderClause = C;
11359 }
11360 unsigned OMPVersion = getLangOpts().OpenMP;
11361 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11362 SourceLocation MemOrderLoc;
11363 for (const OMPClause *C : Clauses) {
11364 if (C->getClauseKind() == OMPC_acq_rel ||
11365 C->getClauseKind() == OMPC_acquire ||
11366 C->getClauseKind() == OMPC_release ||
11367 C->getClauseKind() == OMPC_seq_cst /*OpenMP 5.1*/) {
11368 if (MemOrderKind != OMPC_unknown) {
11369 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11370 << getOpenMPDirectiveName(OMPD_flush, OMPVersion) << 1
11371 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11372 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11373 << getOpenMPClauseNameForDiag(MemOrderKind);
11374 } else {
11375 MemOrderKind = C->getClauseKind();
11376 MemOrderLoc = C->getBeginLoc();
11377 }
11378 }
11379 }
11380 if (FC && OrderClause) {
11381 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11382 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11383 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11384 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11385 return StmtError();
11386 }
11387 return OMPFlushDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11388}
11389
11391 SourceLocation StartLoc,
11392 SourceLocation EndLoc) {
11393 if (Clauses.empty()) {
11394 Diag(StartLoc, diag::err_omp_depobj_expected);
11395 return StmtError();
11396 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11397 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11398 return StmtError();
11399 }
11400 // Only depobj expression and another single clause is allowed.
11401 if (Clauses.size() > 2) {
11402 Diag(Clauses[2]->getBeginLoc(),
11403 diag::err_omp_depobj_single_clause_expected);
11404 return StmtError();
11405 } else if (Clauses.size() < 1) {
11406 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11407 return StmtError();
11408 }
11409 return OMPDepobjDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11410}
11411
11413 SourceLocation StartLoc,
11414 SourceLocation EndLoc) {
11415 // Check that exactly one clause is specified.
11416 if (Clauses.size() != 1) {
11417 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11418 diag::err_omp_scan_single_clause_expected);
11419 return StmtError();
11420 }
11421 // Check that scan directive is used in the scope of the OpenMP loop body.
11422 if (Scope *S = DSAStack->getCurScope()) {
11423 Scope *ParentS = S->getParent();
11424 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11425 !ParentS->getBreakParent()->isOpenMPLoopScope()) {
11426 unsigned OMPVersion = getLangOpts().OpenMP;
11427 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11428 << getOpenMPDirectiveName(OMPD_scan, OMPVersion) << 5);
11429 }
11430 }
11431 // Check that only one instance of scan directives is used in the same outer
11432 // region.
11433 if (DSAStack->doesParentHasScanDirective()) {
11434 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11435 Diag(DSAStack->getParentScanDirectiveLoc(),
11436 diag::note_omp_previous_directive)
11437 << "scan";
11438 return StmtError();
11439 }
11440 DSAStack->setParentHasScanDirective(StartLoc);
11441 return OMPScanDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11442}
11443
11446 Stmt *AStmt, SourceLocation StartLoc,
11447 SourceLocation EndLoc) {
11448 const OMPClause *DependFound = nullptr;
11449 const OMPClause *DependSourceClause = nullptr;
11450 const OMPClause *DependSinkClause = nullptr;
11451 const OMPClause *DoacrossFound = nullptr;
11452 const OMPClause *DoacrossSourceClause = nullptr;
11453 const OMPClause *DoacrossSinkClause = nullptr;
11454 bool ErrorFound = false;
11455 const OMPThreadsClause *TC = nullptr;
11456 const OMPSIMDClause *SC = nullptr;
11457 for (const OMPClause *C : Clauses) {
11458 auto DOC = dyn_cast<OMPDoacrossClause>(C);
11459 auto DC = dyn_cast<OMPDependClause>(C);
11460 if (DC || DOC) {
11461 DependFound = DC ? C : nullptr;
11462 DoacrossFound = DOC ? C : nullptr;
11463 OMPDoacrossKind ODK;
11464 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11465 (DOC && (ODK.isSource(DOC)))) {
11466 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11467 unsigned OMPVersion = getLangOpts().OpenMP;
11468 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11469 << getOpenMPDirectiveName(OMPD_ordered, OMPVersion)
11470 << getOpenMPClauseNameForDiag(DC ? OMPC_depend : OMPC_doacross)
11471 << 2;
11472 ErrorFound = true;
11473 } else {
11474 if (DC)
11475 DependSourceClause = C;
11476 else
11477 DoacrossSourceClause = C;
11478 }
11479 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11480 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11481 << (DC ? "depend" : "doacross") << 0;
11482 ErrorFound = true;
11483 }
11484 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11485 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11486 if (DependSourceClause || DoacrossSourceClause) {
11487 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11488 << (DC ? "depend" : "doacross") << 1;
11489 ErrorFound = true;
11490 }
11491 if (DC)
11492 DependSinkClause = C;
11493 else
11494 DoacrossSinkClause = C;
11495 }
11496 } else if (C->getClauseKind() == OMPC_threads) {
11498 } else if (C->getClauseKind() == OMPC_simd) {
11499 SC = cast<OMPSIMDClause>(C);
11500 }
11501 }
11502 if (!ErrorFound && !SC &&
11503 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11504 // OpenMP [2.8.1,simd Construct, Restrictions]
11505 // An ordered construct with the simd clause is the only OpenMP construct
11506 // that can appear in the simd region.
11507 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11508 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11509 ErrorFound = true;
11510 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11511 SourceLocation Loc =
11512 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11513 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11514 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend : OMPC_doacross)
11516 : SC->getClauseKind());
11517 ErrorFound = true;
11518 } else if ((DependFound || DoacrossFound) &&
11519 !DSAStack->getParentOrderedRegionParam().first) {
11520 SourceLocation Loc =
11521 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11522 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11523 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend
11524 : OMPC_doacross);
11525 ErrorFound = true;
11526 } else if (TC || Clauses.empty()) {
11527 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11528 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11529 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11530 << (TC != nullptr);
11531 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11532 ErrorFound = true;
11533 }
11534 }
11535 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11536 return StmtError();
11537
11538 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11539 // During execution of an iteration of a worksharing-loop or a loop nest
11540 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11541 // must not execute more than one ordered region corresponding to an ordered
11542 // construct without a depend clause.
11543 if (!DependFound && !DoacrossFound) {
11544 if (DSAStack->doesParentHasOrderedDirective()) {
11545 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11546 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11547 diag::note_omp_previous_directive)
11548 << "ordered";
11549 return StmtError();
11550 }
11551 DSAStack->setParentHasOrderedDirective(StartLoc);
11552 }
11553
11554 if (AStmt) {
11555 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11556
11557 SemaRef.setFunctionHasBranchProtectedScope();
11558 }
11559
11560 return OMPOrderedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11561 AStmt);
11562}
11563
11564namespace {
11565/// Helper class for checking expression in 'omp atomic [update]'
11566/// construct.
11567class OpenMPAtomicUpdateChecker {
11568 /// Error results for atomic update expressions.
11569 enum ExprAnalysisErrorCode {
11570 /// A statement is not an expression statement.
11571 NotAnExpression,
11572 /// Expression is not builtin binary or unary operation.
11573 NotABinaryOrUnaryExpression,
11574 /// Unary operation is not post-/pre- increment/decrement operation.
11575 NotAnUnaryIncDecExpression,
11576 /// An expression is not of scalar type.
11577 NotAScalarType,
11578 /// A binary operation is not an assignment operation.
11579 NotAnAssignmentOp,
11580 /// RHS part of the binary operation is not a binary expression.
11581 NotABinaryExpression,
11582 /// RHS part is not additive/multiplicative/shift/bitwise binary
11583 /// expression.
11584 NotABinaryOperator,
11585 /// RHS binary operation does not have reference to the updated LHS
11586 /// part.
11587 NotAnUpdateExpression,
11588 /// An expression contains semantical error not related to
11589 /// 'omp atomic [update]'
11590 NotAValidExpression,
11591 /// No errors is found.
11592 NoError
11593 };
11594 /// Reference to Sema.
11595 Sema &SemaRef;
11596 /// A location for note diagnostics (when error is found).
11597 SourceLocation NoteLoc;
11598 /// 'x' lvalue part of the source atomic expression.
11599 Expr *X;
11600 /// 'expr' rvalue part of the source atomic expression.
11601 Expr *E;
11602 /// Helper expression of the form
11603 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11604 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11605 Expr *UpdateExpr;
11606 /// Is 'x' a LHS in a RHS part of full update expression. It is
11607 /// important for non-associative operations.
11608 bool IsXLHSInRHSPart;
11610 SourceLocation OpLoc;
11611 /// true if the source expression is a postfix unary operation, false
11612 /// if it is a prefix unary operation.
11613 bool IsPostfixUpdate;
11614
11615public:
11616 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11617 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11618 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11619 /// Check specified statement that it is suitable for 'atomic update'
11620 /// constructs and extract 'x', 'expr' and Operation from the original
11621 /// expression. If DiagId and NoteId == 0, then only check is performed
11622 /// without error notification.
11623 /// \param DiagId Diagnostic which should be emitted if error is found.
11624 /// \param NoteId Diagnostic note for the main error message.
11625 /// \return true if statement is not an update expression, false otherwise.
11626 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11627 /// Return the 'x' lvalue part of the source atomic expression.
11628 Expr *getX() const { return X; }
11629 /// Return the 'expr' rvalue part of the source atomic expression.
11630 Expr *getExpr() const { return E; }
11631 /// Return the update expression used in calculation of the updated
11632 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11633 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11634 Expr *getUpdateExpr() const { return UpdateExpr; }
11635 /// Return true if 'x' is LHS in RHS part of full update expression,
11636 /// false otherwise.
11637 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11638
11639 /// true if the source expression is a postfix unary operation, false
11640 /// if it is a prefix unary operation.
11641 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11642
11643private:
11644 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11645 unsigned NoteId = 0);
11646};
11647
11648bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11649 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11650 ExprAnalysisErrorCode ErrorFound = NoError;
11651 SourceLocation ErrorLoc, NoteLoc;
11652 SourceRange ErrorRange, NoteRange;
11653 // Allowed constructs are:
11654 // x = x binop expr;
11655 // x = expr binop x;
11656 if (AtomicBinOp->getOpcode() == BO_Assign) {
11657 X = AtomicBinOp->getLHS();
11658 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11659 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11660 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11661 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11662 AtomicInnerBinOp->isBitwiseOp()) {
11663 Op = AtomicInnerBinOp->getOpcode();
11664 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11665 Expr *LHS = AtomicInnerBinOp->getLHS();
11666 Expr *RHS = AtomicInnerBinOp->getRHS();
11667 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11668 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11669 /*Canonical=*/true);
11670 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11671 /*Canonical=*/true);
11672 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11673 /*Canonical=*/true);
11674 if (XId == LHSId) {
11675 E = RHS;
11676 IsXLHSInRHSPart = true;
11677 } else if (XId == RHSId) {
11678 E = LHS;
11679 IsXLHSInRHSPart = false;
11680 } else {
11681 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11682 ErrorRange = AtomicInnerBinOp->getSourceRange();
11683 NoteLoc = X->getExprLoc();
11684 NoteRange = X->getSourceRange();
11685 ErrorFound = NotAnUpdateExpression;
11686 }
11687 } else {
11688 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11689 ErrorRange = AtomicInnerBinOp->getSourceRange();
11690 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11691 NoteRange = SourceRange(NoteLoc, NoteLoc);
11692 ErrorFound = NotABinaryOperator;
11693 }
11694 } else {
11695 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11696 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11697 ErrorFound = NotABinaryExpression;
11698 }
11699 } else {
11700 ErrorLoc = AtomicBinOp->getExprLoc();
11701 ErrorRange = AtomicBinOp->getSourceRange();
11702 NoteLoc = AtomicBinOp->getOperatorLoc();
11703 NoteRange = SourceRange(NoteLoc, NoteLoc);
11704 ErrorFound = NotAnAssignmentOp;
11705 }
11706 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11707 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11708 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11709 return true;
11710 }
11711 if (SemaRef.CurContext->isDependentContext())
11712 E = X = UpdateExpr = nullptr;
11713 return ErrorFound != NoError;
11714}
11715
11716bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11717 unsigned NoteId) {
11718 ExprAnalysisErrorCode ErrorFound = NoError;
11719 SourceLocation ErrorLoc, NoteLoc;
11720 SourceRange ErrorRange, NoteRange;
11721 // Allowed constructs are:
11722 // x++;
11723 // x--;
11724 // ++x;
11725 // --x;
11726 // x binop= expr;
11727 // x = x binop expr;
11728 // x = expr binop x;
11729 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11730 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11731 if (AtomicBody->getType()->isScalarType() ||
11732 AtomicBody->isInstantiationDependent()) {
11733 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11734 AtomicBody->IgnoreParenImpCasts())) {
11735 // Check for Compound Assignment Operation
11737 AtomicCompAssignOp->getOpcode());
11738 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11739 E = AtomicCompAssignOp->getRHS();
11740 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11741 IsXLHSInRHSPart = true;
11742 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11743 AtomicBody->IgnoreParenImpCasts())) {
11744 // Check for Binary Operation
11745 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11746 return true;
11747 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11748 AtomicBody->IgnoreParenImpCasts())) {
11749 // Check for Unary Operation
11750 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11751 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11752 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11753 OpLoc = AtomicUnaryOp->getOperatorLoc();
11754 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11755 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11756 IsXLHSInRHSPart = true;
11757 } else {
11758 ErrorFound = NotAnUnaryIncDecExpression;
11759 ErrorLoc = AtomicUnaryOp->getExprLoc();
11760 ErrorRange = AtomicUnaryOp->getSourceRange();
11761 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11762 NoteRange = SourceRange(NoteLoc, NoteLoc);
11763 }
11764 } else if (!AtomicBody->isInstantiationDependent()) {
11765 ErrorFound = NotABinaryOrUnaryExpression;
11766 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11767 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11768 } else if (AtomicBody->containsErrors()) {
11769 ErrorFound = NotAValidExpression;
11770 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11771 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11772 }
11773 } else {
11774 ErrorFound = NotAScalarType;
11775 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11776 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11777 }
11778 } else {
11779 ErrorFound = NotAnExpression;
11780 NoteLoc = ErrorLoc = S->getBeginLoc();
11781 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11782 }
11783 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11784 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11785 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11786 return true;
11787 }
11788 if (SemaRef.CurContext->isDependentContext())
11789 E = X = UpdateExpr = nullptr;
11790 if (ErrorFound == NoError && E && X) {
11791 // Build an update expression of form 'OpaqueValueExpr(x) binop
11792 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11793 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11794 auto *OVEX = new (SemaRef.getASTContext())
11795 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11796 auto *OVEExpr = new (SemaRef.getASTContext())
11799 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11800 IsXLHSInRHSPart ? OVEExpr : OVEX);
11801 if (Update.isInvalid())
11802 return true;
11803 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11805 if (Update.isInvalid())
11806 return true;
11807 UpdateExpr = Update.get();
11808 }
11809 return ErrorFound != NoError;
11810}
11811
11812/// Get the node id of the fixed point of an expression \a S.
11813llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11814 llvm::FoldingSetNodeID Id;
11815 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11816 return Id;
11817}
11818
11819/// Check if two expressions are same.
11820bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11821 const Expr *RHS) {
11822 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11823}
11824
11825class OpenMPAtomicCompareChecker {
11826public:
11827 /// All kinds of errors that can occur in `atomic compare`
11828 enum ErrorTy {
11829 /// Empty compound statement.
11830 NoStmt = 0,
11831 /// More than one statement in a compound statement.
11832 MoreThanOneStmt,
11833 /// Not an assignment binary operator.
11834 NotAnAssignment,
11835 /// Not a conditional operator.
11836 NotCondOp,
11837 /// Wrong false expr. According to the spec, 'x' should be at the false
11838 /// expression of a conditional expression.
11839 WrongFalseExpr,
11840 /// The condition of a conditional expression is not a binary operator.
11841 NotABinaryOp,
11842 /// Invalid binary operator (not <, >, or ==).
11843 InvalidBinaryOp,
11844 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11845 InvalidComparison,
11846 /// X is not a lvalue.
11847 XNotLValue,
11848 /// Not a scalar.
11849 NotScalar,
11850 /// Not an integer.
11851 NotInteger,
11852 /// 'else' statement is not expected.
11853 UnexpectedElse,
11854 /// Not an equality operator.
11855 NotEQ,
11856 /// Invalid assignment (not v == x).
11857 InvalidAssignment,
11858 /// Not if statement
11859 NotIfStmt,
11860 /// More than two statements in a compound statement.
11861 MoreThanTwoStmts,
11862 /// Not a compound statement.
11863 NotCompoundStmt,
11864 /// No else statement.
11865 NoElse,
11866 /// Not 'if (r)'.
11867 InvalidCondition,
11868 /// No error.
11869 NoError,
11870 };
11871
11872 struct ErrorInfoTy {
11873 ErrorTy Error;
11874 SourceLocation ErrorLoc;
11875 SourceRange ErrorRange;
11876 SourceLocation NoteLoc;
11877 SourceRange NoteRange;
11878 };
11879
11880 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11881
11882 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11883 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11884
11885 Expr *getX() const { return X; }
11886 Expr *getE() const { return E; }
11887 Expr *getD() const { return D; }
11888 Expr *getCond() const { return C; }
11889 bool isXBinopExpr() const { return IsXBinopExpr; }
11890
11891protected:
11892 /// Reference to ASTContext
11893 ASTContext &ContextRef;
11894 /// 'x' lvalue part of the source atomic expression.
11895 Expr *X = nullptr;
11896 /// 'expr' or 'e' rvalue part of the source atomic expression.
11897 Expr *E = nullptr;
11898 /// 'd' rvalue part of the source atomic expression.
11899 Expr *D = nullptr;
11900 /// 'cond' part of the source atomic expression. It is in one of the following
11901 /// forms:
11902 /// expr ordop x
11903 /// x ordop expr
11904 /// x == e
11905 /// e == x
11906 Expr *C = nullptr;
11907 /// True if the cond expr is in the form of 'x ordop expr'.
11908 bool IsXBinopExpr = true;
11909
11910 /// Check if it is a valid conditional update statement (cond-update-stmt).
11911 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11912
11913 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11914 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11915
11916 /// Check if all captured values have right type.
11917 bool checkType(ErrorInfoTy &ErrorInfo) const;
11918
11919 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11920 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11921 if (E->isInstantiationDependent())
11922 return true;
11923
11924 if (ShouldBeLValue && !E->isLValue()) {
11925 ErrorInfo.Error = ErrorTy::XNotLValue;
11926 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11927 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11928 return false;
11929 }
11930
11931 QualType QTy = E->getType();
11932 if (!QTy->isScalarType()) {
11933 ErrorInfo.Error = ErrorTy::NotScalar;
11934 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11935 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11936 return false;
11937 }
11938 if (ShouldBeInteger && !QTy->isIntegerType()) {
11939 ErrorInfo.Error = ErrorTy::NotInteger;
11940 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11941 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11942 return false;
11943 }
11944
11945 return true;
11946 }
11947};
11948
11949bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11950 ErrorInfoTy &ErrorInfo) {
11951 auto *Then = S->getThen();
11952 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11953 if (CS->body_empty()) {
11954 ErrorInfo.Error = ErrorTy::NoStmt;
11955 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11956 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11957 return false;
11958 }
11959 if (CS->size() > 1) {
11960 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11961 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11962 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11963 return false;
11964 }
11965 Then = CS->body_front();
11966 }
11967
11968 auto *BO = dyn_cast<BinaryOperator>(Then);
11969 if (!BO) {
11970 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11971 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11972 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11973 return false;
11974 }
11975 if (BO->getOpcode() != BO_Assign) {
11976 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11977 ErrorInfo.ErrorLoc = BO->getExprLoc();
11978 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11979 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11980 return false;
11981 }
11982
11983 X = BO->getLHS();
11984
11985 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11986 auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
11987 Expr *LHS = nullptr;
11988 Expr *RHS = nullptr;
11989 if (Cond) {
11990 LHS = Cond->getLHS();
11991 RHS = Cond->getRHS();
11992 } else if (Call) {
11993 LHS = Call->getArg(0);
11994 RHS = Call->getArg(1);
11995 } else {
11996 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11997 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11998 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11999 return false;
12000 }
12001
12002 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12003 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12004 C = S->getCond();
12005 D = BO->getRHS();
12006 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12007 E = RHS;
12008 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12009 E = LHS;
12010 } else {
12011 ErrorInfo.Error = ErrorTy::InvalidComparison;
12012 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12013 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12014 S->getCond()->getSourceRange();
12015 return false;
12016 }
12017 } else if ((Cond &&
12018 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12019 (Call &&
12020 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12021 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12022 E = BO->getRHS();
12023 if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
12024 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12025 C = S->getCond();
12026 } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12027 checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12028 C = S->getCond();
12029 IsXBinopExpr = false;
12030 } else {
12031 ErrorInfo.Error = ErrorTy::InvalidComparison;
12032 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12033 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12034 S->getCond()->getSourceRange();
12035 return false;
12036 }
12037 } else {
12038 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12039 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12040 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12041 return false;
12042 }
12043
12044 if (S->getElse()) {
12045 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12046 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
12047 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
12048 return false;
12049 }
12050
12051 return true;
12052}
12053
12054bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
12055 ErrorInfoTy &ErrorInfo) {
12056 auto *BO = dyn_cast<BinaryOperator>(S);
12057 if (!BO) {
12058 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12059 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12060 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12061 return false;
12062 }
12063 if (BO->getOpcode() != BO_Assign) {
12064 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12065 ErrorInfo.ErrorLoc = BO->getExprLoc();
12066 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12067 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12068 return false;
12069 }
12070
12071 X = BO->getLHS();
12072
12073 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
12074 if (!CO) {
12075 ErrorInfo.Error = ErrorTy::NotCondOp;
12076 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12077 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12078 return false;
12079 }
12080
12081 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
12082 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12083 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12084 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12085 CO->getFalseExpr()->getSourceRange();
12086 return false;
12087 }
12088
12089 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
12090 auto *Call = dyn_cast<CXXOperatorCallExpr>(CO->getCond());
12091 Expr *LHS = nullptr;
12092 Expr *RHS = nullptr;
12093 if (Cond) {
12094 LHS = Cond->getLHS();
12095 RHS = Cond->getRHS();
12096 } else if (Call) {
12097 LHS = Call->getArg(0);
12098 RHS = Call->getArg(1);
12099 } else {
12100 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12101 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12102 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12103 CO->getCond()->getSourceRange();
12104 return false;
12105 }
12106
12107 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12108 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12109 C = CO->getCond();
12110 D = CO->getTrueExpr();
12111 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12112 E = RHS;
12113 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12114 E = LHS;
12115 } else {
12116 ErrorInfo.Error = ErrorTy::InvalidComparison;
12117 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12118 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12119 CO->getCond()->getSourceRange();
12120 return false;
12121 }
12122 } else if ((Cond &&
12123 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12124 (Call &&
12125 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12126 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12127
12128 E = CO->getTrueExpr();
12129 if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
12130 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12131 C = CO->getCond();
12132 } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12133 checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12134 C = CO->getCond();
12135 IsXBinopExpr = false;
12136 } else {
12137 ErrorInfo.Error = ErrorTy::InvalidComparison;
12138 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12139 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12140 CO->getCond()->getSourceRange();
12141 return false;
12142 }
12143 } else {
12144 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12145 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12146 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12147 CO->getCond()->getSourceRange();
12148 return false;
12149 }
12150
12151 return true;
12152}
12153
12154bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
12155 // 'x' and 'e' cannot be nullptr
12156 assert(X && E && "X and E cannot be nullptr");
12157
12158 if (!CheckValue(X, ErrorInfo, true))
12159 return false;
12160
12161 if (!CheckValue(E, ErrorInfo, false))
12162 return false;
12163
12164 if (D && !CheckValue(D, ErrorInfo, false))
12165 return false;
12166
12167 return true;
12168}
12169
12170bool OpenMPAtomicCompareChecker::checkStmt(
12171 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12172 auto *CS = dyn_cast<CompoundStmt>(S);
12173 if (CS) {
12174 if (CS->body_empty()) {
12175 ErrorInfo.Error = ErrorTy::NoStmt;
12176 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12177 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12178 return false;
12179 }
12180
12181 if (CS->size() != 1) {
12182 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12183 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12184 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12185 return false;
12186 }
12187 S = CS->body_front();
12188 }
12189
12190 auto Res = false;
12191
12192 if (auto *IS = dyn_cast<IfStmt>(S)) {
12193 // Check if the statement is in one of the following forms
12194 // (cond-update-stmt):
12195 // if (expr ordop x) { x = expr; }
12196 // if (x ordop expr) { x = expr; }
12197 // if (x == e) { x = d; }
12198 Res = checkCondUpdateStmt(IS, ErrorInfo);
12199 } else {
12200 // Check if the statement is in one of the following forms (cond-expr-stmt):
12201 // x = expr ordop x ? expr : x;
12202 // x = x ordop expr ? expr : x;
12203 // x = x == e ? d : x;
12204 Res = checkCondExprStmt(S, ErrorInfo);
12205 }
12206
12207 if (!Res)
12208 return false;
12209
12210 return checkType(ErrorInfo);
12211}
12212
12213class OpenMPAtomicCompareCaptureChecker final
12214 : public OpenMPAtomicCompareChecker {
12215public:
12216 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12217
12218 Expr *getV() const { return V; }
12219 Expr *getR() const { return R; }
12220 bool isFailOnly() const { return IsFailOnly; }
12221 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12222
12223 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12224 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12225
12226private:
12227 bool checkType(ErrorInfoTy &ErrorInfo);
12228
12229 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12230 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12231 // spec p.p. 82:
12232 // (1) { v = x; cond-update-stmt }
12233 // (2) { cond-update-stmt v = x; }
12234 // (3) if(x == e) { x = d; } else { v = x; }
12235 // (4) { r = x == e; if(r) { x = d; } }
12236 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12237
12238 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12239 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12240
12241 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12242 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12243 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12244
12245 /// 'v' lvalue part of the source atomic expression.
12246 Expr *V = nullptr;
12247 /// 'r' lvalue part of the source atomic expression.
12248 Expr *R = nullptr;
12249 /// If 'v' is only updated when the comparison fails.
12250 bool IsFailOnly = false;
12251 /// If original value of 'x' must be stored in 'v', not an updated one.
12252 bool IsPostfixUpdate = false;
12253};
12254
12255bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12256 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12257 return false;
12258
12259 if (V && !CheckValue(V, ErrorInfo, true))
12260 return false;
12261
12262 if (R && !CheckValue(R, ErrorInfo, true, true))
12263 return false;
12264
12265 return true;
12266}
12267
12268bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12269 ErrorInfoTy &ErrorInfo) {
12270 IsFailOnly = true;
12271
12272 auto *Then = S->getThen();
12273 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12274 if (CS->body_empty()) {
12275 ErrorInfo.Error = ErrorTy::NoStmt;
12276 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12277 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12278 return false;
12279 }
12280 if (CS->size() > 1) {
12281 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12282 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12283 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12284 return false;
12285 }
12286 Then = CS->body_front();
12287 }
12288
12289 auto *BO = dyn_cast<BinaryOperator>(Then);
12290 if (!BO) {
12291 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12292 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12293 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12294 return false;
12295 }
12296 if (BO->getOpcode() != BO_Assign) {
12297 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12298 ErrorInfo.ErrorLoc = BO->getExprLoc();
12299 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12300 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12301 return false;
12302 }
12303
12304 X = BO->getLHS();
12305 D = BO->getRHS();
12306
12307 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12308 auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
12309 Expr *LHS = nullptr;
12310 Expr *RHS = nullptr;
12311 if (Cond) {
12312 LHS = Cond->getLHS();
12313 RHS = Cond->getRHS();
12314 } else if (Call) {
12315 LHS = Call->getArg(0);
12316 RHS = Call->getArg(1);
12317 } else {
12318 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12319 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12320 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12321 return false;
12322 }
12323 if ((Cond && Cond->getOpcode() != BO_EQ) ||
12324 (Call && Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12325 ErrorInfo.Error = ErrorTy::NotEQ;
12326 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12327 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12328 return false;
12329 }
12330
12331 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12332 E = RHS;
12333 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12334 E = LHS;
12335 } else {
12336 ErrorInfo.Error = ErrorTy::InvalidComparison;
12337 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12338 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12339 return false;
12340 }
12341
12342 C = S->getCond();
12343
12344 if (!S->getElse()) {
12345 ErrorInfo.Error = ErrorTy::NoElse;
12346 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12347 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12348 return false;
12349 }
12350
12351 auto *Else = S->getElse();
12352 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12353 if (CS->body_empty()) {
12354 ErrorInfo.Error = ErrorTy::NoStmt;
12355 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12356 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12357 return false;
12358 }
12359 if (CS->size() > 1) {
12360 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12361 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12362 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12363 return false;
12364 }
12365 Else = CS->body_front();
12366 }
12367
12368 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12369 if (!ElseBO) {
12370 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12371 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12372 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12373 return false;
12374 }
12375 if (ElseBO->getOpcode() != BO_Assign) {
12376 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12377 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12378 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12379 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12380 return false;
12381 }
12382
12383 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12384 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12385 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12386 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12387 ElseBO->getRHS()->getSourceRange();
12388 return false;
12389 }
12390
12391 V = ElseBO->getLHS();
12392
12393 return checkType(ErrorInfo);
12394}
12395
12396bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12397 ErrorInfoTy &ErrorInfo) {
12398 // We don't check here as they should be already done before call this
12399 // function.
12400 auto *CS = cast<CompoundStmt>(S);
12401 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12402 auto *S1 = cast<BinaryOperator>(CS->body_front());
12403 auto *S2 = cast<IfStmt>(CS->body_back());
12404 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12405
12406 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12407 ErrorInfo.Error = ErrorTy::InvalidCondition;
12408 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12409 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12410 return false;
12411 }
12412
12413 R = S1->getLHS();
12414
12415 auto *Then = S2->getThen();
12416 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12417 if (ThenCS->body_empty()) {
12418 ErrorInfo.Error = ErrorTy::NoStmt;
12419 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12420 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12421 return false;
12422 }
12423 if (ThenCS->size() > 1) {
12424 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12425 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12426 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12427 return false;
12428 }
12429 Then = ThenCS->body_front();
12430 }
12431
12432 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12433 if (!ThenBO) {
12434 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12435 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12436 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12437 return false;
12438 }
12439 if (ThenBO->getOpcode() != BO_Assign) {
12440 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12441 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12442 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12443 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12444 return false;
12445 }
12446
12447 X = ThenBO->getLHS();
12448 D = ThenBO->getRHS();
12449
12450 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12451 if (BO->getOpcode() != BO_EQ) {
12452 ErrorInfo.Error = ErrorTy::NotEQ;
12453 ErrorInfo.ErrorLoc = BO->getExprLoc();
12454 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12455 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12456 return false;
12457 }
12458
12459 C = BO;
12460
12461 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12462 E = BO->getRHS();
12463 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12464 E = BO->getLHS();
12465 } else {
12466 ErrorInfo.Error = ErrorTy::InvalidComparison;
12467 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12468 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12469 return false;
12470 }
12471
12472 if (S2->getElse()) {
12473 IsFailOnly = true;
12474
12475 auto *Else = S2->getElse();
12476 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12477 if (ElseCS->body_empty()) {
12478 ErrorInfo.Error = ErrorTy::NoStmt;
12479 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12480 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12481 return false;
12482 }
12483 if (ElseCS->size() > 1) {
12484 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12485 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12486 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12487 return false;
12488 }
12489 Else = ElseCS->body_front();
12490 }
12491
12492 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12493 if (!ElseBO) {
12494 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12495 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12496 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12497 return false;
12498 }
12499 if (ElseBO->getOpcode() != BO_Assign) {
12500 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12501 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12502 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12503 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12504 return false;
12505 }
12506 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12507 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12508 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12509 ErrorInfo.NoteLoc = X->getExprLoc();
12510 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12511 ErrorInfo.NoteRange = X->getSourceRange();
12512 return false;
12513 }
12514
12515 V = ElseBO->getLHS();
12516 }
12517
12518 return checkType(ErrorInfo);
12519}
12520
12521bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12522 ErrorInfoTy &ErrorInfo) {
12523 // if(x == e) { x = d; } else { v = x; }
12524 if (auto *IS = dyn_cast<IfStmt>(S))
12525 return checkForm3(IS, ErrorInfo);
12526
12527 auto *CS = dyn_cast<CompoundStmt>(S);
12528 if (!CS) {
12529 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12530 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12531 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12532 return false;
12533 }
12534 if (CS->body_empty()) {
12535 ErrorInfo.Error = ErrorTy::NoStmt;
12536 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12537 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12538 return false;
12539 }
12540
12541 // { if(x == e) { x = d; } else { v = x; } }
12542 if (CS->size() == 1) {
12543 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12544 if (!IS) {
12545 ErrorInfo.Error = ErrorTy::NotIfStmt;
12546 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12547 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12548 CS->body_front()->getSourceRange();
12549 return false;
12550 }
12551
12552 return checkForm3(IS, ErrorInfo);
12553 } else if (CS->size() == 2) {
12554 auto *S1 = CS->body_front();
12555 auto *S2 = CS->body_back();
12556
12557 Stmt *UpdateStmt = nullptr;
12558 Stmt *CondUpdateStmt = nullptr;
12559 Stmt *CondExprStmt = nullptr;
12560
12561 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12562 // It could be one of the following cases:
12563 // { v = x; cond-update-stmt }
12564 // { v = x; cond-expr-stmt }
12565 // { cond-expr-stmt; v = x; }
12566 // form 45
12567 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12568 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12569 // check if form 45
12570 if (isa<IfStmt>(S2))
12571 return checkForm45(CS, ErrorInfo);
12572 // { cond-expr-stmt; v = x; }
12573 CondExprStmt = S1;
12574 UpdateStmt = S2;
12575 } else {
12576 IsPostfixUpdate = true;
12577 UpdateStmt = S1;
12578 if (isa<IfStmt>(S2)) {
12579 // { v = x; cond-update-stmt }
12580 CondUpdateStmt = S2;
12581 } else {
12582 // { v = x; cond-expr-stmt }
12583 CondExprStmt = S2;
12584 }
12585 }
12586 } else {
12587 // { cond-update-stmt v = x; }
12588 UpdateStmt = S2;
12589 CondUpdateStmt = S1;
12590 }
12591
12592 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12593 auto *IS = dyn_cast<IfStmt>(CUS);
12594 if (!IS) {
12595 ErrorInfo.Error = ErrorTy::NotIfStmt;
12596 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12597 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12598 return false;
12599 }
12600
12601 return checkCondUpdateStmt(IS, ErrorInfo);
12602 };
12603
12604 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12605 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12606 auto *BO = dyn_cast<BinaryOperator>(US);
12607 if (!BO) {
12608 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12609 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12610 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12611 return false;
12612 }
12613 if (BO->getOpcode() != BO_Assign) {
12614 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12615 ErrorInfo.ErrorLoc = BO->getExprLoc();
12616 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12617 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12618 return false;
12619 }
12620 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12621 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12622 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12623 ErrorInfo.NoteLoc = this->X->getExprLoc();
12624 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12625 ErrorInfo.NoteRange = this->X->getSourceRange();
12626 return false;
12627 }
12628
12629 this->V = BO->getLHS();
12630
12631 return true;
12632 };
12633
12634 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12635 return false;
12636 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12637 return false;
12638 if (!CheckUpdateStmt(UpdateStmt))
12639 return false;
12640 } else {
12641 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12642 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12643 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12644 return false;
12645 }
12646
12647 return checkType(ErrorInfo);
12648}
12649} // namespace
12650
12652 Stmt *AStmt,
12653 SourceLocation StartLoc,
12654 SourceLocation EndLoc) {
12655 ASTContext &Context = getASTContext();
12656 unsigned OMPVersion = getLangOpts().OpenMP;
12657 // Register location of the first atomic directive.
12658 DSAStack->addAtomicDirectiveLoc(StartLoc);
12659 if (!AStmt)
12660 return StmtError();
12661
12662 // 1.2.2 OpenMP Language Terminology
12663 // Structured block - An executable statement with a single entry at the
12664 // top and a single exit at the bottom.
12665 // The point of exit cannot be a branch out of the structured block.
12666 // longjmp() and throw() must not violate the entry/exit criteria.
12667 OpenMPClauseKind AtomicKind = OMPC_unknown;
12668 SourceLocation AtomicKindLoc;
12669 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12670 SourceLocation MemOrderLoc;
12671 bool MutexClauseEncountered = false;
12672 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12673 for (const OMPClause *C : Clauses) {
12674 switch (C->getClauseKind()) {
12675 case OMPC_read:
12676 case OMPC_write:
12677 case OMPC_update:
12678 MutexClauseEncountered = true;
12679 [[fallthrough]];
12680 case OMPC_capture:
12681 case OMPC_compare: {
12682 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12683 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12684 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12685 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12686 << getOpenMPClauseNameForDiag(AtomicKind);
12687 } else {
12688 AtomicKind = C->getClauseKind();
12689 AtomicKindLoc = C->getBeginLoc();
12690 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12691 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12692 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12693 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12694 << getOpenMPClauseNameForDiag(AtomicKind);
12695 }
12696 }
12697 break;
12698 }
12699 case OMPC_weak:
12700 case OMPC_fail: {
12701 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12702 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12703 << getOpenMPClauseNameForDiag(C->getClauseKind())
12704 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12705 return StmtError();
12706 }
12707 break;
12708 }
12709 case OMPC_seq_cst:
12710 case OMPC_acq_rel:
12711 case OMPC_acquire:
12712 case OMPC_release:
12713 case OMPC_relaxed: {
12714 if (MemOrderKind != OMPC_unknown) {
12715 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12716 << getOpenMPDirectiveName(OMPD_atomic, OMPVersion) << 0
12717 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12718 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12719 << getOpenMPClauseNameForDiag(MemOrderKind);
12720 } else {
12721 MemOrderKind = C->getClauseKind();
12722 MemOrderLoc = C->getBeginLoc();
12723 }
12724 break;
12725 }
12726 // The following clauses are allowed, but we don't need to do anything here.
12727 case OMPC_hint:
12728 break;
12729 default:
12730 llvm_unreachable("unknown clause is encountered");
12731 }
12732 }
12733 bool IsCompareCapture = false;
12734 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12735 EncounteredAtomicKinds.contains(OMPC_capture)) {
12736 IsCompareCapture = true;
12737 AtomicKind = OMPC_compare;
12738 }
12739 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12740 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12741 // release.
12742 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12743 // acquire.
12744 // If atomic-clause is update or not present then memory-order-clause must not
12745 // be acq_rel or acquire.
12746 if ((AtomicKind == OMPC_read &&
12747 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12748 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12749 AtomicKind == OMPC_unknown) &&
12750 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12751 SourceLocation Loc = AtomicKindLoc;
12752 if (AtomicKind == OMPC_unknown)
12753 Loc = StartLoc;
12754 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12755 << getOpenMPClauseNameForDiag(AtomicKind)
12756 << (AtomicKind == OMPC_unknown ? 1 : 0)
12757 << getOpenMPClauseNameForDiag(MemOrderKind);
12758 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12759 << getOpenMPClauseNameForDiag(MemOrderKind);
12760 }
12761
12762 Stmt *Body = AStmt;
12763 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12764 Body = EWC->getSubExpr();
12765
12766 Expr *X = nullptr;
12767 Expr *V = nullptr;
12768 Expr *E = nullptr;
12769 Expr *UE = nullptr;
12770 Expr *D = nullptr;
12771 Expr *CE = nullptr;
12772 Expr *R = nullptr;
12773 bool IsXLHSInRHSPart = false;
12774 bool IsPostfixUpdate = false;
12775 bool IsFailOnly = false;
12776 // OpenMP [2.12.6, atomic Construct]
12777 // In the next expressions:
12778 // * x and v (as applicable) are both l-value expressions with scalar type.
12779 // * During the execution of an atomic region, multiple syntactic
12780 // occurrences of x must designate the same storage location.
12781 // * Neither of v and expr (as applicable) may access the storage location
12782 // designated by x.
12783 // * Neither of x and expr (as applicable) may access the storage location
12784 // designated by v.
12785 // * expr is an expression with scalar type.
12786 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12787 // * binop, binop=, ++, and -- are not overloaded operators.
12788 // * The expression x binop expr must be numerically equivalent to x binop
12789 // (expr). This requirement is satisfied if the operators in expr have
12790 // precedence greater than binop, or by using parentheses around expr or
12791 // subexpressions of expr.
12792 // * The expression expr binop x must be numerically equivalent to (expr)
12793 // binop x. This requirement is satisfied if the operators in expr have
12794 // precedence equal to or greater than binop, or by using parentheses around
12795 // expr or subexpressions of expr.
12796 // * For forms that allow multiple occurrences of x, the number of times
12797 // that x is evaluated is unspecified.
12798 if (AtomicKind == OMPC_read) {
12799 enum {
12800 NotAnExpression,
12801 NotAnAssignmentOp,
12802 NotAScalarType,
12803 NotAnLValue,
12804 NoError
12805 } ErrorFound = NoError;
12806 SourceLocation ErrorLoc, NoteLoc;
12807 SourceRange ErrorRange, NoteRange;
12808 // If clause is read:
12809 // v = x;
12810 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12811 const auto *AtomicBinOp =
12812 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12813 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12814 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12815 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12816 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12817 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12818 if (!X->isLValue() || !V->isLValue()) {
12819 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12820 ErrorFound = NotAnLValue;
12821 ErrorLoc = AtomicBinOp->getExprLoc();
12822 ErrorRange = AtomicBinOp->getSourceRange();
12823 NoteLoc = NotLValueExpr->getExprLoc();
12824 NoteRange = NotLValueExpr->getSourceRange();
12825 }
12826 } else if (!X->isInstantiationDependent() ||
12827 !V->isInstantiationDependent()) {
12828 const Expr *NotScalarExpr =
12829 (X->isInstantiationDependent() || X->getType()->isScalarType())
12830 ? V
12831 : X;
12832 ErrorFound = NotAScalarType;
12833 ErrorLoc = AtomicBinOp->getExprLoc();
12834 ErrorRange = AtomicBinOp->getSourceRange();
12835 NoteLoc = NotScalarExpr->getExprLoc();
12836 NoteRange = NotScalarExpr->getSourceRange();
12837 }
12838 } else if (!AtomicBody->isInstantiationDependent()) {
12839 ErrorFound = NotAnAssignmentOp;
12840 ErrorLoc = AtomicBody->getExprLoc();
12841 ErrorRange = AtomicBody->getSourceRange();
12842 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12843 : AtomicBody->getExprLoc();
12844 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12845 : AtomicBody->getSourceRange();
12846 }
12847 } else {
12848 ErrorFound = NotAnExpression;
12849 NoteLoc = ErrorLoc = Body->getBeginLoc();
12850 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12851 }
12852 if (ErrorFound != NoError) {
12853 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12854 << ErrorRange;
12855 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12856 << ErrorFound << NoteRange;
12857 return StmtError();
12858 }
12859 if (SemaRef.CurContext->isDependentContext())
12860 V = X = nullptr;
12861 } else if (AtomicKind == OMPC_write) {
12862 enum {
12863 NotAnExpression,
12864 NotAnAssignmentOp,
12865 NotAScalarType,
12866 NotAnLValue,
12867 NoError
12868 } ErrorFound = NoError;
12869 SourceLocation ErrorLoc, NoteLoc;
12870 SourceRange ErrorRange, NoteRange;
12871 // If clause is write:
12872 // x = expr;
12873 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12874 const auto *AtomicBinOp =
12875 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12876 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12877 X = AtomicBinOp->getLHS();
12878 E = AtomicBinOp->getRHS();
12879 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12880 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
12881 if (!X->isLValue()) {
12882 ErrorFound = NotAnLValue;
12883 ErrorLoc = AtomicBinOp->getExprLoc();
12884 ErrorRange = AtomicBinOp->getSourceRange();
12885 NoteLoc = X->getExprLoc();
12886 NoteRange = X->getSourceRange();
12887 }
12888 } else if (!X->isInstantiationDependent() ||
12890 const Expr *NotScalarExpr =
12891 (X->isInstantiationDependent() || X->getType()->isScalarType())
12892 ? E
12893 : X;
12894 ErrorFound = NotAScalarType;
12895 ErrorLoc = AtomicBinOp->getExprLoc();
12896 ErrorRange = AtomicBinOp->getSourceRange();
12897 NoteLoc = NotScalarExpr->getExprLoc();
12898 NoteRange = NotScalarExpr->getSourceRange();
12899 }
12900 } else if (!AtomicBody->isInstantiationDependent()) {
12901 ErrorFound = NotAnAssignmentOp;
12902 ErrorLoc = AtomicBody->getExprLoc();
12903 ErrorRange = AtomicBody->getSourceRange();
12904 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12905 : AtomicBody->getExprLoc();
12906 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12907 : AtomicBody->getSourceRange();
12908 }
12909 } else {
12910 ErrorFound = NotAnExpression;
12911 NoteLoc = ErrorLoc = Body->getBeginLoc();
12912 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12913 }
12914 if (ErrorFound != NoError) {
12915 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12916 << ErrorRange;
12917 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12918 << ErrorFound << NoteRange;
12919 return StmtError();
12920 }
12921 if (SemaRef.CurContext->isDependentContext())
12922 E = X = nullptr;
12923 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12924 // If clause is update:
12925 // x++;
12926 // x--;
12927 // ++x;
12928 // --x;
12929 // x binop= expr;
12930 // x = x binop expr;
12931 // x = expr binop x;
12932 OpenMPAtomicUpdateChecker Checker(SemaRef);
12933 if (Checker.checkStatement(
12934 Body,
12935 (AtomicKind == OMPC_update)
12936 ? diag::err_omp_atomic_update_not_expression_statement
12937 : diag::err_omp_atomic_not_expression_statement,
12938 diag::note_omp_atomic_update))
12939 return StmtError();
12940 if (!SemaRef.CurContext->isDependentContext()) {
12941 E = Checker.getExpr();
12942 X = Checker.getX();
12943 UE = Checker.getUpdateExpr();
12944 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12945 }
12946 } else if (AtomicKind == OMPC_capture) {
12947 enum {
12948 NotAnAssignmentOp,
12949 NotACompoundStatement,
12950 NotTwoSubstatements,
12951 NotASpecificExpression,
12952 NoError
12953 } ErrorFound = NoError;
12954 SourceLocation ErrorLoc, NoteLoc;
12955 SourceRange ErrorRange, NoteRange;
12956 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12957 // If clause is a capture:
12958 // v = x++;
12959 // v = x--;
12960 // v = ++x;
12961 // v = --x;
12962 // v = x binop= expr;
12963 // v = x = x binop expr;
12964 // v = x = expr binop x;
12965 const auto *AtomicBinOp =
12966 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12967 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12968 V = AtomicBinOp->getLHS();
12969 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12970 OpenMPAtomicUpdateChecker Checker(SemaRef);
12971 if (Checker.checkStatement(
12972 Body, diag::err_omp_atomic_capture_not_expression_statement,
12973 diag::note_omp_atomic_update))
12974 return StmtError();
12975 E = Checker.getExpr();
12976 X = Checker.getX();
12977 UE = Checker.getUpdateExpr();
12978 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12979 IsPostfixUpdate = Checker.isPostfixUpdate();
12980 } else if (!AtomicBody->isInstantiationDependent()) {
12981 ErrorLoc = AtomicBody->getExprLoc();
12982 ErrorRange = AtomicBody->getSourceRange();
12983 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12984 : AtomicBody->getExprLoc();
12985 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12986 : AtomicBody->getSourceRange();
12987 ErrorFound = NotAnAssignmentOp;
12988 }
12989 if (ErrorFound != NoError) {
12990 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12991 << ErrorRange;
12992 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12993 return StmtError();
12994 }
12995 if (SemaRef.CurContext->isDependentContext())
12996 UE = V = E = X = nullptr;
12997 } else {
12998 // If clause is a capture:
12999 // { v = x; x = expr; }
13000 // { v = x; x++; }
13001 // { v = x; x--; }
13002 // { v = x; ++x; }
13003 // { v = x; --x; }
13004 // { v = x; x binop= expr; }
13005 // { v = x; x = x binop expr; }
13006 // { v = x; x = expr binop x; }
13007 // { x++; v = x; }
13008 // { x--; v = x; }
13009 // { ++x; v = x; }
13010 // { --x; v = x; }
13011 // { x binop= expr; v = x; }
13012 // { x = x binop expr; v = x; }
13013 // { x = expr binop x; v = x; }
13014 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
13015 // Check that this is { expr1; expr2; }
13016 if (CS->size() == 2) {
13017 Stmt *First = CS->body_front();
13018 Stmt *Second = CS->body_back();
13019 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
13020 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13021 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
13022 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13023 // Need to find what subexpression is 'v' and what is 'x'.
13024 OpenMPAtomicUpdateChecker Checker(SemaRef);
13025 bool IsUpdateExprFound = !Checker.checkStatement(Second);
13026 BinaryOperator *BinOp = nullptr;
13027 if (IsUpdateExprFound) {
13028 BinOp = dyn_cast<BinaryOperator>(First);
13029 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13030 }
13031 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
13032 // { v = x; x++; }
13033 // { v = x; x--; }
13034 // { v = x; ++x; }
13035 // { v = x; --x; }
13036 // { v = x; x binop= expr; }
13037 // { v = x; x = x binop expr; }
13038 // { v = x; x = expr binop x; }
13039 // Check that the first expression has form v = x.
13040 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13041 llvm::FoldingSetNodeID XId, PossibleXId;
13042 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13043 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13044 IsUpdateExprFound = XId == PossibleXId;
13045 if (IsUpdateExprFound) {
13046 V = BinOp->getLHS();
13047 X = Checker.getX();
13048 E = Checker.getExpr();
13049 UE = Checker.getUpdateExpr();
13050 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13051 IsPostfixUpdate = true;
13052 }
13053 }
13054 if (!IsUpdateExprFound) {
13055 IsUpdateExprFound = !Checker.checkStatement(First);
13056 BinOp = nullptr;
13057 if (IsUpdateExprFound) {
13058 BinOp = dyn_cast<BinaryOperator>(Second);
13059 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13060 }
13061 if (IsUpdateExprFound &&
13062 !SemaRef.CurContext->isDependentContext()) {
13063 // { x++; v = x; }
13064 // { x--; v = x; }
13065 // { ++x; v = x; }
13066 // { --x; v = x; }
13067 // { x binop= expr; v = x; }
13068 // { x = x binop expr; v = x; }
13069 // { x = expr binop x; v = x; }
13070 // Check that the second expression has form v = x.
13071 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13072 llvm::FoldingSetNodeID XId, PossibleXId;
13073 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13074 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13075 IsUpdateExprFound = XId == PossibleXId;
13076 if (IsUpdateExprFound) {
13077 V = BinOp->getLHS();
13078 X = Checker.getX();
13079 E = Checker.getExpr();
13080 UE = Checker.getUpdateExpr();
13081 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13082 IsPostfixUpdate = false;
13083 }
13084 }
13085 }
13086 if (!IsUpdateExprFound) {
13087 // { v = x; x = expr; }
13088 auto *FirstExpr = dyn_cast<Expr>(First);
13089 auto *SecondExpr = dyn_cast<Expr>(Second);
13090 if (!FirstExpr || !SecondExpr ||
13091 !(FirstExpr->isInstantiationDependent() ||
13092 SecondExpr->isInstantiationDependent())) {
13093 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
13094 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13095 ErrorFound = NotAnAssignmentOp;
13096 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13097 : First->getBeginLoc();
13098 NoteRange = ErrorRange = FirstBinOp
13099 ? FirstBinOp->getSourceRange()
13100 : SourceRange(ErrorLoc, ErrorLoc);
13101 } else {
13102 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
13103 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13104 ErrorFound = NotAnAssignmentOp;
13105 NoteLoc = ErrorLoc = SecondBinOp
13106 ? SecondBinOp->getOperatorLoc()
13107 : Second->getBeginLoc();
13108 NoteRange = ErrorRange =
13109 SecondBinOp ? SecondBinOp->getSourceRange()
13110 : SourceRange(ErrorLoc, ErrorLoc);
13111 } else {
13112 Expr *PossibleXRHSInFirst =
13113 FirstBinOp->getRHS()->IgnoreParenImpCasts();
13114 Expr *PossibleXLHSInSecond =
13115 SecondBinOp->getLHS()->IgnoreParenImpCasts();
13116 llvm::FoldingSetNodeID X1Id, X2Id;
13117 PossibleXRHSInFirst->Profile(X1Id, Context,
13118 /*Canonical=*/true);
13119 PossibleXLHSInSecond->Profile(X2Id, Context,
13120 /*Canonical=*/true);
13121 IsUpdateExprFound = X1Id == X2Id;
13122 if (IsUpdateExprFound) {
13123 V = FirstBinOp->getLHS();
13124 X = SecondBinOp->getLHS();
13125 E = SecondBinOp->getRHS();
13126 UE = nullptr;
13127 IsXLHSInRHSPart = false;
13128 IsPostfixUpdate = true;
13129 } else {
13130 ErrorFound = NotASpecificExpression;
13131 ErrorLoc = FirstBinOp->getExprLoc();
13132 ErrorRange = FirstBinOp->getSourceRange();
13133 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13134 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13135 }
13136 }
13137 }
13138 }
13139 }
13140 } else {
13141 NoteLoc = ErrorLoc = Body->getBeginLoc();
13142 NoteRange = ErrorRange =
13143 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13144 ErrorFound = NotTwoSubstatements;
13145 }
13146 } else {
13147 NoteLoc = ErrorLoc = Body->getBeginLoc();
13148 NoteRange = ErrorRange =
13149 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13150 ErrorFound = NotACompoundStatement;
13151 }
13152 }
13153 if (ErrorFound != NoError) {
13154 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
13155 << ErrorRange;
13156 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13157 return StmtError();
13158 }
13159 if (SemaRef.CurContext->isDependentContext())
13160 UE = V = E = X = nullptr;
13161 } else if (AtomicKind == OMPC_compare) {
13162 if (IsCompareCapture) {
13163 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13164 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
13165 if (!Checker.checkStmt(Body, ErrorInfo)) {
13166 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
13167 << ErrorInfo.ErrorRange;
13168 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13169 << ErrorInfo.Error << ErrorInfo.NoteRange;
13170 return StmtError();
13171 }
13172 X = Checker.getX();
13173 E = Checker.getE();
13174 D = Checker.getD();
13175 CE = Checker.getCond();
13176 V = Checker.getV();
13177 R = Checker.getR();
13178 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13179 IsXLHSInRHSPart = Checker.isXBinopExpr();
13180 IsFailOnly = Checker.isFailOnly();
13181 IsPostfixUpdate = Checker.isPostfixUpdate();
13182 } else {
13183 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13184 OpenMPAtomicCompareChecker Checker(SemaRef);
13185 if (!Checker.checkStmt(Body, ErrorInfo)) {
13186 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
13187 << ErrorInfo.ErrorRange;
13188 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13189 << ErrorInfo.Error << ErrorInfo.NoteRange;
13190 return StmtError();
13191 }
13192 X = Checker.getX();
13193 E = Checker.getE();
13194 D = Checker.getD();
13195 CE = Checker.getCond();
13196 // The weak clause may only appear if the resulting atomic operation is
13197 // an atomic conditional update for which the comparison tests for
13198 // equality. It was not possible to do this check in
13199 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
13200 // could not be performed (Clauses are not available).
13201 auto *It = find_if(Clauses, [](OMPClause *C) {
13202 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13203 });
13204 if (It != Clauses.end()) {
13205 auto *Cond = dyn_cast<BinaryOperator>(CE);
13206 if (Cond->getOpcode() != BO_EQ) {
13207 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13208 ErrorInfo.ErrorLoc = Cond->getExprLoc();
13209 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
13210 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
13211
13212 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
13213 << ErrorInfo.ErrorRange;
13214 return StmtError();
13215 }
13216 }
13217 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13218 IsXLHSInRHSPart = Checker.isXBinopExpr();
13219 }
13220 }
13221
13222 SemaRef.setFunctionHasBranchProtectedScope();
13223
13224 return OMPAtomicDirective::Create(
13225 Context, StartLoc, EndLoc, Clauses, AStmt,
13226 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
13227}
13228
13230 Stmt *AStmt,
13231 SourceLocation StartLoc,
13232 SourceLocation EndLoc) {
13233 if (!AStmt)
13234 return StmtError();
13235
13236 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target, AStmt);
13237
13238 // OpenMP [2.16, Nesting of Regions]
13239 // If specified, a teams construct must be contained within a target
13240 // construct. That target construct must contain no statements or directives
13241 // outside of the teams construct.
13242 if (DSAStack->hasInnerTeamsRegion()) {
13243 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13244 bool OMPTeamsFound = true;
13245 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
13246 auto I = CS->body_begin();
13247 while (I != CS->body_end()) {
13248 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13249 bool IsTeams = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13250 if (!IsTeams || I != CS->body_begin()) {
13251 OMPTeamsFound = false;
13252 if (IsTeams && I != CS->body_begin()) {
13253 // This is the two teams case. Since the InnerTeamsRegionLoc will
13254 // point to this second one reset the iterator to the other teams.
13255 --I;
13256 }
13257 break;
13258 }
13259 ++I;
13260 }
13261 assert(I != CS->body_end() && "Not found statement");
13262 S = *I;
13263 } else {
13264 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13265 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13266 }
13267 if (!OMPTeamsFound) {
13268 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13269 Diag(DSAStack->getInnerTeamsRegionLoc(),
13270 diag::note_omp_nested_teams_construct_here);
13271 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
13273 return StmtError();
13274 }
13275 }
13276
13277 return OMPTargetDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13278 AStmt);
13279}
13280
13282 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13283 SourceLocation EndLoc) {
13284 if (!AStmt)
13285 return StmtError();
13286
13287 setBranchProtectedScope(SemaRef, OMPD_target_parallel, AStmt);
13288
13290 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
13291 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13292}
13293
13295 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13296 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13297 if (!AStmt)
13298 return StmtError();
13299
13300 CapturedStmt *CS =
13301 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for, AStmt);
13302
13303 OMPLoopBasedDirective::HelperExprs B;
13304 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13305 // define the nested loops number.
13306 unsigned NestedLoopCount =
13307 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13308 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13309 VarsWithImplicitDSA, B);
13310 if (NestedLoopCount == 0)
13311 return StmtError();
13312
13313 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13314 return StmtError();
13315
13317 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13318 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13319}
13320
13321/// Check for existence of a map clause in the list of clauses.
13323 const OpenMPClauseKind K) {
13324 return llvm::any_of(
13325 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13326}
13327
13328template <typename... Params>
13330 const Params... ClauseTypes) {
13331 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13332}
13333
13334/// Check if the variables in the mapping clause are externally visible.
13336 for (const OMPClause *C : Clauses) {
13337 if (auto *TC = dyn_cast<OMPToClause>(C))
13338 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13339 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13340 (VD->isExternallyVisible() &&
13341 VD->getVisibility() != HiddenVisibility);
13342 });
13343 else if (auto *FC = dyn_cast<OMPFromClause>(C))
13344 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13345 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13346 (VD->isExternallyVisible() &&
13347 VD->getVisibility() != HiddenVisibility);
13348 });
13349 }
13350
13351 return true;
13352}
13353
13356 Stmt *AStmt, SourceLocation StartLoc,
13357 SourceLocation EndLoc) {
13358 if (!AStmt)
13359 return StmtError();
13360
13361 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13362
13363 // OpenMP [2.12.2, target data Construct, Restrictions]
13364 // At least one map, use_device_addr or use_device_ptr clause must appear on
13365 // the directive.
13366 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13367 (getLangOpts().OpenMP < 50 ||
13368 !hasClauses(Clauses, OMPC_use_device_addr))) {
13369 StringRef Expected;
13370 if (getLangOpts().OpenMP < 50)
13371 Expected = "'map' or 'use_device_ptr'";
13372 else
13373 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13374 unsigned OMPVersion = getLangOpts().OpenMP;
13375 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13376 << Expected << getOpenMPDirectiveName(OMPD_target_data, OMPVersion);
13377 return StmtError();
13378 }
13379
13380 SemaRef.setFunctionHasBranchProtectedScope();
13381
13382 return OMPTargetDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13383 Clauses, AStmt);
13384}
13385
13387 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13388 SourceLocation EndLoc, Stmt *AStmt) {
13389 if (!AStmt)
13390 return StmtError();
13391
13392 setBranchProtectedScope(SemaRef, OMPD_target_enter_data, AStmt);
13393
13394 // OpenMP [2.10.2, Restrictions, p. 99]
13395 // At least one map clause must appear on the directive.
13396 if (!hasClauses(Clauses, OMPC_map)) {
13397 unsigned OMPVersion = getLangOpts().OpenMP;
13398 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13399 << "'map'"
13400 << getOpenMPDirectiveName(OMPD_target_enter_data, OMPVersion);
13401 return StmtError();
13402 }
13403
13404 return OMPTargetEnterDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13405 Clauses, AStmt);
13406}
13407
13409 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13410 SourceLocation EndLoc, Stmt *AStmt) {
13411 if (!AStmt)
13412 return StmtError();
13413
13414 setBranchProtectedScope(SemaRef, OMPD_target_exit_data, AStmt);
13415
13416 // OpenMP [2.10.3, Restrictions, p. 102]
13417 // At least one map clause must appear on the directive.
13418 if (!hasClauses(Clauses, OMPC_map)) {
13419 unsigned OMPVersion = getLangOpts().OpenMP;
13420 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13421 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data, OMPVersion);
13422 return StmtError();
13423 }
13424
13425 return OMPTargetExitDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13426 Clauses, AStmt);
13427}
13428
13430 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13431 SourceLocation EndLoc, Stmt *AStmt) {
13432 if (!AStmt)
13433 return StmtError();
13434
13435 setBranchProtectedScope(SemaRef, OMPD_target_update, AStmt);
13436
13437 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13438 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13439 return StmtError();
13440 }
13441
13442 if (!isClauseMappable(Clauses)) {
13443 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13444 return StmtError();
13445 }
13446
13447 return OMPTargetUpdateDirective::Create(getASTContext(), StartLoc, EndLoc,
13448 Clauses, AStmt);
13449}
13450
13451/// This checks whether a \p ClauseType clause \p C has at most \p Max
13452/// expression. If not, a diag of number \p Diag will be emitted.
13453template <typename ClauseType>
13454static bool checkNumExprsInClause(SemaBase &SemaRef,
13455 ArrayRef<OMPClause *> Clauses,
13456 unsigned MaxNum, unsigned Diag) {
13457 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13458 if (ClauseItr == Clauses.end())
13459 return true;
13460 const auto *C = cast<ClauseType>(*ClauseItr);
13461 auto VarList = C->getVarRefs();
13462 if (VarList.size() > MaxNum) {
13463 SemaRef.Diag(VarList[MaxNum]->getBeginLoc(), Diag)
13464 << getOpenMPClauseNameForDiag(C->getClauseKind());
13465 return false;
13466 }
13467 return true;
13468}
13469
13471 Stmt *AStmt,
13472 SourceLocation StartLoc,
13473 SourceLocation EndLoc) {
13474 if (!AStmt)
13475 return StmtError();
13476
13478 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
13480 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
13481 return StmtError();
13482
13483 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13484 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13485 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13486
13487 setBranchProtectedScope(SemaRef, OMPD_teams, AStmt);
13488
13489 DSAStack->setParentTeamsRegionLoc(StartLoc);
13490
13491 return OMPTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13492 AStmt);
13493}
13494
13496 SourceLocation StartLoc, SourceLocation EndLoc,
13497 OpenMPDirectiveKind CancelRegion) {
13498 if (DSAStack->isParentNowaitRegion()) {
13499 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13500 return StmtError();
13501 }
13502 if (DSAStack->isParentOrderedRegion()) {
13503 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13504 return StmtError();
13505 }
13507 EndLoc, CancelRegion);
13508}
13509
13511 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13512 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13513 if (DSAStack->isParentNowaitRegion()) {
13514 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13515 return StmtError();
13516 }
13517 if (DSAStack->isParentOrderedRegion()) {
13518 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13519 return StmtError();
13520 }
13521 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13522 return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13523 CancelRegion);
13524}
13525
13527 ArrayRef<OMPClause *> Clauses) {
13528 const OMPClause *ReductionClause = nullptr;
13529 const OMPClause *NogroupClause = nullptr;
13530 for (const OMPClause *C : Clauses) {
13531 if (C->getClauseKind() == OMPC_reduction) {
13532 ReductionClause = C;
13533 if (NogroupClause)
13534 break;
13535 continue;
13536 }
13537 if (C->getClauseKind() == OMPC_nogroup) {
13538 NogroupClause = C;
13539 if (ReductionClause)
13540 break;
13541 continue;
13542 }
13543 }
13544 if (ReductionClause && NogroupClause) {
13545 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13546 << SourceRange(NogroupClause->getBeginLoc(),
13547 NogroupClause->getEndLoc());
13548 return true;
13549 }
13550 return false;
13551}
13552
13554 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13555 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13556 if (!AStmt)
13557 return StmtError();
13558
13559 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13560 OMPLoopBasedDirective::HelperExprs B;
13561 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13562 // define the nested loops number.
13563 unsigned NestedLoopCount =
13564 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13565 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13566 *DSAStack, VarsWithImplicitDSA, B);
13567 if (NestedLoopCount == 0)
13568 return StmtError();
13569
13570 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13571 "omp for loop exprs were not built");
13572
13573 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13574 // The grainsize clause and num_tasks clause are mutually exclusive and may
13575 // not appear on the same taskloop directive.
13577 {OMPC_grainsize, OMPC_num_tasks}))
13578 return StmtError();
13579 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13580 // If a reduction clause is present on the taskloop directive, the nogroup
13581 // clause must not be specified.
13583 return StmtError();
13584
13585 SemaRef.setFunctionHasBranchProtectedScope();
13586 return OMPTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13587 NestedLoopCount, Clauses, AStmt, B,
13588 DSAStack->isCancelRegion());
13589}
13590
13592 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13593 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13594 if (!AStmt)
13595 return StmtError();
13596
13597 CapturedStmt *CS =
13598 setBranchProtectedScope(SemaRef, OMPD_taskloop_simd, AStmt);
13599
13600 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13601 OMPLoopBasedDirective::HelperExprs B;
13602 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13603 // define the nested loops number.
13604 unsigned NestedLoopCount =
13605 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13606 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13607 VarsWithImplicitDSA, B);
13608 if (NestedLoopCount == 0)
13609 return StmtError();
13610
13611 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13612 return StmtError();
13613
13614 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13615 // The grainsize clause and num_tasks clause are mutually exclusive and may
13616 // not appear on the same taskloop directive.
13618 {OMPC_grainsize, OMPC_num_tasks}))
13619 return StmtError();
13620 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13621 // If a reduction clause is present on the taskloop directive, the nogroup
13622 // clause must not be specified.
13624 return StmtError();
13626 return StmtError();
13627
13628 return OMPTaskLoopSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13629 NestedLoopCount, Clauses, AStmt, B);
13630}
13631
13633 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13634 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13635 if (!AStmt)
13636 return StmtError();
13637
13638 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13639 OMPLoopBasedDirective::HelperExprs B;
13640 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13641 // define the nested loops number.
13642 unsigned NestedLoopCount =
13643 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13644 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13645 *DSAStack, VarsWithImplicitDSA, B);
13646 if (NestedLoopCount == 0)
13647 return StmtError();
13648
13649 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13650 "omp for loop exprs were not built");
13651
13652 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13653 // The grainsize clause and num_tasks clause are mutually exclusive and may
13654 // not appear on the same taskloop directive.
13656 {OMPC_grainsize, OMPC_num_tasks}))
13657 return StmtError();
13658 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13659 // If a reduction clause is present on the taskloop directive, the nogroup
13660 // clause must not be specified.
13662 return StmtError();
13663
13664 SemaRef.setFunctionHasBranchProtectedScope();
13665 return OMPMasterTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13666 NestedLoopCount, Clauses, AStmt, B,
13667 DSAStack->isCancelRegion());
13668}
13669
13671 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13672 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13673 if (!AStmt)
13674 return StmtError();
13675
13676 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13677 OMPLoopBasedDirective::HelperExprs B;
13678 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13679 // define the nested loops number.
13680 unsigned NestedLoopCount =
13681 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13682 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13683 *DSAStack, VarsWithImplicitDSA, B);
13684 if (NestedLoopCount == 0)
13685 return StmtError();
13686
13687 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13688 "omp for loop exprs were not built");
13689
13690 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13691 // The grainsize clause and num_tasks clause are mutually exclusive and may
13692 // not appear on the same taskloop directive.
13694 {OMPC_grainsize, OMPC_num_tasks}))
13695 return StmtError();
13696 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13697 // If a reduction clause is present on the taskloop directive, the nogroup
13698 // clause must not be specified.
13700 return StmtError();
13701
13702 SemaRef.setFunctionHasBranchProtectedScope();
13703 return OMPMaskedTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13704 NestedLoopCount, Clauses, AStmt, B,
13705 DSAStack->isCancelRegion());
13706}
13707
13709 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13710 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13711 if (!AStmt)
13712 return StmtError();
13713
13714 CapturedStmt *CS =
13715 setBranchProtectedScope(SemaRef, OMPD_master_taskloop_simd, AStmt);
13716
13717 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13718 OMPLoopBasedDirective::HelperExprs B;
13719 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13720 // define the nested loops number.
13721 unsigned NestedLoopCount =
13722 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13723 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13724 VarsWithImplicitDSA, B);
13725 if (NestedLoopCount == 0)
13726 return StmtError();
13727
13728 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13729 return StmtError();
13730
13731 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13732 // The grainsize clause and num_tasks clause are mutually exclusive and may
13733 // not appear on the same taskloop directive.
13735 {OMPC_grainsize, OMPC_num_tasks}))
13736 return StmtError();
13737 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13738 // If a reduction clause is present on the taskloop directive, the nogroup
13739 // clause must not be specified.
13741 return StmtError();
13743 return StmtError();
13744
13746 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13747}
13748
13750 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13751 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13752 if (!AStmt)
13753 return StmtError();
13754
13755 CapturedStmt *CS =
13756 setBranchProtectedScope(SemaRef, OMPD_masked_taskloop_simd, AStmt);
13757
13758 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13759 OMPLoopBasedDirective::HelperExprs B;
13760 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13761 // define the nested loops number.
13762 unsigned NestedLoopCount =
13763 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13764 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13765 VarsWithImplicitDSA, B);
13766 if (NestedLoopCount == 0)
13767 return StmtError();
13768
13769 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13770 return StmtError();
13771
13772 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13773 // The grainsize clause and num_tasks clause are mutually exclusive and may
13774 // not appear on the same taskloop directive.
13776 {OMPC_grainsize, OMPC_num_tasks}))
13777 return StmtError();
13778 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13779 // If a reduction clause is present on the taskloop directive, the nogroup
13780 // clause must not be specified.
13782 return StmtError();
13784 return StmtError();
13785
13787 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13788}
13789
13791 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13792 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13793 if (!AStmt)
13794 return StmtError();
13795
13796 CapturedStmt *CS =
13797 setBranchProtectedScope(SemaRef, OMPD_parallel_master_taskloop, AStmt);
13798
13799 OMPLoopBasedDirective::HelperExprs B;
13800 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13801 // define the nested loops number.
13802 unsigned NestedLoopCount = checkOpenMPLoop(
13803 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13804 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13805 VarsWithImplicitDSA, B);
13806 if (NestedLoopCount == 0)
13807 return StmtError();
13808
13809 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13810 "omp for loop exprs were not built");
13811
13812 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13813 // The grainsize clause and num_tasks clause are mutually exclusive and may
13814 // not appear on the same taskloop directive.
13816 {OMPC_grainsize, OMPC_num_tasks}))
13817 return StmtError();
13818 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13819 // If a reduction clause is present on the taskloop directive, the nogroup
13820 // clause must not be specified.
13822 return StmtError();
13823
13825 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13826 DSAStack->isCancelRegion());
13827}
13828
13830 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13831 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13832 if (!AStmt)
13833 return StmtError();
13834
13835 CapturedStmt *CS =
13836 setBranchProtectedScope(SemaRef, OMPD_parallel_masked_taskloop, AStmt);
13837
13838 OMPLoopBasedDirective::HelperExprs B;
13839 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13840 // define the nested loops number.
13841 unsigned NestedLoopCount = checkOpenMPLoop(
13842 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13843 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13844 VarsWithImplicitDSA, B);
13845 if (NestedLoopCount == 0)
13846 return StmtError();
13847
13848 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13849 "omp for loop exprs were not built");
13850
13851 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13852 // The grainsize clause and num_tasks clause are mutually exclusive and may
13853 // not appear on the same taskloop directive.
13855 {OMPC_grainsize, OMPC_num_tasks}))
13856 return StmtError();
13857 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13858 // If a reduction clause is present on the taskloop directive, the nogroup
13859 // clause must not be specified.
13861 return StmtError();
13862
13864 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13865 DSAStack->isCancelRegion());
13866}
13867
13869 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13870 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13871 if (!AStmt)
13872 return StmtError();
13873
13875 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13876
13877 OMPLoopBasedDirective::HelperExprs B;
13878 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13879 // define the nested loops number.
13880 unsigned NestedLoopCount = checkOpenMPLoop(
13881 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13882 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13883 VarsWithImplicitDSA, B);
13884 if (NestedLoopCount == 0)
13885 return StmtError();
13886
13887 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13888 return StmtError();
13889
13890 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13891 // The grainsize clause and num_tasks clause are mutually exclusive and may
13892 // not appear on the same taskloop directive.
13894 {OMPC_grainsize, OMPC_num_tasks}))
13895 return StmtError();
13896 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13897 // If a reduction clause is present on the taskloop directive, the nogroup
13898 // clause must not be specified.
13900 return StmtError();
13902 return StmtError();
13903
13905 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13906}
13907
13909 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13910 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13911 if (!AStmt)
13912 return StmtError();
13913
13915 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13916
13917 OMPLoopBasedDirective::HelperExprs B;
13918 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13919 // define the nested loops number.
13920 unsigned NestedLoopCount = checkOpenMPLoop(
13921 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13922 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13923 VarsWithImplicitDSA, B);
13924 if (NestedLoopCount == 0)
13925 return StmtError();
13926
13927 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13928 return StmtError();
13929
13930 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13931 // The grainsize clause and num_tasks clause are mutually exclusive and may
13932 // not appear on the same taskloop directive.
13934 {OMPC_grainsize, OMPC_num_tasks}))
13935 return StmtError();
13936 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13937 // If a reduction clause is present on the taskloop directive, the nogroup
13938 // clause must not be specified.
13940 return StmtError();
13942 return StmtError();
13943
13945 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13946}
13947
13949 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13950 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13951 if (!AStmt)
13952 return StmtError();
13953
13954 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13955 OMPLoopBasedDirective::HelperExprs B;
13956 // In presence of clause 'collapse' with number of loops, it will
13957 // define the nested loops number.
13958 unsigned NestedLoopCount =
13959 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
13960 nullptr /*ordered not a clause on distribute*/, AStmt,
13961 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13962 if (NestedLoopCount == 0)
13963 return StmtError();
13964
13965 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13966 "omp for loop exprs were not built");
13967
13968 SemaRef.setFunctionHasBranchProtectedScope();
13969 auto *DistributeDirective = OMPDistributeDirective::Create(
13970 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13971 return DistributeDirective;
13972}
13973
13975 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13976 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13977 if (!AStmt)
13978 return StmtError();
13979
13980 CapturedStmt *CS =
13981 setBranchProtectedScope(SemaRef, OMPD_distribute_parallel_for, AStmt);
13982
13983 OMPLoopBasedDirective::HelperExprs B;
13984 // In presence of clause 'collapse' with number of loops, it will
13985 // define the nested loops number.
13986 unsigned NestedLoopCount = checkOpenMPLoop(
13987 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13988 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13989 VarsWithImplicitDSA, B);
13990 if (NestedLoopCount == 0)
13991 return StmtError();
13992
13993 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13994 "omp for loop exprs were not built");
13995
13997 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13998 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13999}
14000
14002 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14003 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14004 if (!AStmt)
14005 return StmtError();
14006
14008 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
14009
14010 OMPLoopBasedDirective::HelperExprs B;
14011 // In presence of clause 'collapse' with number of loops, it will
14012 // define the nested loops number.
14013 unsigned NestedLoopCount = checkOpenMPLoop(
14014 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14015 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14016 VarsWithImplicitDSA, B);
14017 if (NestedLoopCount == 0)
14018 return StmtError();
14019
14020 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14021 return StmtError();
14022
14024 return StmtError();
14025
14027 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14028}
14029
14031 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14032 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14033 if (!AStmt)
14034 return StmtError();
14035
14036 CapturedStmt *CS =
14037 setBranchProtectedScope(SemaRef, OMPD_distribute_simd, AStmt);
14038
14039 OMPLoopBasedDirective::HelperExprs B;
14040 // In presence of clause 'collapse' with number of loops, it will
14041 // define the nested loops number.
14042 unsigned NestedLoopCount =
14043 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
14044 nullptr /*ordered not a clause on distribute*/, CS,
14045 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14046 if (NestedLoopCount == 0)
14047 return StmtError();
14048
14049 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14050 return StmtError();
14051
14053 return StmtError();
14054
14055 return OMPDistributeSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
14056 NestedLoopCount, Clauses, AStmt, B);
14057}
14058
14060 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14061 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14062 if (!AStmt)
14063 return StmtError();
14064
14065 CapturedStmt *CS =
14066 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for_simd, AStmt);
14067
14068 OMPLoopBasedDirective::HelperExprs B;
14069 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14070 // define the nested loops number.
14071 unsigned NestedLoopCount = checkOpenMPLoop(
14072 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
14073 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
14074 VarsWithImplicitDSA, B);
14075 if (NestedLoopCount == 0)
14076 return StmtError();
14077
14078 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14079 return StmtError();
14080
14082 return StmtError();
14083
14085 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14086}
14087
14089 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14090 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14091 if (!AStmt)
14092 return StmtError();
14093
14094 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target_simd, AStmt);
14095
14096 OMPLoopBasedDirective::HelperExprs B;
14097 // In presence of clause 'collapse' with number of loops, it will define the
14098 // nested loops number.
14099 unsigned NestedLoopCount =
14100 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
14101 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
14102 VarsWithImplicitDSA, B);
14103 if (NestedLoopCount == 0)
14104 return StmtError();
14105
14106 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14107 return StmtError();
14108
14110 return StmtError();
14111
14112 return OMPTargetSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
14113 NestedLoopCount, Clauses, AStmt, B);
14114}
14115
14117 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14118 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14119 if (!AStmt)
14120 return StmtError();
14121
14122 CapturedStmt *CS =
14123 setBranchProtectedScope(SemaRef, OMPD_teams_distribute, AStmt);
14124
14125 OMPLoopBasedDirective::HelperExprs B;
14126 // In presence of clause 'collapse' with number of loops, it will
14127 // define the nested loops number.
14128 unsigned NestedLoopCount =
14129 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
14130 nullptr /*ordered not a clause on distribute*/, CS,
14131 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14132 if (NestedLoopCount == 0)
14133 return StmtError();
14134
14135 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14136 "omp teams distribute loop exprs were not built");
14137
14138 DSAStack->setParentTeamsRegionLoc(StartLoc);
14139
14141 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14142}
14143
14145 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14146 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14147 if (!AStmt)
14148 return StmtError();
14149
14150 CapturedStmt *CS =
14151 setBranchProtectedScope(SemaRef, OMPD_teams_distribute_simd, AStmt);
14152
14153 OMPLoopBasedDirective::HelperExprs B;
14154 // In presence of clause 'collapse' with number of loops, it will
14155 // define the nested loops number.
14156 unsigned NestedLoopCount = checkOpenMPLoop(
14157 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14158 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14159 VarsWithImplicitDSA, B);
14160 if (NestedLoopCount == 0)
14161 return StmtError();
14162
14163 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14164 return StmtError();
14165
14167 return StmtError();
14168
14169 DSAStack->setParentTeamsRegionLoc(StartLoc);
14170
14172 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14173}
14174
14176 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14177 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14178 if (!AStmt)
14179 return StmtError();
14180
14182 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
14183
14184 OMPLoopBasedDirective::HelperExprs B;
14185 // In presence of clause 'collapse' with number of loops, it will
14186 // define the nested loops number.
14187 unsigned NestedLoopCount = checkOpenMPLoop(
14188 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14189 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14190 VarsWithImplicitDSA, B);
14191 if (NestedLoopCount == 0)
14192 return StmtError();
14193
14194 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14195 return StmtError();
14196
14198 return StmtError();
14199
14200 DSAStack->setParentTeamsRegionLoc(StartLoc);
14201
14203 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14204}
14205
14207 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14208 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14209 if (!AStmt)
14210 return StmtError();
14211
14213 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
14214
14215 OMPLoopBasedDirective::HelperExprs B;
14216 // In presence of clause 'collapse' with number of loops, it will
14217 // define the nested loops number.
14218 unsigned NestedLoopCount = checkOpenMPLoop(
14219 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14220 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14221 VarsWithImplicitDSA, B);
14222
14223 if (NestedLoopCount == 0)
14224 return StmtError();
14225
14226 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14227 "omp for loop exprs were not built");
14228
14229 DSAStack->setParentTeamsRegionLoc(StartLoc);
14230
14232 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14233 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14234}
14235
14237 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14238 SourceLocation EndLoc) {
14239 if (!AStmt)
14240 return StmtError();
14241
14242 setBranchProtectedScope(SemaRef, OMPD_target_teams, AStmt);
14243
14244 const OMPClause *BareClause = nullptr;
14245 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) &&
14246 hasClauses(Clauses, OMPC_thread_limit);
14247 bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) {
14248 BareClause = C;
14249 return C->getClauseKind() == OMPC_ompx_bare;
14250 });
14251
14252 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14253 Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
14254 return StmtError();
14255 }
14256
14257 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
14258 unsigned DiagNo = HasBareClause
14259 ? diag::err_ompx_more_than_three_expr_not_allowed
14260 : diag::err_omp_multi_expr_not_allowed;
14261 if (!checkNumExprsInClause<OMPNumTeamsClause>(*this, Clauses,
14262 ClauseMaxNumExprs, DiagNo) ||
14264 ClauseMaxNumExprs, DiagNo))
14265 return StmtError();
14266
14267 return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc,
14268 Clauses, AStmt);
14269}
14270
14272 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14273 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14274 if (!AStmt)
14275 return StmtError();
14276
14278 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14280 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14281 return StmtError();
14282
14283 CapturedStmt *CS =
14284 setBranchProtectedScope(SemaRef, OMPD_target_teams_distribute, AStmt);
14285
14286 OMPLoopBasedDirective::HelperExprs B;
14287 // In presence of clause 'collapse' with number of loops, it will
14288 // define the nested loops number.
14289 unsigned NestedLoopCount = checkOpenMPLoop(
14290 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14291 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14292 VarsWithImplicitDSA, B);
14293 if (NestedLoopCount == 0)
14294 return StmtError();
14295
14296 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14297 "omp target teams distribute loop exprs were not built");
14298
14300 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14301}
14302
14304 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14305 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14306 if (!AStmt)
14307 return StmtError();
14308
14310 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14312 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14313 return StmtError();
14314
14316 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14317
14318 OMPLoopBasedDirective::HelperExprs B;
14319 // In presence of clause 'collapse' with number of loops, it will
14320 // define the nested loops number.
14321 unsigned NestedLoopCount = checkOpenMPLoop(
14322 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14323 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14324 VarsWithImplicitDSA, B);
14325 if (NestedLoopCount == 0)
14326 return StmtError();
14327
14328 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14329 return StmtError();
14330
14332 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14333 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14334}
14335
14337 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14338 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14339 if (!AStmt)
14340 return StmtError();
14341
14343 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14345 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14346 return StmtError();
14347
14349 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14350
14351 OMPLoopBasedDirective::HelperExprs B;
14352 // In presence of clause 'collapse' with number of loops, it will
14353 // define the nested loops number.
14354 unsigned NestedLoopCount =
14355 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14356 getCollapseNumberExpr(Clauses),
14357 nullptr /*ordered not a clause on distribute*/, CS,
14358 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14359 if (NestedLoopCount == 0)
14360 return StmtError();
14361
14362 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14363 return StmtError();
14364
14366 return StmtError();
14367
14369 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14370}
14371
14373 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14374 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14375 if (!AStmt)
14376 return StmtError();
14377
14379 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14381 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14382 return StmtError();
14383
14385 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14386
14387 OMPLoopBasedDirective::HelperExprs B;
14388 // In presence of clause 'collapse' with number of loops, it will
14389 // define the nested loops number.
14390 unsigned NestedLoopCount = checkOpenMPLoop(
14391 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14392 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14393 VarsWithImplicitDSA, B);
14394 if (NestedLoopCount == 0)
14395 return StmtError();
14396
14397 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14398 return StmtError();
14399
14401 return StmtError();
14402
14404 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14405}
14406
14407bool SemaOpenMP::checkTransformableLoopNest(
14408 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14410 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *, 0>> &OriginalInits) {
14411 OriginalInits.emplace_back();
14412 bool Result = OMPLoopBasedDirective::doForAllLoops(
14413 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14414 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14415 Stmt *CurStmt) {
14416 VarsWithInheritedDSAType TmpDSA;
14417 unsigned SingleNumLoops =
14418 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14419 TmpDSA, LoopHelpers[Cnt]);
14420 if (SingleNumLoops == 0)
14421 return true;
14422 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14423 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14424 OriginalInits.back().push_back(For->getInit());
14425 Body = For->getBody();
14426 } else {
14427 assert(isa<CXXForRangeStmt>(CurStmt) &&
14428 "Expected canonical for or range-based for loops.");
14429 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14430 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14431 Body = CXXFor->getBody();
14432 }
14433 OriginalInits.emplace_back();
14434 return false;
14435 },
14436 [&OriginalInits](OMPLoopBasedDirective *Transform) {
14437 Stmt *DependentPreInits;
14438 if (auto *Dir = dyn_cast<OMPTileDirective>(Transform))
14439 DependentPreInits = Dir->getPreInits();
14440 else if (auto *Dir = dyn_cast<OMPStripeDirective>(Transform))
14441 DependentPreInits = Dir->getPreInits();
14442 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
14443 DependentPreInits = Dir->getPreInits();
14444 else if (auto *Dir = dyn_cast<OMPReverseDirective>(Transform))
14445 DependentPreInits = Dir->getPreInits();
14446 else if (auto *Dir = dyn_cast<OMPInterchangeDirective>(Transform))
14447 DependentPreInits = Dir->getPreInits();
14448 else
14449 llvm_unreachable("Unhandled loop transformation");
14450
14451 appendFlattenedStmtList(OriginalInits.back(), DependentPreInits);
14452 });
14453 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14454 OriginalInits.pop_back();
14455 return Result;
14456}
14457
14458/// Add preinit statements that need to be propageted from the selected loop.
14459static void addLoopPreInits(ASTContext &Context,
14460 OMPLoopBasedDirective::HelperExprs &LoopHelper,
14461 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
14462 SmallVectorImpl<Stmt *> &PreInits) {
14463
14464 // For range-based for-statements, ensure that their syntactic sugar is
14465 // executed by adding them as pre-init statements.
14466 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14467 Stmt *RangeInit = CXXRangeFor->getInit();
14468 if (RangeInit)
14469 PreInits.push_back(RangeInit);
14470
14471 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14472 PreInits.push_back(new (Context) DeclStmt(RangeStmt->getDeclGroup(),
14473 RangeStmt->getBeginLoc(),
14474 RangeStmt->getEndLoc()));
14475
14476 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14477 PreInits.push_back(new (Context) DeclStmt(RangeEnd->getDeclGroup(),
14478 RangeEnd->getBeginLoc(),
14479 RangeEnd->getEndLoc()));
14480 }
14481
14482 llvm::append_range(PreInits, OriginalInit);
14483
14484 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
14485 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
14486 PreInits.push_back(new (Context) DeclStmt(
14487 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14488 }
14489
14490 // Gather declarations for the data members used as counters.
14491 for (Expr *CounterRef : LoopHelper.Counters) {
14492 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14493 if (isa<OMPCapturedExprDecl>(CounterDecl))
14494 PreInits.push_back(new (Context) DeclStmt(
14495 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
14496 }
14497}
14498
14499/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
14500/// loop of a construct.
14501static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) {
14502 size_t NumLoops = LoopStmts.size();
14503 OMPLoopBasedDirective::doForAllLoops(
14504 AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
14505 [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
14506 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
14507 LoopStmts[Cnt] = CurStmt;
14508 return false;
14509 });
14510 assert(!is_contained(LoopStmts, nullptr) &&
14511 "Expecting a loop statement for each affected loop");
14512}
14513
14514/// Build and return a DeclRefExpr for the floor induction variable using the
14515/// SemaRef and the provided parameters.
14516static Expr *makeFloorIVRef(Sema &SemaRef, ArrayRef<VarDecl *> FloorIndVars,
14517 int I, QualType IVTy, DeclRefExpr *OrigCntVar) {
14518 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14519 OrigCntVar->getExprLoc());
14520}
14521
14523 Stmt *AStmt,
14524 SourceLocation StartLoc,
14525 SourceLocation EndLoc) {
14526 ASTContext &Context = getASTContext();
14527 Scope *CurScope = SemaRef.getCurScope();
14528
14529 const auto *SizesClause =
14530 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14531 if (!SizesClause ||
14532 llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; }))
14533 return StmtError();
14534 unsigned NumLoops = SizesClause->getNumSizes();
14535
14536 // Empty statement should only be possible if there already was an error.
14537 if (!AStmt)
14538 return StmtError();
14539
14540 // Verify and diagnose loop nest.
14542 Stmt *Body = nullptr;
14543 SmallVector<SmallVector<Stmt *, 0>, 4> OriginalInits;
14544 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14545 OriginalInits))
14546 return StmtError();
14547
14548 // Delay tiling to when template is completely instantiated.
14549 if (SemaRef.CurContext->isDependentContext())
14550 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14551 NumLoops, AStmt, nullptr, nullptr);
14552
14553 assert(LoopHelpers.size() == NumLoops &&
14554 "Expecting loop iteration space dimensionality to match number of "
14555 "affected loops");
14556 assert(OriginalInits.size() == NumLoops &&
14557 "Expecting loop iteration space dimensionality to match number of "
14558 "affected loops");
14559
14560 // Collect all affected loop statements.
14561 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14562 collectLoopStmts(AStmt, LoopStmts);
14563
14564 SmallVector<Stmt *, 4> PreInits;
14565 CaptureVars CopyTransformer(SemaRef);
14566
14567 // Create iteration variables for the generated loops.
14568 SmallVector<VarDecl *, 4> FloorIndVars;
14569 SmallVector<VarDecl *, 4> TileIndVars;
14570 FloorIndVars.resize(NumLoops);
14571 TileIndVars.resize(NumLoops);
14572 for (unsigned I = 0; I < NumLoops; ++I) {
14573 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14574
14575 assert(LoopHelper.Counters.size() == 1 &&
14576 "Expect single-dimensional loop iteration space");
14577 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14578 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14579 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14580 QualType CntTy = IterVarRef->getType();
14581
14582 // Iteration variable for the floor (i.e. outer) loop.
14583 {
14584 std::string FloorCntName =
14585 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14586 VarDecl *FloorCntDecl =
14587 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14588 FloorIndVars[I] = FloorCntDecl;
14589 }
14590
14591 // Iteration variable for the tile (i.e. inner) loop.
14592 {
14593 std::string TileCntName =
14594 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14595
14596 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14597 // used by the expressions to derive the original iteration variable's
14598 // value from the logical iteration number.
14599 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14600 TileCntDecl->setDeclName(
14601 &SemaRef.PP.getIdentifierTable().get(TileCntName));
14602 TileIndVars[I] = TileCntDecl;
14603 }
14604
14605 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
14606 PreInits);
14607 }
14608
14609 // Once the original iteration values are set, append the innermost body.
14610 Stmt *Inner = Body;
14611
14612 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
14613 SizesClause, CurScope](int I) -> Expr * {
14614 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14615
14616 if (DimTileSizeExpr->containsErrors())
14617 return nullptr;
14618
14619 if (isa<ConstantExpr>(DimTileSizeExpr))
14620 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14621
14622 // When the tile size is not a constant but a variable, it is possible to
14623 // pass non-positive numbers. For instance:
14624 // \code{c}
14625 // int a = 0;
14626 // #pragma omp tile sizes(a)
14627 // for (int i = 0; i < 42; ++i)
14628 // body(i);
14629 // \endcode
14630 // Although there is no meaningful interpretation of the tile size, the body
14631 // should still be executed 42 times to avoid surprises. To preserve the
14632 // invariant that every loop iteration is executed exactly once and not
14633 // cause an infinite loop, apply a minimum tile size of one.
14634 // Build expr:
14635 // \code{c}
14636 // (TS <= 0) ? 1 : TS
14637 // \endcode
14638 QualType DimTy = DimTileSizeExpr->getType();
14639 uint64_t DimWidth = Context.getTypeSize(DimTy);
14641 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14642 IntegerLiteral *One =
14643 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
14644 Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
14645 CurScope, {}, BO_LE,
14646 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
14647 Expr *MinOne = new (Context) ConditionalOperator(
14648 Cond, {}, One, {},
14649 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14651 return MinOne;
14652 };
14653
14654 // Create tile loops from the inside to the outside.
14655 for (int I = NumLoops - 1; I >= 0; --I) {
14656 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14657 Expr *NumIterations = LoopHelper.NumIterations;
14658 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14659 QualType IVTy = NumIterations->getType();
14660 Stmt *LoopStmt = LoopStmts[I];
14661
14662 // Commonly used variables. One of the constraints of an AST is that every
14663 // node object must appear at most once, hence we define a lambda that
14664 // creates a new AST node at every use.
14665 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
14666 OrigCntVar]() {
14667 return buildDeclRefExpr(SemaRef, TileIndVars[I], IVTy,
14668 OrigCntVar->getExprLoc());
14669 };
14670
14671 // For init-statement: auto .tile.iv = .floor.iv
14672 SemaRef.AddInitializerToDecl(
14673 TileIndVars[I],
14674 SemaRef
14675 .DefaultLvalueConversion(
14676 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
14677 .get(),
14678 /*DirectInit=*/false);
14679 Decl *CounterDecl = TileIndVars[I];
14680 StmtResult InitStmt = new (Context)
14681 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14682 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14683 if (!InitStmt.isUsable())
14684 return StmtError();
14685
14686 // For cond-expression:
14687 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
14688 Expr *DimTileSize = MakeDimTileSize(I);
14689 if (!DimTileSize)
14690 return StmtError();
14691 ExprResult EndOfTile = SemaRef.BuildBinOp(
14692 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14693 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14694 DimTileSize);
14695 if (!EndOfTile.isUsable())
14696 return StmtError();
14697 ExprResult IsPartialTile =
14698 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14699 NumIterations, EndOfTile.get());
14700 if (!IsPartialTile.isUsable())
14701 return StmtError();
14702 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
14703 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14704 IsPartialTile.get(), NumIterations, EndOfTile.get());
14705 if (!MinTileAndIterSpace.isUsable())
14706 return StmtError();
14707 ExprResult CondExpr =
14708 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14709 MakeTileIVRef(), MinTileAndIterSpace.get());
14710 if (!CondExpr.isUsable())
14711 return StmtError();
14712
14713 // For incr-statement: ++.tile.iv
14714 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14715 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
14716 if (!IncrStmt.isUsable())
14717 return StmtError();
14718
14719 // Statements to set the original iteration variable's value from the
14720 // logical iteration number.
14721 // Generated for loop is:
14722 // \code
14723 // Original_for_init;
14724 // for (auto .tile.iv = .floor.iv;
14725 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
14726 // ++.tile.iv) {
14727 // Original_Body;
14728 // Original_counter_update;
14729 // }
14730 // \endcode
14731 // FIXME: If the innermost body is an loop itself, inserting these
14732 // statements stops it being recognized as a perfectly nested loop (e.g.
14733 // for applying tiling again). If this is the case, sink the expressions
14734 // further into the inner loop.
14735 SmallVector<Stmt *, 4> BodyParts;
14736 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14737 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14738 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14739 BodyParts.push_back(Inner);
14740 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
14741 Inner->getBeginLoc(), Inner->getEndLoc());
14742 Inner = new (Context)
14743 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14744 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14745 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14746 }
14747
14748 // Create floor loops from the inside to the outside.
14749 for (int I = NumLoops - 1; I >= 0; --I) {
14750 auto &LoopHelper = LoopHelpers[I];
14751 Expr *NumIterations = LoopHelper.NumIterations;
14752 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14753 QualType IVTy = NumIterations->getType();
14754
14755 // For init-statement: auto .floor.iv = 0
14756 SemaRef.AddInitializerToDecl(
14757 FloorIndVars[I],
14758 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14759 /*DirectInit=*/false);
14760 Decl *CounterDecl = FloorIndVars[I];
14761 StmtResult InitStmt = new (Context)
14762 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14763 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14764 if (!InitStmt.isUsable())
14765 return StmtError();
14766
14767 // For cond-expression: .floor.iv < NumIterations
14768 ExprResult CondExpr = SemaRef.BuildBinOp(
14769 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14770 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14771 NumIterations);
14772 if (!CondExpr.isUsable())
14773 return StmtError();
14774
14775 // For incr-statement: .floor.iv += DimTileSize
14776 Expr *DimTileSize = MakeDimTileSize(I);
14777 if (!DimTileSize)
14778 return StmtError();
14779 ExprResult IncrStmt = SemaRef.BuildBinOp(
14780 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
14781 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14782 DimTileSize);
14783 if (!IncrStmt.isUsable())
14784 return StmtError();
14785
14786 Inner = new (Context)
14787 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14788 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14789 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14790 }
14791
14792 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
14793 AStmt, Inner,
14794 buildPreInits(Context, PreInits));
14795}
14796
14798 Stmt *AStmt,
14799 SourceLocation StartLoc,
14800 SourceLocation EndLoc) {
14801 ASTContext &Context = getASTContext();
14802 Scope *CurScope = SemaRef.getCurScope();
14803
14804 const auto *SizesClause =
14805 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14806 if (!SizesClause ||
14807 llvm::any_of(SizesClause->getSizesRefs(), [](const Expr *SizeExpr) {
14808 return !SizeExpr || SizeExpr->containsErrors();
14809 }))
14810 return StmtError();
14811 unsigned NumLoops = SizesClause->getNumSizes();
14812
14813 // Empty statement should only be possible if there already was an error.
14814 if (!AStmt)
14815 return StmtError();
14816
14817 // Verify and diagnose loop nest.
14819 Stmt *Body = nullptr;
14820 SmallVector<SmallVector<Stmt *, 0>, 4> OriginalInits;
14821 if (!checkTransformableLoopNest(OMPD_stripe, AStmt, NumLoops, LoopHelpers,
14822 Body, OriginalInits))
14823 return StmtError();
14824
14825 // Delay striping to when template is completely instantiated.
14826 if (SemaRef.CurContext->isDependentContext())
14827 return OMPStripeDirective::Create(Context, StartLoc, EndLoc, Clauses,
14828 NumLoops, AStmt, nullptr, nullptr);
14829
14830 assert(LoopHelpers.size() == NumLoops &&
14831 "Expecting loop iteration space dimensionality to match number of "
14832 "affected loops");
14833 assert(OriginalInits.size() == NumLoops &&
14834 "Expecting loop iteration space dimensionality to match number of "
14835 "affected loops");
14836
14837 // Collect all affected loop statements.
14838 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14839 collectLoopStmts(AStmt, LoopStmts);
14840
14841 SmallVector<Stmt *, 4> PreInits;
14842 CaptureVars CopyTransformer(SemaRef);
14843
14844 // Create iteration variables for the generated loops.
14845 SmallVector<VarDecl *, 4> FloorIndVars;
14846 SmallVector<VarDecl *, 4> StripeIndVars;
14847 FloorIndVars.resize(NumLoops);
14848 StripeIndVars.resize(NumLoops);
14849 for (unsigned I : llvm::seq<unsigned>(NumLoops)) {
14850 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14851
14852 assert(LoopHelper.Counters.size() == 1 &&
14853 "Expect single-dimensional loop iteration space");
14854 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14855 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14856 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14857 QualType CntTy = IterVarRef->getType();
14858
14859 // Iteration variable for the stripe (i.e. outer) loop.
14860 {
14861 std::string FloorCntName =
14862 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14863 VarDecl *FloorCntDecl =
14864 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14865 FloorIndVars[I] = FloorCntDecl;
14866 }
14867
14868 // Iteration variable for the stripe (i.e. inner) loop.
14869 {
14870 std::string StripeCntName =
14871 (Twine(".stripe_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14872
14873 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14874 // used by the expressions to derive the original iteration variable's
14875 // value from the logical iteration number.
14876 auto *StripeCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14877 StripeCntDecl->setDeclName(
14878 &SemaRef.PP.getIdentifierTable().get(StripeCntName));
14879 StripeIndVars[I] = StripeCntDecl;
14880 }
14881
14882 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
14883 PreInits);
14884 }
14885
14886 // Once the original iteration values are set, append the innermost body.
14887 Stmt *Inner = Body;
14888
14889 auto MakeDimStripeSize = [&](int I) -> Expr * {
14890 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
14891 if (isa<ConstantExpr>(DimStripeSizeExpr))
14892 return AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr));
14893
14894 // When the stripe 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 stripe sizes(a)
14899 // for (int i = 0; i < 42; ++i)
14900 // body(i);
14901 // \endcode
14902 // Although there is no meaningful interpretation of the stripe size, the
14903 // body should still be executed 42 times to avoid surprises. To preserve
14904 // the invariant that every loop iteration is executed exactly once and not
14905 // cause an infinite loop, apply a minimum stripe size of one.
14906 // Build expr:
14907 // \code{c}
14908 // (TS <= 0) ? 1 : TS
14909 // \endcode
14910 QualType DimTy = DimStripeSizeExpr->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(DimStripeSizeExpr)), Zero));
14919 Expr *MinOne = new (Context) ConditionalOperator(
14920 Cond, {}, One, {},
14921 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), DimTy,
14923 return MinOne;
14924 };
14925
14926 // Create stripe 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 // For init-statement: auto .stripe.iv = .floor.iv
14935 SemaRef.AddInitializerToDecl(
14936 StripeIndVars[I],
14937 SemaRef
14938 .DefaultLvalueConversion(
14939 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
14940 .get(),
14941 /*DirectInit=*/false);
14942 Decl *CounterDecl = StripeIndVars[I];
14943 StmtResult InitStmt = new (Context)
14944 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14945 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14946 if (!InitStmt.isUsable())
14947 return StmtError();
14948
14949 // For cond-expression:
14950 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations)
14951 ExprResult EndOfStripe = SemaRef.BuildBinOp(
14952 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14953 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14954 MakeDimStripeSize(I));
14955 if (!EndOfStripe.isUsable())
14956 return StmtError();
14957 ExprResult IsPartialStripe =
14958 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14959 NumIterations, EndOfStripe.get());
14960 if (!IsPartialStripe.isUsable())
14961 return StmtError();
14962 ExprResult MinStripeAndIterSpace = SemaRef.ActOnConditionalOp(
14963 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14964 IsPartialStripe.get(), NumIterations, EndOfStripe.get());
14965 if (!MinStripeAndIterSpace.isUsable())
14966 return StmtError();
14967 ExprResult CondExpr = SemaRef.BuildBinOp(
14968 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14969 makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar),
14970 MinStripeAndIterSpace.get());
14971 if (!CondExpr.isUsable())
14972 return StmtError();
14973
14974 // For incr-statement: ++.stripe.iv
14975 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14976 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc,
14977 makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar));
14978 if (!IncrStmt.isUsable())
14979 return StmtError();
14980
14981 // Statements to set the original iteration variable's value from the
14982 // logical iteration number.
14983 // Generated for loop is:
14984 // \code
14985 // Original_for_init;
14986 // for (auto .stripe.iv = .floor.iv;
14987 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations);
14988 // ++.stripe.iv) {
14989 // Original_Body;
14990 // Original_counter_update;
14991 // }
14992 // \endcode
14993 // FIXME: If the innermost body is a loop itself, inserting these
14994 // statements stops it being recognized as a perfectly nested loop (e.g.
14995 // for applying another loop transformation). If this is the case, sink the
14996 // expressions further into the inner loop.
14997 SmallVector<Stmt *, 4> BodyParts;
14998 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14999 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15000 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15001 BodyParts.push_back(Inner);
15002 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15003 Inner->getBeginLoc(), Inner->getEndLoc());
15004 Inner = new (Context)
15005 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15006 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15007 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15008 }
15009
15010 // Create grid loops from the inside to the outside.
15011 for (int I = NumLoops - 1; I >= 0; --I) {
15012 auto &LoopHelper = LoopHelpers[I];
15013 Expr *NumIterations = LoopHelper.NumIterations;
15014 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15015 QualType IVTy = NumIterations->getType();
15016
15017 // For init-statement: auto .grid.iv = 0
15018 SemaRef.AddInitializerToDecl(
15019 FloorIndVars[I],
15020 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15021 /*DirectInit=*/false);
15022 Decl *CounterDecl = FloorIndVars[I];
15023 StmtResult InitStmt = new (Context)
15024 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15025 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15026 if (!InitStmt.isUsable())
15027 return StmtError();
15028
15029 // For cond-expression: .floor.iv < NumIterations
15030 ExprResult CondExpr = SemaRef.BuildBinOp(
15031 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15032 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15033 NumIterations);
15034 if (!CondExpr.isUsable())
15035 return StmtError();
15036
15037 // For incr-statement: .floor.iv += DimStripeSize
15038 ExprResult IncrStmt = SemaRef.BuildBinOp(
15039 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15040 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15041 MakeDimStripeSize(I));
15042 if (!IncrStmt.isUsable())
15043 return StmtError();
15044
15045 Inner = new (Context)
15046 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15047 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15048 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15049 }
15050
15051 return OMPStripeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15052 NumLoops, AStmt, Inner,
15053 buildPreInits(Context, PreInits));
15054}
15055
15057 Stmt *AStmt,
15058 SourceLocation StartLoc,
15059 SourceLocation EndLoc) {
15060 ASTContext &Context = getASTContext();
15061 Scope *CurScope = SemaRef.getCurScope();
15062 // Empty statement should only be possible if there already was an error.
15063 if (!AStmt)
15064 return StmtError();
15065
15067 {OMPC_partial, OMPC_full}))
15068 return StmtError();
15069
15070 const OMPFullClause *FullClause =
15071 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15072 const OMPPartialClause *PartialClause =
15073 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15074 assert(!(FullClause && PartialClause) &&
15075 "mutual exclusivity must have been checked before");
15076
15077 constexpr unsigned NumLoops = 1;
15078 Stmt *Body = nullptr;
15080 NumLoops);
15081 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
15082 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15083 Body, OriginalInits))
15084 return StmtError();
15085
15086 unsigned NumGeneratedTopLevelLoops = PartialClause ? 1 : 0;
15087
15088 // Delay unrolling to when template is completely instantiated.
15089 if (SemaRef.CurContext->isDependentContext())
15090 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15091 NumGeneratedTopLevelLoops, nullptr,
15092 nullptr);
15093
15094 assert(LoopHelpers.size() == NumLoops &&
15095 "Expecting a single-dimensional loop iteration space");
15096 assert(OriginalInits.size() == NumLoops &&
15097 "Expecting a single-dimensional loop iteration space");
15098 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15099
15100 if (FullClause) {
15102 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
15103 /*SuppressExprDiags=*/true)
15104 .isUsable()) {
15105 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
15106 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
15107 << "#pragma omp unroll full";
15108 return StmtError();
15109 }
15110 }
15111
15112 // The generated loop may only be passed to other loop-associated directive
15113 // when a partial clause is specified. Without the requirement it is
15114 // sufficient to generate loop unroll metadata at code-generation.
15115 if (NumGeneratedTopLevelLoops == 0)
15116 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15117 NumGeneratedTopLevelLoops, nullptr,
15118 nullptr);
15119
15120 // Otherwise, we need to provide a de-sugared/transformed AST that can be
15121 // associated with another loop directive.
15122 //
15123 // The canonical loop analysis return by checkTransformableLoopNest assumes
15124 // the following structure to be the same loop without transformations or
15125 // directives applied: \code OriginalInits; LoopHelper.PreInits;
15126 // LoopHelper.Counters;
15127 // for (; IV < LoopHelper.NumIterations; ++IV) {
15128 // LoopHelper.Updates;
15129 // Body;
15130 // }
15131 // \endcode
15132 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
15133 // and referenced by LoopHelper.IterationVarRef.
15134 //
15135 // The unrolling directive transforms this into the following loop:
15136 // \code
15137 // OriginalInits; \
15138 // LoopHelper.PreInits; > NewPreInits
15139 // LoopHelper.Counters; /
15140 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
15141 // #pragma clang loop unroll_count(Factor)
15142 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
15143 // {
15144 // LoopHelper.Updates;
15145 // Body;
15146 // }
15147 // }
15148 // \endcode
15149 // where UIV is a new logical iteration counter. IV must be the same VarDecl
15150 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
15151 // references it. If the partially unrolled loop is associated with another
15152 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
15153 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
15154 // OpenMP canonical loop. The inner loop is not an associable canonical loop
15155 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
15156 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
15157 // property of the OMPLoopBasedDirective instead of statements in
15158 // CompoundStatement. This is to allow the loop to become a non-outermost loop
15159 // of a canonical loop nest where these PreInits are emitted before the
15160 // outermost directive.
15161
15162 // Find the loop statement.
15163 Stmt *LoopStmt = nullptr;
15164 collectLoopStmts(AStmt, {LoopStmt});
15165
15166 // Determine the PreInit declarations.
15167 SmallVector<Stmt *, 4> PreInits;
15168 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15169
15170 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15171 QualType IVTy = IterationVarRef->getType();
15172 assert(LoopHelper.Counters.size() == 1 &&
15173 "Expecting a single-dimensional loop iteration space");
15174 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15175
15176 // Determine the unroll factor.
15177 uint64_t Factor;
15178 SourceLocation FactorLoc;
15179 if (Expr *FactorVal = PartialClause->getFactor();
15180 FactorVal && !FactorVal->containsErrors()) {
15181 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15182 FactorLoc = FactorVal->getExprLoc();
15183 } else {
15184 // TODO: Use a better profitability model.
15185 Factor = 2;
15186 }
15187 assert(Factor > 0 && "Expected positive unroll factor");
15188 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
15190 getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor),
15191 IVTy, FactorLoc);
15192 };
15193
15194 // Iteration variable SourceLocations.
15195 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15196 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15197 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15198
15199 // Internal variable names.
15200 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15201 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
15202 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
15203
15204 // Create the iteration variable for the unrolled loop.
15205 VarDecl *OuterIVDecl =
15206 buildVarDecl(SemaRef, {}, IVTy, OuterIVName, nullptr, OrigVar);
15207 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
15208 return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc);
15209 };
15210
15211 // Iteration variable for the inner loop: Reuse the iteration variable created
15212 // by checkOpenMPLoop.
15213 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15214 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(InnerIVName));
15215 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
15216 return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc);
15217 };
15218
15219 // Make a copy of the NumIterations expression for each use: By the AST
15220 // constraints, every expression object in a DeclContext must be unique.
15221 CaptureVars CopyTransformer(SemaRef);
15222 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15223 return AssertSuccess(
15224 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15225 };
15226
15227 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15228 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(MakeOuterRef());
15229 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(),
15230 /*DirectInit=*/false);
15231 StmtResult InnerInit = new (Context)
15232 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15233 if (!InnerInit.isUsable())
15234 return StmtError();
15235
15236 // Inner For cond-expression:
15237 // \code
15238 // .unroll_inner.iv < .unrolled.iv + Factor &&
15239 // .unroll_inner.iv < NumIterations
15240 // \endcode
15241 // This conjunction of two conditions allows ScalarEvolution to derive the
15242 // maximum trip count of the inner loop.
15243 ExprResult EndOfTile =
15244 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15245 MakeOuterRef(), MakeFactorExpr());
15246 if (!EndOfTile.isUsable())
15247 return StmtError();
15248 ExprResult InnerCond1 =
15249 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15250 MakeInnerRef(), EndOfTile.get());
15251 if (!InnerCond1.isUsable())
15252 return StmtError();
15253 ExprResult InnerCond2 =
15254 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15255 MakeInnerRef(), MakeNumIterations());
15256 if (!InnerCond2.isUsable())
15257 return StmtError();
15258 ExprResult InnerCond =
15259 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15260 InnerCond1.get(), InnerCond2.get());
15261 if (!InnerCond.isUsable())
15262 return StmtError();
15263
15264 // Inner For incr-statement: ++.unroll_inner.iv
15265 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
15266 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
15267 if (!InnerIncr.isUsable())
15268 return StmtError();
15269
15270 // Inner For statement.
15271 SmallVector<Stmt *> InnerBodyStmts;
15272 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15273 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15274 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15275 InnerBodyStmts.push_back(Body);
15276 CompoundStmt *InnerBody =
15278 Body->getBeginLoc(), Body->getEndLoc());
15279 ForStmt *InnerFor = new (Context)
15280 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15281 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15282 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15283
15284 // Unroll metadata for the inner loop.
15285 // This needs to take into account the remainder portion of the unrolled loop,
15286 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15287 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15288 // the maximum trip count, which will also generate a remainder loop. Just
15289 // `unroll(enable)` (which could have been useful if the user has not
15290 // specified a concrete factor; even though the outer loop cannot be
15291 // influenced anymore, would avoid more code bloat than necessary) will refuse
15292 // the loop because "Won't unroll; remainder loop could not be generated when
15293 // assuming runtime trip count". Even if it did work, it must not choose a
15294 // larger unroll factor than the maximum loop length, or it would always just
15295 // execute the remainder loop.
15296 LoopHintAttr *UnrollHintAttr =
15297 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15298 LoopHintAttr::Numeric, MakeFactorExpr());
15299 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
15300 getASTContext(), StartLoc, {UnrollHintAttr}, InnerFor);
15301
15302 // Outer For init-statement: auto .unrolled.iv = 0
15303 SemaRef.AddInitializerToDecl(
15304 OuterIVDecl,
15305 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15306 /*DirectInit=*/false);
15307 StmtResult OuterInit = new (Context)
15308 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15309 if (!OuterInit.isUsable())
15310 return StmtError();
15311
15312 // Outer For cond-expression: .unrolled.iv < NumIterations
15313 ExprResult OuterConde =
15314 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15315 MakeOuterRef(), MakeNumIterations());
15316 if (!OuterConde.isUsable())
15317 return StmtError();
15318
15319 // Outer For incr-statement: .unrolled.iv += Factor
15320 ExprResult OuterIncr =
15321 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15322 MakeOuterRef(), MakeFactorExpr());
15323 if (!OuterIncr.isUsable())
15324 return StmtError();
15325
15326 // Outer For statement.
15327 ForStmt *OuterFor = new (Context)
15328 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15329 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15330 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15331
15332 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15333 NumGeneratedTopLevelLoops, OuterFor,
15334 buildPreInits(Context, PreInits));
15335}
15336
15338 SourceLocation StartLoc,
15339 SourceLocation EndLoc) {
15340 ASTContext &Context = getASTContext();
15341 Scope *CurScope = SemaRef.getCurScope();
15342
15343 // Empty statement should only be possible if there already was an error.
15344 if (!AStmt)
15345 return StmtError();
15346
15347 constexpr unsigned NumLoops = 1;
15348 Stmt *Body = nullptr;
15350 NumLoops);
15351 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
15352 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
15353 Body, OriginalInits))
15354 return StmtError();
15355
15356 // Delay applying the transformation to when template is completely
15357 // instantiated.
15358 if (SemaRef.CurContext->isDependentContext())
15359 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
15360 NumLoops, nullptr, nullptr);
15361
15362 assert(LoopHelpers.size() == NumLoops &&
15363 "Expecting a single-dimensional loop iteration space");
15364 assert(OriginalInits.size() == NumLoops &&
15365 "Expecting a single-dimensional loop iteration space");
15366 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15367
15368 // Find the loop statement.
15369 Stmt *LoopStmt = nullptr;
15370 collectLoopStmts(AStmt, {LoopStmt});
15371
15372 // Determine the PreInit declarations.
15373 SmallVector<Stmt *> PreInits;
15374 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15375
15376 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15377 QualType IVTy = IterationVarRef->getType();
15378 uint64_t IVWidth = Context.getTypeSize(IVTy);
15379 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15380
15381 // Iteration variable SourceLocations.
15382 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15383 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15384 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15385
15386 // Locations pointing to the transformation.
15387 SourceLocation TransformLoc = StartLoc;
15388 SourceLocation TransformLocBegin = StartLoc;
15389 SourceLocation TransformLocEnd = EndLoc;
15390
15391 // Internal variable names.
15392 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15393 SmallString<64> ForwardIVName(".forward.iv.");
15394 ForwardIVName += OrigVarName;
15395 SmallString<64> ReversedIVName(".reversed.iv.");
15396 ReversedIVName += OrigVarName;
15397
15398 // LoopHelper.Updates will read the logical iteration number from
15399 // LoopHelper.IterationVarRef, compute the value of the user loop counter of
15400 // that logical iteration from it, then assign it to the user loop counter
15401 // variable. We cannot directly use LoopHelper.IterationVarRef as the
15402 // induction variable of the generated loop because it may cause an underflow:
15403 // \code{.c}
15404 // for (unsigned i = 0; i < n; ++i)
15405 // body(i);
15406 // \endcode
15407 //
15408 // Naive reversal:
15409 // \code{.c}
15410 // for (unsigned i = n-1; i >= 0; --i)
15411 // body(i);
15412 // \endcode
15413 //
15414 // Instead, we introduce a new iteration variable representing the logical
15415 // iteration counter of the original loop, convert it to the logical iteration
15416 // number of the reversed loop, then let LoopHelper.Updates compute the user's
15417 // loop iteration variable from it.
15418 // \code{.cpp}
15419 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
15420 // auto .reversed.iv = n - .forward.iv - 1;
15421 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates
15422 // body(i); // Body
15423 // }
15424 // \endcode
15425
15426 // Subexpressions with more than one use. One of the constraints of an AST is
15427 // that every node object must appear at most once, hence we define a lambda
15428 // that creates a new AST node at every use.
15429 CaptureVars CopyTransformer(SemaRef);
15430 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15431 return AssertSuccess(
15432 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15433 };
15434
15435 // Create the iteration variable for the forward loop (from 0 to n-1).
15436 VarDecl *ForwardIVDecl =
15437 buildVarDecl(SemaRef, {}, IVTy, ForwardIVName, nullptr, OrigVar);
15438 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
15439 OrigVarLoc]() {
15440 return buildDeclRefExpr(SemaRef, ForwardIVDecl, IVTy, OrigVarLoc);
15441 };
15442
15443 // Iteration variable for the reversed induction variable (from n-1 downto 0):
15444 // Reuse the iteration variable created by checkOpenMPLoop.
15445 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15446 ReversedIVDecl->setDeclName(
15447 &SemaRef.PP.getIdentifierTable().get(ReversedIVName));
15448
15449 // For init-statement:
15450 // \code{.cpp}
15451 // auto .forward.iv = 0;
15452 // \endcode
15453 auto *Zero = IntegerLiteral::Create(Context, llvm::APInt::getZero(IVWidth),
15454 ForwardIVDecl->getType(), OrigVarLoc);
15455 SemaRef.AddInitializerToDecl(ForwardIVDecl, Zero, /*DirectInit=*/false);
15456 StmtResult Init = new (Context)
15457 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15458 if (!Init.isUsable())
15459 return StmtError();
15460
15461 // Forward iv cond-expression:
15462 // \code{.cpp}
15463 // .forward.iv < MakeNumIterations()
15464 // \endcode
15466 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15467 MakeForwardRef(), MakeNumIterations());
15468 if (!Cond.isUsable())
15469 return StmtError();
15470
15471 // Forward incr-statement:
15472 // \code{.c}
15473 // ++.forward.iv
15474 // \endcode
15475 ExprResult Incr = SemaRef.BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
15476 UO_PreInc, MakeForwardRef());
15477 if (!Incr.isUsable())
15478 return StmtError();
15479
15480 // Reverse the forward-iv:
15481 // \code{.cpp}
15482 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
15483 // \endcode
15484 auto *One = IntegerLiteral::Create(Context, llvm::APInt(IVWidth, 1), IVTy,
15485 TransformLoc);
15486 ExprResult Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub,
15487 MakeNumIterations(), One);
15488 if (!Minus.isUsable())
15489 return StmtError();
15490 Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.get(),
15491 MakeForwardRef());
15492 if (!Minus.isUsable())
15493 return StmtError();
15494 StmtResult InitReversed = new (Context) DeclStmt(
15495 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
15496 if (!InitReversed.isUsable())
15497 return StmtError();
15498 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.get(),
15499 /*DirectInit=*/false);
15500
15501 // The new loop body.
15502 SmallVector<Stmt *, 4> BodyStmts;
15503 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
15504 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
15505 BodyStmts.push_back(InitReversed.get());
15506 llvm::append_range(BodyStmts, LoopHelper.Updates);
15507 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15508 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15509 BodyStmts.push_back(Body);
15510 auto *ReversedBody =
15511 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
15512 Body->getBeginLoc(), Body->getEndLoc());
15513
15514 // Finally create the reversed For-statement.
15515 auto *ReversedFor = new (Context)
15516 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
15517 ReversedBody, LoopHelper.Init->getBeginLoc(),
15518 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15519 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt, NumLoops,
15520 ReversedFor,
15521 buildPreInits(Context, PreInits));
15522}
15523
15525 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15526 SourceLocation EndLoc) {
15527 ASTContext &Context = getASTContext();
15528 DeclContext *CurContext = SemaRef.CurContext;
15529 Scope *CurScope = SemaRef.getCurScope();
15530
15531 // Empty statement should only be possible if there already was an error.
15532 if (!AStmt)
15533 return StmtError();
15534
15535 // interchange without permutation clause swaps two loops.
15536 const OMPPermutationClause *PermutationClause =
15537 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
15538 size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2;
15539
15540 // Verify and diagnose loop nest.
15542 Stmt *Body = nullptr;
15543 SmallVector<SmallVector<Stmt *, 0>, 2> OriginalInits;
15544 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
15545 LoopHelpers, Body, OriginalInits))
15546 return StmtError();
15547
15548 // Delay interchange to when template is completely instantiated.
15549 if (CurContext->isDependentContext())
15550 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15551 NumLoops, AStmt, nullptr, nullptr);
15552
15553 // An invalid expression in the permutation clause is set to nullptr in
15554 // ActOnOpenMPPermutationClause.
15555 if (PermutationClause &&
15556 llvm::is_contained(PermutationClause->getArgsRefs(), nullptr))
15557 return StmtError();
15558
15559 assert(LoopHelpers.size() == NumLoops &&
15560 "Expecting loop iteration space dimensionaly to match number of "
15561 "affected loops");
15562 assert(OriginalInits.size() == NumLoops &&
15563 "Expecting loop iteration space dimensionaly to match number of "
15564 "affected loops");
15565
15566 // Decode the permutation clause.
15567 SmallVector<uint64_t, 2> Permutation;
15568 if (!PermutationClause) {
15569 Permutation = {1, 0};
15570 } else {
15571 ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs();
15572 llvm::BitVector Flags(PermArgs.size());
15573 for (Expr *PermArg : PermArgs) {
15574 std::optional<llvm::APSInt> PermCstExpr =
15575 PermArg->getIntegerConstantExpr(Context);
15576 if (!PermCstExpr)
15577 continue;
15578 uint64_t PermInt = PermCstExpr->getZExtValue();
15579 assert(1 <= PermInt && PermInt <= NumLoops &&
15580 "Must be a permutation; diagnostic emitted in "
15581 "ActOnOpenMPPermutationClause");
15582 if (Flags[PermInt - 1]) {
15583 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
15584 Diag(PermArg->getExprLoc(),
15585 diag::err_omp_interchange_permutation_value_repeated)
15586 << PermInt << ExprRange;
15587 continue;
15588 }
15589 Flags[PermInt - 1] = true;
15590
15591 Permutation.push_back(PermInt - 1);
15592 }
15593
15594 if (Permutation.size() != NumLoops)
15595 return StmtError();
15596 }
15597
15598 // Nothing to transform with trivial permutation.
15599 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](auto P) {
15600 auto [Idx, Arg] = P;
15601 return Idx == Arg;
15602 }))
15603 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15604 NumLoops, AStmt, AStmt, nullptr);
15605
15606 // Find the affected loops.
15607 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15608 collectLoopStmts(AStmt, LoopStmts);
15609
15610 // Collect pre-init statements on the order before the permuation.
15611 SmallVector<Stmt *> PreInits;
15612 for (auto I : llvm::seq<int>(NumLoops)) {
15613 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15614
15615 assert(LoopHelper.Counters.size() == 1 &&
15616 "Single-dimensional loop iteration space expected");
15617
15618 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
15619 PreInits);
15620 }
15621
15622 SmallVector<VarDecl *> PermutedIndVars(NumLoops);
15623 CaptureVars CopyTransformer(SemaRef);
15624
15625 // Create the permuted loops from the inside to the outside of the
15626 // interchanged loop nest. Body of the innermost new loop is the original
15627 // innermost body.
15628 Stmt *Inner = Body;
15629 for (auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
15630 // Get the original loop that belongs to this new position.
15631 uint64_t SourceIdx = Permutation[TargetIdx];
15632 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
15633 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15634 assert(SourceHelper.Counters.size() == 1 &&
15635 "Single-dimensional loop iteration space expected");
15636 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.Counters.front());
15637
15638 // Normalized loop counter variable: From 0 to n-1, always an integer type.
15639 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(SourceHelper.IterationVarRef);
15640 QualType IVTy = IterVarRef->getType();
15641 assert(IVTy->isIntegerType() &&
15642 "Expected the logical iteration counter to be an integer");
15643
15644 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15645 SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
15646
15647 // Make a copy of the NumIterations expression for each use: By the AST
15648 // constraints, every expression object in a DeclContext must be unique.
15649 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
15650 return AssertSuccess(
15651 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
15652 };
15653
15654 // Iteration variable for the permuted loop. Reuse the one from
15655 // checkOpenMPLoop which will also be used to update the original loop
15656 // variable.
15657 SmallString<64> PermutedCntName(".permuted_");
15658 PermutedCntName.append({llvm::utostr(TargetIdx), ".iv.", OrigVarName});
15659 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15660 PermutedCntDecl->setDeclName(
15661 &SemaRef.PP.getIdentifierTable().get(PermutedCntName));
15662 PermutedIndVars[TargetIdx] = PermutedCntDecl;
15663 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
15664 return buildDeclRefExpr(SemaRef, PermutedCntDecl, IVTy, OrigVarLoc);
15665 };
15666
15667 // For init-statement:
15668 // \code
15669 // auto .permuted_{target}.iv = 0
15670 // \endcode
15671 ExprResult Zero = SemaRef.ActOnIntegerConstant(OrigVarLoc, 0);
15672 if (!Zero.isUsable())
15673 return StmtError();
15674 SemaRef.AddInitializerToDecl(PermutedCntDecl, Zero.get(),
15675 /*DirectInit=*/false);
15676 StmtResult InitStmt = new (Context)
15677 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
15678 OrigCntVar->getEndLoc());
15679 if (!InitStmt.isUsable())
15680 return StmtError();
15681
15682 // For cond-expression:
15683 // \code
15684 // .permuted_{target}.iv < MakeNumIterations()
15685 // \endcode
15686 ExprResult CondExpr =
15687 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
15688 MakePermutedRef(), MakeNumIterations());
15689 if (!CondExpr.isUsable())
15690 return StmtError();
15691
15692 // For incr-statement:
15693 // \code
15694 // ++.tile.iv
15695 // \endcode
15696 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15697 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
15698 if (!IncrStmt.isUsable())
15699 return StmtError();
15700
15701 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
15702 SourceHelper.Updates.end());
15703 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
15704 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15705 BodyParts.push_back(Inner);
15706 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15707 Inner->getBeginLoc(), Inner->getEndLoc());
15708 Inner = new (Context) ForStmt(
15709 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
15710 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
15711 SourceHelper.Inc->getEndLoc());
15712 }
15713
15714 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15715 NumLoops, AStmt, Inner,
15716 buildPreInits(Context, PreInits));
15717}
15718
15720 Expr *Expr,
15721 SourceLocation StartLoc,
15722 SourceLocation LParenLoc,
15723 SourceLocation EndLoc) {
15724 OMPClause *Res = nullptr;
15725 switch (Kind) {
15726 case OMPC_final:
15727 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
15728 break;
15729 case OMPC_safelen:
15730 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
15731 break;
15732 case OMPC_simdlen:
15733 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
15734 break;
15735 case OMPC_allocator:
15736 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
15737 break;
15738 case OMPC_collapse:
15739 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
15740 break;
15741 case OMPC_ordered:
15742 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
15743 break;
15744 case OMPC_priority:
15745 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
15746 break;
15747 case OMPC_hint:
15748 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
15749 break;
15750 case OMPC_depobj:
15751 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
15752 break;
15753 case OMPC_detach:
15754 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
15755 break;
15756 case OMPC_novariants:
15757 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
15758 break;
15759 case OMPC_nocontext:
15760 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
15761 break;
15762 case OMPC_filter:
15763 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
15764 break;
15765 case OMPC_partial:
15766 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
15767 break;
15768 case OMPC_message:
15769 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
15770 break;
15771 case OMPC_align:
15772 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
15773 break;
15774 case OMPC_ompx_dyn_cgroup_mem:
15775 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
15776 break;
15777 case OMPC_holds:
15778 Res = ActOnOpenMPHoldsClause(Expr, StartLoc, LParenLoc, EndLoc);
15779 break;
15780 case OMPC_grainsize:
15781 case OMPC_num_tasks:
15782 case OMPC_num_threads:
15783 case OMPC_device:
15784 case OMPC_if:
15785 case OMPC_default:
15786 case OMPC_proc_bind:
15787 case OMPC_schedule:
15788 case OMPC_private:
15789 case OMPC_firstprivate:
15790 case OMPC_lastprivate:
15791 case OMPC_shared:
15792 case OMPC_reduction:
15793 case OMPC_task_reduction:
15794 case OMPC_in_reduction:
15795 case OMPC_linear:
15796 case OMPC_aligned:
15797 case OMPC_copyin:
15798 case OMPC_copyprivate:
15799 case OMPC_nowait:
15800 case OMPC_untied:
15801 case OMPC_mergeable:
15802 case OMPC_threadprivate:
15803 case OMPC_groupprivate:
15804 case OMPC_sizes:
15805 case OMPC_allocate:
15806 case OMPC_flush:
15807 case OMPC_read:
15808 case OMPC_write:
15809 case OMPC_update:
15810 case OMPC_capture:
15811 case OMPC_compare:
15812 case OMPC_seq_cst:
15813 case OMPC_acq_rel:
15814 case OMPC_acquire:
15815 case OMPC_release:
15816 case OMPC_relaxed:
15817 case OMPC_depend:
15818 case OMPC_threads:
15819 case OMPC_simd:
15820 case OMPC_map:
15821 case OMPC_nogroup:
15822 case OMPC_dist_schedule:
15823 case OMPC_defaultmap:
15824 case OMPC_unknown:
15825 case OMPC_uniform:
15826 case OMPC_to:
15827 case OMPC_from:
15828 case OMPC_use_device_ptr:
15829 case OMPC_use_device_addr:
15830 case OMPC_is_device_ptr:
15831 case OMPC_unified_address:
15832 case OMPC_unified_shared_memory:
15833 case OMPC_reverse_offload:
15834 case OMPC_dynamic_allocators:
15835 case OMPC_atomic_default_mem_order:
15836 case OMPC_self_maps:
15837 case OMPC_device_type:
15838 case OMPC_match:
15839 case OMPC_nontemporal:
15840 case OMPC_order:
15841 case OMPC_at:
15842 case OMPC_severity:
15843 case OMPC_destroy:
15844 case OMPC_inclusive:
15845 case OMPC_exclusive:
15846 case OMPC_uses_allocators:
15847 case OMPC_affinity:
15848 case OMPC_when:
15849 case OMPC_bind:
15850 case OMPC_num_teams:
15851 case OMPC_thread_limit:
15852 default:
15853 llvm_unreachable("Clause is not allowed.");
15854 }
15855 return Res;
15856}
15857
15858// An OpenMP directive such as 'target parallel' has two captured regions:
15859// for the 'target' and 'parallel' respectively. This function returns
15860// the region in which to capture expressions associated with a clause.
15861// A return value of OMPD_unknown signifies that the expression should not
15862// be captured.
15864 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15865 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15866 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
15867 "Invalid directive with CKind-clause");
15868
15869 // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
15870 if (NameModifier != OMPD_unknown &&
15871 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
15872 return OMPD_unknown;
15873
15874 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(DKind);
15875
15876 // [5.2:341:24-30]
15877 // If the clauses have expressions on them, such as for various clauses where
15878 // the argument of the clause is an expression, or lower-bound, length, or
15879 // stride expressions inside array sections (or subscript and stride
15880 // expressions in subscript-triplet for Fortran), or linear-step or alignment
15881 // expressions, the expressions are evaluated immediately before the construct
15882 // to which the clause has been split or duplicated per the above rules
15883 // (therefore inside of the outer leaf constructs). However, the expressions
15884 // inside the num_teams and thread_limit clauses are always evaluated before
15885 // the outermost leaf construct.
15886
15887 // Process special cases first.
15888 switch (CKind) {
15889 case OMPC_if:
15890 switch (DKind) {
15891 case OMPD_teams_loop:
15892 case OMPD_target_teams_loop:
15893 // For [target] teams loop, assume capture region is 'teams' so it's
15894 // available for codegen later to use if/when necessary.
15895 return OMPD_teams;
15896 case OMPD_target_update:
15897 case OMPD_target_enter_data:
15898 case OMPD_target_exit_data:
15899 return OMPD_task;
15900 default:
15901 break;
15902 }
15903 break;
15904 case OMPC_num_teams:
15905 case OMPC_thread_limit:
15906 case OMPC_ompx_dyn_cgroup_mem:
15907 if (Leafs[0] == OMPD_target)
15908 return OMPD_target;
15909 break;
15910 case OMPC_device:
15911 if (Leafs[0] == OMPD_target ||
15912 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
15913 OMPD_target_enter_data, OMPD_target_exit_data},
15914 DKind))
15915 return OMPD_task;
15916 break;
15917 case OMPC_novariants:
15918 case OMPC_nocontext:
15919 if (DKind == OMPD_dispatch)
15920 return OMPD_task;
15921 break;
15922 case OMPC_when:
15923 if (DKind == OMPD_metadirective)
15924 return OMPD_metadirective;
15925 break;
15926 case OMPC_filter:
15927 return OMPD_unknown;
15928 default:
15929 break;
15930 }
15931
15932 // If none of the special cases above applied, and DKind is a capturing
15933 // directive, find the innermost enclosing leaf construct that allows the
15934 // clause, and returns the corresponding capture region.
15935
15936 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
15937 // Find the index in "Leafs" of the last leaf that allows the given
15938 // clause. The search will only include indexes [0, EndIdx).
15939 // EndIdx may be set to the index of the NameModifier, if present.
15940 int InnermostIdx = [&]() {
15941 for (int I = EndIdx - 1; I >= 0; --I) {
15942 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
15943 return I;
15944 }
15945 return -1;
15946 }();
15947
15948 // Find the nearest enclosing capture region.
15950 for (int I = InnermostIdx - 1; I >= 0; --I) {
15951 if (!isOpenMPCapturingDirective(Leafs[I]))
15952 continue;
15953 Regions.clear();
15954 getOpenMPCaptureRegions(Regions, Leafs[I]);
15955 if (Regions[0] != OMPD_unknown)
15956 return Regions.back();
15957 }
15958 return OMPD_unknown;
15959 };
15960
15961 if (isOpenMPCapturingDirective(DKind)) {
15962 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
15963 for (int I = 0, E = Leafs.size(); I != E; ++I) {
15964 if (Leafs[I] == Dir)
15965 return I + 1;
15966 }
15967 return 0;
15968 };
15969
15970 int End = NameModifier == OMPD_unknown ? Leafs.size()
15971 : GetLeafIndex(NameModifier);
15972 return GetEnclosingRegion(End, CKind);
15973 }
15974
15975 return OMPD_unknown;
15976}
15977
15979 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
15980 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
15981 SourceLocation ColonLoc, SourceLocation EndLoc) {
15982 Expr *ValExpr = Condition;
15983 Stmt *HelperValStmt = nullptr;
15984 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15985 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
15986 !Condition->isInstantiationDependent() &&
15987 !Condition->containsUnexpandedParameterPack()) {
15988 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
15989 if (Val.isInvalid())
15990 return nullptr;
15991
15992 ValExpr = Val.get();
15993
15994 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15995 CaptureRegion = getOpenMPCaptureRegionForClause(
15996 DKind, OMPC_if, getLangOpts().OpenMP, NameModifier);
15997 if (CaptureRegion != OMPD_unknown &&
15998 !SemaRef.CurContext->isDependentContext()) {
15999 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16000 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16001 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16002 HelperValStmt = buildPreInits(getASTContext(), Captures);
16003 }
16004 }
16005
16006 return new (getASTContext())
16007 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16008 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16009}
16010
16012 SourceLocation StartLoc,
16013 SourceLocation LParenLoc,
16014 SourceLocation EndLoc) {
16015 Expr *ValExpr = Condition;
16016 Stmt *HelperValStmt = nullptr;
16017 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16018 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16019 !Condition->isInstantiationDependent() &&
16020 !Condition->containsUnexpandedParameterPack()) {
16021 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
16022 if (Val.isInvalid())
16023 return nullptr;
16024
16025 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
16026
16027 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16028 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final,
16029 getLangOpts().OpenMP);
16030 if (CaptureRegion != OMPD_unknown &&
16031 !SemaRef.CurContext->isDependentContext()) {
16032 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16033 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16034 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16035 HelperValStmt = buildPreInits(getASTContext(), Captures);
16036 }
16037 }
16038
16039 return new (getASTContext()) OMPFinalClause(
16040 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16041}
16042
16045 Expr *Op) {
16046 if (!Op)
16047 return ExprError();
16048
16049 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
16050 public:
16051 IntConvertDiagnoser()
16052 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {}
16053 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
16054 QualType T) override {
16055 return S.Diag(Loc, diag::err_omp_not_integral) << T;
16056 }
16057 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
16058 QualType T) override {
16059 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
16060 }
16061 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
16062 QualType T,
16063 QualType ConvTy) override {
16064 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
16065 }
16066 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
16067 QualType ConvTy) override {
16068 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16069 << ConvTy->isEnumeralType() << ConvTy;
16070 }
16071 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
16072 QualType T) override {
16073 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
16074 }
16075 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
16076 QualType ConvTy) override {
16077 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16078 << ConvTy->isEnumeralType() << ConvTy;
16079 }
16080 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
16081 QualType) override {
16082 llvm_unreachable("conversion functions are permitted");
16083 }
16084 } ConvertDiagnoser;
16085 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16086}
16087
16088static bool
16090 bool StrictlyPositive, bool BuildCapture = false,
16091 OpenMPDirectiveKind DKind = OMPD_unknown,
16092 OpenMPDirectiveKind *CaptureRegion = nullptr,
16093 Stmt **HelperValStmt = nullptr) {
16094 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
16095 !ValExpr->isInstantiationDependent()) {
16096 SourceLocation Loc = ValExpr->getExprLoc();
16098 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
16099 if (Value.isInvalid())
16100 return false;
16101
16102 ValExpr = Value.get();
16103 // The expression must evaluate to a non-negative integer value.
16104 if (std::optional<llvm::APSInt> Result =
16105 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
16106 if (Result->isSigned() &&
16107 !((!StrictlyPositive && Result->isNonNegative()) ||
16108 (StrictlyPositive && Result->isStrictlyPositive()))) {
16109 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
16110 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
16111 << ValExpr->getSourceRange();
16112 return false;
16113 }
16114 }
16115 if (!BuildCapture)
16116 return true;
16117 *CaptureRegion =
16118 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
16119 if (*CaptureRegion != OMPD_unknown &&
16120 !SemaRef.CurContext->isDependentContext()) {
16121 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16122 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16123 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16124 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
16125 }
16126 }
16127 return true;
16128}
16129
16130static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First,
16131 unsigned Last,
16132 ArrayRef<unsigned> Exclude = {}) {
16133 SmallString<256> Buffer;
16134 llvm::raw_svector_ostream Out(Buffer);
16135 unsigned Skipped = Exclude.size();
16136 for (unsigned I = First; I < Last; ++I) {
16137 if (llvm::is_contained(Exclude, I)) {
16138 --Skipped;
16139 continue;
16140 }
16141 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
16142 if (I + Skipped + 2 == Last)
16143 Out << " or ";
16144 else if (I + Skipped + 1 != Last)
16145 Out << ", ";
16146 }
16147 return std::string(Out.str());
16148}
16149
16151 OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads,
16152 SourceLocation StartLoc, SourceLocation LParenLoc,
16153 SourceLocation ModifierLoc, SourceLocation EndLoc) {
16154 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 60) &&
16155 "Unexpected num_threads modifier in OpenMP < 60.");
16156
16157 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTHREADS_unknown) {
16158 std::string Values = getListOfPossibleValues(OMPC_num_threads, /*First=*/0,
16160 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
16161 << Values << getOpenMPClauseNameForDiag(OMPC_num_threads);
16162 return nullptr;
16163 }
16164
16165 Expr *ValExpr = NumThreads;
16166 Stmt *HelperValStmt = nullptr;
16167
16168 // OpenMP [2.5, Restrictions]
16169 // The num_threads expression must evaluate to a positive integer value.
16170 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads,
16171 /*StrictlyPositive=*/true))
16172 return nullptr;
16173
16174 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16176 DKind, OMPC_num_threads, getLangOpts().OpenMP);
16177 if (CaptureRegion != OMPD_unknown &&
16178 !SemaRef.CurContext->isDependentContext()) {
16179 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16180 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16181 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16182 HelperValStmt = buildPreInits(getASTContext(), Captures);
16183 }
16184
16185 return new (getASTContext())
16186 OMPNumThreadsClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
16187 StartLoc, LParenLoc, ModifierLoc, EndLoc);
16188}
16189
16191 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
16192 bool SuppressExprDiags) {
16193 if (!E)
16194 return ExprError();
16195 if (E->isValueDependent() || E->isTypeDependent() ||
16197 return E;
16198
16199 llvm::APSInt Result;
16200 ExprResult ICE;
16201 if (SuppressExprDiags) {
16202 // Use a custom diagnoser that suppresses 'note' diagnostics about the
16203 // expression.
16204 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
16205 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
16207 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
16208 llvm_unreachable("Diagnostic suppressed");
16209 }
16210 } Diagnoser;
16211 ICE = SemaRef.VerifyIntegerConstantExpression(E, &Result, Diagnoser,
16213 } else {
16214 ICE =
16215 SemaRef.VerifyIntegerConstantExpression(E, &Result,
16216 /*FIXME*/ AllowFoldKind::Allow);
16217 }
16218 if (ICE.isInvalid())
16219 return ExprError();
16220
16221 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
16222 (!StrictlyPositive && !Result.isNonNegative())) {
16223 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
16224 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
16225 << E->getSourceRange();
16226 return ExprError();
16227 }
16228 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
16229 CKind == OMPC_allocate) &&
16230 !Result.isPowerOf2()) {
16231 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
16232 << E->getSourceRange();
16233 return ExprError();
16234 }
16235
16236 if (!Result.isRepresentableByInt64()) {
16237 Diag(E->getExprLoc(), diag::err_omp_large_expression_in_clause)
16239 return ExprError();
16240 }
16241
16242 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
16243 DSAStack->setAssociatedLoops(Result.getExtValue());
16244 else if (CKind == OMPC_ordered)
16245 DSAStack->setAssociatedLoops(Result.getExtValue());
16246 return ICE;
16247}
16248
16249void SemaOpenMP::setOpenMPDeviceNum(int Num) { DeviceNum = Num; }
16250
16251void SemaOpenMP::setOpenMPDeviceNumID(StringRef ID) { DeviceNumID = ID; }
16252
16253int SemaOpenMP::getOpenMPDeviceNum() const { return DeviceNum; }
16254
16256 llvm::APSInt Result;
16257 Expr::EvalResult EvalResult;
16258 // Evaluate the expression to an integer value
16259 if (!DeviceNumExpr->isValueDependent() &&
16260 DeviceNumExpr->EvaluateAsInt(EvalResult, SemaRef.Context)) {
16261 // The device expression must evaluate to a non-negative integer value.
16262 Result = EvalResult.Val.getInt();
16263 if (Result.isNonNegative()) {
16264 setOpenMPDeviceNum(Result.getZExtValue());
16265 } else {
16266 Diag(DeviceNumExpr->getExprLoc(),
16267 diag::err_omp_negative_expression_in_clause)
16268 << "device_num" << 0 << DeviceNumExpr->getSourceRange();
16269 }
16270 } else if (auto *DeclRef = dyn_cast<DeclRefExpr>(DeviceNumExpr)) {
16271 // Check if the expression is an identifier
16272 IdentifierInfo *IdInfo = DeclRef->getDecl()->getIdentifier();
16273 if (IdInfo) {
16274 setOpenMPDeviceNumID(IdInfo->getName());
16275 }
16276 } else {
16277 Diag(DeviceNumExpr->getExprLoc(), diag::err_expected_expression);
16278 }
16279}
16280
16282 SourceLocation StartLoc,
16283 SourceLocation LParenLoc,
16284 SourceLocation EndLoc) {
16285 // OpenMP [2.8.1, simd construct, Description]
16286 // The parameter of the safelen clause must be a constant
16287 // positive integer expression.
16288 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
16289 if (Safelen.isInvalid())
16290 return nullptr;
16291 return new (getASTContext())
16292 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
16293}
16294
16296 SourceLocation StartLoc,
16297 SourceLocation LParenLoc,
16298 SourceLocation EndLoc) {
16299 // OpenMP [2.8.1, simd construct, Description]
16300 // The parameter of the simdlen clause must be a constant
16301 // positive integer expression.
16302 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
16303 if (Simdlen.isInvalid())
16304 return nullptr;
16305 return new (getASTContext())
16306 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
16307}
16308
16309/// Tries to find omp_allocator_handle_t type.
16311 DSAStackTy *Stack) {
16312 if (!Stack->getOMPAllocatorHandleT().isNull())
16313 return true;
16314
16315 // Set the allocator handle type.
16316 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
16317 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
16318 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
16319 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16320 << "omp_allocator_handle_t";
16321 return false;
16322 }
16323 QualType AllocatorHandleEnumTy = PT.get();
16324 AllocatorHandleEnumTy.addConst();
16325 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
16326
16327 // Fill the predefined allocator map.
16328 bool ErrorFound = false;
16329 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
16330 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
16331 StringRef Allocator =
16332 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
16333 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
16334 auto *VD = dyn_cast_or_null<ValueDecl>(
16335 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
16336 if (!VD) {
16337 ErrorFound = true;
16338 break;
16339 }
16340 QualType AllocatorType =
16342 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
16343 if (!Res.isUsable()) {
16344 ErrorFound = true;
16345 break;
16346 }
16347 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
16349 /*AllowExplicit=*/true);
16350 if (!Res.isUsable()) {
16351 ErrorFound = true;
16352 break;
16353 }
16354 Stack->setAllocator(AllocatorKind, Res.get());
16355 }
16356 if (ErrorFound) {
16357 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16358 << "omp_allocator_handle_t";
16359 return false;
16360 }
16361
16362 return true;
16363}
16364
16366 SourceLocation StartLoc,
16367 SourceLocation LParenLoc,
16368 SourceLocation EndLoc) {
16369 // OpenMP [2.11.3, allocate Directive, Description]
16370 // allocator is an expression of omp_allocator_handle_t type.
16372 return nullptr;
16373
16374 ExprResult Allocator = SemaRef.DefaultLvalueConversion(A);
16375 if (Allocator.isInvalid())
16376 return nullptr;
16377 Allocator = SemaRef.PerformImplicitConversion(
16378 Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
16380 /*AllowExplicit=*/true);
16381 if (Allocator.isInvalid())
16382 return nullptr;
16383 return new (getASTContext())
16384 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
16385}
16386
16388 SourceLocation StartLoc,
16389 SourceLocation LParenLoc,
16390 SourceLocation EndLoc) {
16391 // OpenMP [2.7.1, loop construct, Description]
16392 // OpenMP [2.8.1, simd construct, Description]
16393 // OpenMP [2.9.6, distribute construct, Description]
16394 // The parameter of the collapse clause must be a constant
16395 // positive integer expression.
16396 ExprResult NumForLoopsResult =
16397 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
16398 if (NumForLoopsResult.isInvalid())
16399 return nullptr;
16400 return new (getASTContext())
16401 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
16402}
16403
16405 SourceLocation EndLoc,
16406 SourceLocation LParenLoc,
16407 Expr *NumForLoops) {
16408 // OpenMP [2.7.1, loop construct, Description]
16409 // OpenMP [2.8.1, simd construct, Description]
16410 // OpenMP [2.9.6, distribute construct, Description]
16411 // The parameter of the ordered clause must be a constant
16412 // positive integer expression if any.
16413 if (NumForLoops && LParenLoc.isValid()) {
16414 ExprResult NumForLoopsResult =
16415 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
16416 if (NumForLoopsResult.isInvalid())
16417 return nullptr;
16418 NumForLoops = NumForLoopsResult.get();
16419 } else {
16420 NumForLoops = nullptr;
16421 }
16422 auto *Clause =
16424 NumForLoops ? DSAStack->getAssociatedLoops() : 0,
16425 StartLoc, LParenLoc, EndLoc);
16426 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
16427 return Clause;
16428}
16429
16431 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
16432 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16433 OMPClause *Res = nullptr;
16434 switch (Kind) {
16435 case OMPC_proc_bind:
16436 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
16437 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16438 break;
16439 case OMPC_atomic_default_mem_order:
16441 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
16442 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16443 break;
16444 case OMPC_fail:
16445 Res = ActOnOpenMPFailClause(static_cast<OpenMPClauseKind>(Argument),
16446 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16447 break;
16448 case OMPC_update:
16449 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
16450 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16451 break;
16452 case OMPC_bind:
16453 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
16454 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16455 break;
16456 case OMPC_at:
16457 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
16458 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16459 break;
16460 case OMPC_severity:
16462 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
16463 LParenLoc, EndLoc);
16464 break;
16465 case OMPC_if:
16466 case OMPC_final:
16467 case OMPC_num_threads:
16468 case OMPC_safelen:
16469 case OMPC_simdlen:
16470 case OMPC_sizes:
16471 case OMPC_allocator:
16472 case OMPC_collapse:
16473 case OMPC_schedule:
16474 case OMPC_private:
16475 case OMPC_firstprivate:
16476 case OMPC_lastprivate:
16477 case OMPC_shared:
16478 case OMPC_reduction:
16479 case OMPC_task_reduction:
16480 case OMPC_in_reduction:
16481 case OMPC_linear:
16482 case OMPC_aligned:
16483 case OMPC_copyin:
16484 case OMPC_copyprivate:
16485 case OMPC_ordered:
16486 case OMPC_nowait:
16487 case OMPC_untied:
16488 case OMPC_mergeable:
16489 case OMPC_threadprivate:
16490 case OMPC_groupprivate:
16491 case OMPC_allocate:
16492 case OMPC_flush:
16493 case OMPC_depobj:
16494 case OMPC_read:
16495 case OMPC_write:
16496 case OMPC_capture:
16497 case OMPC_compare:
16498 case OMPC_seq_cst:
16499 case OMPC_acq_rel:
16500 case OMPC_acquire:
16501 case OMPC_release:
16502 case OMPC_relaxed:
16503 case OMPC_depend:
16504 case OMPC_device:
16505 case OMPC_threads:
16506 case OMPC_simd:
16507 case OMPC_map:
16508 case OMPC_num_teams:
16509 case OMPC_thread_limit:
16510 case OMPC_priority:
16511 case OMPC_grainsize:
16512 case OMPC_nogroup:
16513 case OMPC_num_tasks:
16514 case OMPC_hint:
16515 case OMPC_dist_schedule:
16516 case OMPC_default:
16517 case OMPC_defaultmap:
16518 case OMPC_unknown:
16519 case OMPC_uniform:
16520 case OMPC_to:
16521 case OMPC_from:
16522 case OMPC_use_device_ptr:
16523 case OMPC_use_device_addr:
16524 case OMPC_is_device_ptr:
16525 case OMPC_has_device_addr:
16526 case OMPC_unified_address:
16527 case OMPC_unified_shared_memory:
16528 case OMPC_reverse_offload:
16529 case OMPC_dynamic_allocators:
16530 case OMPC_self_maps:
16531 case OMPC_device_type:
16532 case OMPC_match:
16533 case OMPC_nontemporal:
16534 case OMPC_destroy:
16535 case OMPC_novariants:
16536 case OMPC_nocontext:
16537 case OMPC_detach:
16538 case OMPC_inclusive:
16539 case OMPC_exclusive:
16540 case OMPC_uses_allocators:
16541 case OMPC_affinity:
16542 case OMPC_when:
16543 case OMPC_message:
16544 default:
16545 llvm_unreachable("Clause is not allowed.");
16546 }
16547 return Res;
16548}
16549
16551 llvm::omp::DefaultKind M, SourceLocation MLoc,
16553 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16554 if (M == OMP_DEFAULT_unknown) {
16555 Diag(MLoc, diag::err_omp_unexpected_clause_value)
16556 << getListOfPossibleValues(OMPC_default, /*First=*/0,
16557 /*Last=*/unsigned(OMP_DEFAULT_unknown))
16558 << getOpenMPClauseNameForDiag(OMPC_default);
16559 return nullptr;
16560 }
16561
16562 switch (M) {
16563 case OMP_DEFAULT_none:
16564 DSAStack->setDefaultDSANone(MLoc);
16565 break;
16566 case OMP_DEFAULT_shared:
16567 DSAStack->setDefaultDSAShared(MLoc);
16568 break;
16569 case OMP_DEFAULT_firstprivate:
16570 DSAStack->setDefaultDSAFirstPrivate(MLoc);
16571 break;
16572 case OMP_DEFAULT_private:
16573 DSAStack->setDefaultDSAPrivate(MLoc);
16574 break;
16575 default:
16576 llvm_unreachable("DSA unexpected in OpenMP default clause");
16577 }
16578
16579 switch (VCKind) {
16580 case OMPC_DEFAULT_VC_aggregate:
16581 DSAStack->setDefaultDSAVCAggregate(VCKindLoc);
16582 break;
16583 case OMPC_DEFAULT_VC_all:
16584 DSAStack->setDefaultDSAVCAll(VCKindLoc);
16585 break;
16586 case OMPC_DEFAULT_VC_allocatable:
16587 DSAStack->setDefaultDSAVCAllocatable(VCKindLoc);
16588 break;
16589 case OMPC_DEFAULT_VC_pointer:
16590 DSAStack->setDefaultDSAVCPointer(VCKindLoc);
16591 break;
16592 case OMPC_DEFAULT_VC_scalar:
16593 DSAStack->setDefaultDSAVCScalar(VCKindLoc);
16594 break;
16595 default:
16596 Diag(VCKindLoc, diag::err_omp_default_vc)
16597 << getOpenMPSimpleClauseTypeName(OMPC_default, unsigned(M));
16598 }
16599
16600 return new (getASTContext())
16601 OMPDefaultClause(M, MLoc, VCKind, VCKindLoc, StartLoc, LParenLoc, EndLoc);
16602}
16603
16605 SourceLocation KindKwLoc,
16606 SourceLocation StartLoc,
16607 SourceLocation LParenLoc,
16608 SourceLocation EndLoc) {
16609 if (Kind == OMP_PROC_BIND_unknown) {
16610 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16611 << getListOfPossibleValues(OMPC_proc_bind,
16612 /*First=*/unsigned(OMP_PROC_BIND_master),
16613 /*Last=*/
16614 unsigned(getLangOpts().OpenMP > 50
16615 ? OMP_PROC_BIND_primary
16616 : OMP_PROC_BIND_spread) +
16617 1)
16618 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
16619 return nullptr;
16620 }
16621 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
16622 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16623 << getListOfPossibleValues(OMPC_proc_bind,
16624 /*First=*/unsigned(OMP_PROC_BIND_master),
16625 /*Last=*/
16626 unsigned(OMP_PROC_BIND_spread) + 1)
16627 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
16628 return new (getASTContext())
16629 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16630}
16631
16634 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16636 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16638 OMPC_atomic_default_mem_order, /*First=*/0,
16640 << getOpenMPClauseNameForDiag(OMPC_atomic_default_mem_order);
16641 return nullptr;
16642 }
16644 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16645}
16646
16648 SourceLocation KindKwLoc,
16649 SourceLocation StartLoc,
16650 SourceLocation LParenLoc,
16651 SourceLocation EndLoc) {
16652 if (Kind == OMPC_AT_unknown) {
16653 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16654 << getListOfPossibleValues(OMPC_at, /*First=*/0,
16655 /*Last=*/OMPC_AT_unknown)
16656 << getOpenMPClauseNameForDiag(OMPC_at);
16657 return nullptr;
16658 }
16659 return new (getASTContext())
16660 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16661}
16662
16664 SourceLocation KindKwLoc,
16665 SourceLocation StartLoc,
16666 SourceLocation LParenLoc,
16667 SourceLocation EndLoc) {
16668 if (Kind == OMPC_SEVERITY_unknown) {
16669 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16670 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
16671 /*Last=*/OMPC_SEVERITY_unknown)
16672 << getOpenMPClauseNameForDiag(OMPC_severity);
16673 return nullptr;
16674 }
16675 return new (getASTContext())
16676 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16677}
16678
16680 SourceLocation StartLoc,
16681 SourceLocation LParenLoc,
16682 SourceLocation EndLoc) {
16683 assert(ME && "NULL expr in Message clause");
16684 QualType Type = ME->getType();
16685 if ((!Type->isPointerType() && !Type->isArrayType()) ||
16687 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
16688 << getOpenMPClauseNameForDiag(OMPC_message) << 0;
16689 return nullptr;
16690 }
16691
16692 Stmt *HelperValStmt = nullptr;
16693
16694 // Depending on whether this clause appears in an executable context or not,
16695 // we may or may not build a capture.
16696 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16697 OpenMPDirectiveKind CaptureRegion =
16698 DKind == OMPD_unknown ? OMPD_unknown
16700 DKind, OMPC_message, getLangOpts().OpenMP);
16701 if (CaptureRegion != OMPD_unknown &&
16702 !SemaRef.CurContext->isDependentContext()) {
16703 ME = SemaRef.MakeFullExpr(ME).get();
16704 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16705 ME = tryBuildCapture(SemaRef, ME, Captures).get();
16706 HelperValStmt = buildPreInits(getASTContext(), Captures);
16707 }
16708
16709 // Convert array type to pointer type if needed.
16710 ME = SemaRef.DefaultFunctionArrayLvalueConversion(ME).get();
16711
16712 return new (getASTContext()) OMPMessageClause(
16713 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16714}
16715
16718 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
16719 SourceLocation KindLoc, SourceLocation EndLoc) {
16720 if (Kind != OMPC_ORDER_concurrent ||
16721 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
16722 // Kind should be concurrent,
16723 // Modifiers introduced in OpenMP 5.1
16724 static_assert(OMPC_ORDER_unknown > 0,
16725 "OMPC_ORDER_unknown not greater than 0");
16726
16727 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16728 << getListOfPossibleValues(OMPC_order,
16729 /*First=*/0,
16730 /*Last=*/OMPC_ORDER_unknown)
16731 << getOpenMPClauseNameForDiag(OMPC_order);
16732 return nullptr;
16733 }
16734 if (getLangOpts().OpenMP >= 51 && Modifier == OMPC_ORDER_MODIFIER_unknown &&
16735 MLoc.isValid()) {
16736 Diag(MLoc, diag::err_omp_unexpected_clause_value)
16737 << getListOfPossibleValues(OMPC_order,
16738 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
16739 /*Last=*/OMPC_ORDER_MODIFIER_last)
16740 << getOpenMPClauseNameForDiag(OMPC_order);
16741 } else if (getLangOpts().OpenMP >= 50) {
16742 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
16743 if (DSAStack->getCurScope()) {
16744 // mark the current scope with 'order' flag
16745 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
16746 DSAStack->getCurScope()->setFlags(existingFlags |
16748 }
16749 }
16750 return new (getASTContext()) OMPOrderClause(
16751 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
16752}
16753
16755 SourceLocation KindKwLoc,
16756 SourceLocation StartLoc,
16757 SourceLocation LParenLoc,
16758 SourceLocation EndLoc) {
16759 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
16760 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
16761 SmallVector<unsigned> Except = {
16762 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
16763 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
16764 if (getLangOpts().OpenMP < 51)
16765 Except.push_back(OMPC_DEPEND_inoutset);
16766 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16767 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
16768 /*Last=*/OMPC_DEPEND_unknown, Except)
16769 << getOpenMPClauseNameForDiag(OMPC_update);
16770 return nullptr;
16771 }
16772 return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc,
16773 KindKwLoc, Kind, EndLoc);
16774}
16775
16777 SourceLocation StartLoc,
16778 SourceLocation LParenLoc,
16779 SourceLocation EndLoc) {
16780 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
16781
16782 for (Expr *&SizeExpr : SanitizedSizeExprs) {
16783 // Skip if already sanitized, e.g. during a partial template instantiation.
16784 if (!SizeExpr)
16785 continue;
16786
16787 bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes,
16788 /*StrictlyPositive=*/true);
16789
16790 // isNonNegativeIntegerValue returns true for non-integral types (but still
16791 // emits error diagnostic), so check for the expected type explicitly.
16792 QualType SizeTy = SizeExpr->getType();
16793 if (!SizeTy->isIntegerType())
16794 IsValid = false;
16795
16796 // Handling in templates is tricky. There are four possibilities to
16797 // consider:
16798 //
16799 // 1a. The expression is valid and we are in a instantiated template or not
16800 // in a template:
16801 // Pass valid expression to be further analysed later in Sema.
16802 // 1b. The expression is valid and we are in a template (including partial
16803 // instantiation):
16804 // isNonNegativeIntegerValue skipped any checks so there is no
16805 // guarantee it will be correct after instantiation.
16806 // ActOnOpenMPSizesClause will be called again at instantiation when
16807 // it is not in a dependent context anymore. This may cause warnings
16808 // to be emitted multiple times.
16809 // 2a. The expression is invalid and we are in an instantiated template or
16810 // not in a template:
16811 // Invalidate the expression with a clearly wrong value (nullptr) so
16812 // later in Sema we do not have to do the same validity analysis again
16813 // or crash from unexpected data. Error diagnostics have already been
16814 // emitted.
16815 // 2b. The expression is invalid and we are in a template (including partial
16816 // instantiation):
16817 // Pass the invalid expression as-is, template instantiation may
16818 // replace unexpected types/values with valid ones. The directives
16819 // with this clause must not try to use these expressions in dependent
16820 // contexts, but delay analysis until full instantiation.
16821 if (!SizeExpr->isInstantiationDependent() && !IsValid)
16822 SizeExpr = nullptr;
16823 }
16824
16825 return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
16826 SanitizedSizeExprs);
16827}
16828
16830 SourceLocation StartLoc,
16831 SourceLocation LParenLoc,
16832 SourceLocation EndLoc) {
16833 size_t NumLoops = PermExprs.size();
16834 SmallVector<Expr *> SanitizedPermExprs;
16835 llvm::append_range(SanitizedPermExprs, PermExprs);
16836
16837 for (Expr *&PermExpr : SanitizedPermExprs) {
16838 // Skip if template-dependent or already sanitized, e.g. during a partial
16839 // template instantiation.
16840 if (!PermExpr || PermExpr->isInstantiationDependent())
16841 continue;
16842
16843 llvm::APSInt PermVal;
16844 ExprResult PermEvalExpr = SemaRef.VerifyIntegerConstantExpression(
16845 PermExpr, &PermVal, AllowFoldKind::Allow);
16846 bool IsValid = PermEvalExpr.isUsable();
16847 if (IsValid)
16848 PermExpr = PermEvalExpr.get();
16849
16850 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
16851 SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
16852 PermEvalExpr.get()->getEndLoc());
16853 Diag(PermEvalExpr.get()->getExprLoc(),
16854 diag::err_omp_interchange_permutation_value_range)
16855 << NumLoops << ExprRange;
16856 IsValid = false;
16857 }
16858
16859 if (!PermExpr->isInstantiationDependent() && !IsValid)
16860 PermExpr = nullptr;
16861 }
16862
16863 return OMPPermutationClause::Create(getASTContext(), StartLoc, LParenLoc,
16864 EndLoc, SanitizedPermExprs);
16865}
16866
16868 SourceLocation EndLoc) {
16869 return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc);
16870}
16871
16873 SourceLocation StartLoc,
16874 SourceLocation LParenLoc,
16875 SourceLocation EndLoc) {
16876 if (FactorExpr) {
16877 // If an argument is specified, it must be a constant (or an unevaluated
16878 // template expression).
16880 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
16881 if (FactorResult.isInvalid())
16882 return nullptr;
16883 FactorExpr = FactorResult.get();
16884 }
16885
16886 return OMPPartialClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
16887 FactorExpr);
16888}
16889
16891 SourceLocation LParenLoc,
16892 SourceLocation EndLoc) {
16893 ExprResult AlignVal;
16894 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
16895 if (AlignVal.isInvalid())
16896 return nullptr;
16897 return OMPAlignClause::Create(getASTContext(), AlignVal.get(), StartLoc,
16898 LParenLoc, EndLoc);
16899}
16900
16903 SourceLocation StartLoc, SourceLocation LParenLoc,
16904 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
16905 SourceLocation EndLoc) {
16906 OMPClause *Res = nullptr;
16907 switch (Kind) {
16908 case OMPC_schedule:
16909 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
16910 assert(Argument.size() == NumberOfElements &&
16911 ArgumentLoc.size() == NumberOfElements);
16913 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
16914 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
16915 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
16916 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
16917 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
16918 break;
16919 case OMPC_if:
16920 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16921 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
16922 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
16923 DelimLoc, EndLoc);
16924 break;
16925 case OMPC_dist_schedule:
16927 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
16928 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
16929 break;
16930 case OMPC_default:
16931 enum { DefaultModifier, DefaultVarCategory };
16933 static_cast<llvm::omp::DefaultKind>(Argument[DefaultModifier]),
16934 ArgumentLoc[DefaultModifier],
16936 Argument[DefaultVarCategory]),
16937 ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc);
16938 break;
16939 case OMPC_defaultmap:
16940 enum { Modifier, DefaultmapKind };
16942 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
16943 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
16944 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
16945 EndLoc);
16946 break;
16947 case OMPC_order:
16948 enum { OrderModifier, OrderKind };
16950 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
16951 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
16952 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
16953 break;
16954 case OMPC_device:
16955 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16957 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
16958 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16959 break;
16960 case OMPC_grainsize:
16961 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16962 "Modifier for grainsize clause and its location are expected.");
16964 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
16965 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16966 break;
16967 case OMPC_num_tasks:
16968 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16969 "Modifier for num_tasks clause and its location are expected.");
16971 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
16972 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16973 break;
16974 case OMPC_num_threads:
16975 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16976 "Modifier for num_threads clause and its location are expected.");
16978 static_cast<OpenMPNumThreadsClauseModifier>(Argument.back()), Expr,
16979 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16980 break;
16981 case OMPC_final:
16982 case OMPC_safelen:
16983 case OMPC_simdlen:
16984 case OMPC_sizes:
16985 case OMPC_allocator:
16986 case OMPC_collapse:
16987 case OMPC_proc_bind:
16988 case OMPC_private:
16989 case OMPC_firstprivate:
16990 case OMPC_lastprivate:
16991 case OMPC_shared:
16992 case OMPC_reduction:
16993 case OMPC_task_reduction:
16994 case OMPC_in_reduction:
16995 case OMPC_linear:
16996 case OMPC_aligned:
16997 case OMPC_copyin:
16998 case OMPC_copyprivate:
16999 case OMPC_ordered:
17000 case OMPC_nowait:
17001 case OMPC_untied:
17002 case OMPC_mergeable:
17003 case OMPC_threadprivate:
17004 case OMPC_groupprivate:
17005 case OMPC_allocate:
17006 case OMPC_flush:
17007 case OMPC_depobj:
17008 case OMPC_read:
17009 case OMPC_write:
17010 case OMPC_update:
17011 case OMPC_capture:
17012 case OMPC_compare:
17013 case OMPC_seq_cst:
17014 case OMPC_acq_rel:
17015 case OMPC_acquire:
17016 case OMPC_release:
17017 case OMPC_relaxed:
17018 case OMPC_depend:
17019 case OMPC_threads:
17020 case OMPC_simd:
17021 case OMPC_map:
17022 case OMPC_num_teams:
17023 case OMPC_thread_limit:
17024 case OMPC_priority:
17025 case OMPC_nogroup:
17026 case OMPC_hint:
17027 case OMPC_unknown:
17028 case OMPC_uniform:
17029 case OMPC_to:
17030 case OMPC_from:
17031 case OMPC_use_device_ptr:
17032 case OMPC_use_device_addr:
17033 case OMPC_is_device_ptr:
17034 case OMPC_has_device_addr:
17035 case OMPC_unified_address:
17036 case OMPC_unified_shared_memory:
17037 case OMPC_reverse_offload:
17038 case OMPC_dynamic_allocators:
17039 case OMPC_atomic_default_mem_order:
17040 case OMPC_self_maps:
17041 case OMPC_device_type:
17042 case OMPC_match:
17043 case OMPC_nontemporal:
17044 case OMPC_at:
17045 case OMPC_severity:
17046 case OMPC_message:
17047 case OMPC_destroy:
17048 case OMPC_novariants:
17049 case OMPC_nocontext:
17050 case OMPC_detach:
17051 case OMPC_inclusive:
17052 case OMPC_exclusive:
17053 case OMPC_uses_allocators:
17054 case OMPC_affinity:
17055 case OMPC_when:
17056 case OMPC_bind:
17057 default:
17058 llvm_unreachable("Clause is not allowed.");
17059 }
17060 return Res;
17061}
17062
17065 SourceLocation M1Loc, SourceLocation M2Loc) {
17066 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
17067 SmallVector<unsigned, 2> Excluded;
17069 Excluded.push_back(M2);
17070 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
17071 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
17072 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
17073 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
17074 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
17075 << getListOfPossibleValues(OMPC_schedule,
17076 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
17078 Excluded)
17079 << getOpenMPClauseNameForDiag(OMPC_schedule);
17080 return true;
17081 }
17082 return false;
17083}
17084
17087 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
17088 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
17089 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
17090 if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) ||
17091 checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc))
17092 return nullptr;
17093 // OpenMP, 2.7.1, Loop Construct, Restrictions
17094 // Either the monotonic modifier or the nonmonotonic modifier can be specified
17095 // but not both.
17096 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
17097 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
17098 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
17099 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
17100 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
17101 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
17102 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
17103 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
17104 return nullptr;
17105 }
17106 if (Kind == OMPC_SCHEDULE_unknown) {
17107 std::string Values;
17108 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
17109 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
17110 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17112 Exclude);
17113 } else {
17114 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17115 /*Last=*/OMPC_SCHEDULE_unknown);
17116 }
17117 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17118 << Values << getOpenMPClauseNameForDiag(OMPC_schedule);
17119 return nullptr;
17120 }
17121 // OpenMP, 2.7.1, Loop Construct, Restrictions
17122 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
17123 // schedule(guided).
17124 // OpenMP 5.0 does not have this restriction.
17125 if (getLangOpts().OpenMP < 50 &&
17126 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
17127 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
17128 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
17129 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
17130 diag::err_omp_schedule_nonmonotonic_static);
17131 return nullptr;
17132 }
17133 Expr *ValExpr = ChunkSize;
17134 Stmt *HelperValStmt = nullptr;
17135 if (ChunkSize) {
17136 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
17137 !ChunkSize->isInstantiationDependent() &&
17138 !ChunkSize->containsUnexpandedParameterPack()) {
17139 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
17140 ExprResult Val =
17141 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
17142 if (Val.isInvalid())
17143 return nullptr;
17144
17145 ValExpr = Val.get();
17146
17147 // OpenMP [2.7.1, Restrictions]
17148 // chunk_size must be a loop invariant integer expression with a positive
17149 // value.
17150 if (std::optional<llvm::APSInt> Result =
17152 if (Result->isSigned() && !Result->isStrictlyPositive()) {
17153 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
17154 << "schedule" << 1 << ChunkSize->getSourceRange();
17155 return nullptr;
17156 }
17158 DSAStack->getCurrentDirective(), OMPC_schedule,
17159 getLangOpts().OpenMP) != OMPD_unknown &&
17160 !SemaRef.CurContext->isDependentContext()) {
17161 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17162 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17163 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17164 HelperValStmt = buildPreInits(getASTContext(), Captures);
17165 }
17166 }
17167 }
17168
17169 return new (getASTContext())
17170 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
17171 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
17172}
17173
17175 SourceLocation StartLoc,
17176 SourceLocation EndLoc) {
17177 OMPClause *Res = nullptr;
17178 switch (Kind) {
17179 case OMPC_ordered:
17180 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
17181 break;
17182 case OMPC_nowait:
17183 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
17184 break;
17185 case OMPC_untied:
17186 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
17187 break;
17188 case OMPC_mergeable:
17189 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
17190 break;
17191 case OMPC_read:
17192 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
17193 break;
17194 case OMPC_write:
17195 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
17196 break;
17197 case OMPC_update:
17198 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
17199 break;
17200 case OMPC_capture:
17201 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
17202 break;
17203 case OMPC_compare:
17204 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
17205 break;
17206 case OMPC_fail:
17207 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
17208 break;
17209 case OMPC_seq_cst:
17210 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
17211 break;
17212 case OMPC_acq_rel:
17213 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
17214 break;
17215 case OMPC_acquire:
17216 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
17217 break;
17218 case OMPC_release:
17219 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
17220 break;
17221 case OMPC_relaxed:
17222 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
17223 break;
17224 case OMPC_weak:
17225 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
17226 break;
17227 case OMPC_threads:
17228 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
17229 break;
17230 case OMPC_simd:
17231 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
17232 break;
17233 case OMPC_nogroup:
17234 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
17235 break;
17236 case OMPC_unified_address:
17237 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
17238 break;
17239 case OMPC_unified_shared_memory:
17240 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17241 break;
17242 case OMPC_reverse_offload:
17243 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
17244 break;
17245 case OMPC_dynamic_allocators:
17246 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
17247 break;
17248 case OMPC_self_maps:
17249 Res = ActOnOpenMPSelfMapsClause(StartLoc, EndLoc);
17250 break;
17251 case OMPC_destroy:
17252 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
17253 /*LParenLoc=*/SourceLocation(),
17254 /*VarLoc=*/SourceLocation(), EndLoc);
17255 break;
17256 case OMPC_full:
17257 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
17258 break;
17259 case OMPC_partial:
17260 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
17261 break;
17262 case OMPC_ompx_bare:
17263 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
17264 break;
17265 case OMPC_if:
17266 case OMPC_final:
17267 case OMPC_num_threads:
17268 case OMPC_safelen:
17269 case OMPC_simdlen:
17270 case OMPC_sizes:
17271 case OMPC_allocator:
17272 case OMPC_collapse:
17273 case OMPC_schedule:
17274 case OMPC_private:
17275 case OMPC_firstprivate:
17276 case OMPC_lastprivate:
17277 case OMPC_shared:
17278 case OMPC_reduction:
17279 case OMPC_task_reduction:
17280 case OMPC_in_reduction:
17281 case OMPC_linear:
17282 case OMPC_aligned:
17283 case OMPC_copyin:
17284 case OMPC_copyprivate:
17285 case OMPC_default:
17286 case OMPC_proc_bind:
17287 case OMPC_threadprivate:
17288 case OMPC_groupprivate:
17289 case OMPC_allocate:
17290 case OMPC_flush:
17291 case OMPC_depobj:
17292 case OMPC_depend:
17293 case OMPC_device:
17294 case OMPC_map:
17295 case OMPC_num_teams:
17296 case OMPC_thread_limit:
17297 case OMPC_priority:
17298 case OMPC_grainsize:
17299 case OMPC_num_tasks:
17300 case OMPC_hint:
17301 case OMPC_dist_schedule:
17302 case OMPC_defaultmap:
17303 case OMPC_unknown:
17304 case OMPC_uniform:
17305 case OMPC_to:
17306 case OMPC_from:
17307 case OMPC_use_device_ptr:
17308 case OMPC_use_device_addr:
17309 case OMPC_is_device_ptr:
17310 case OMPC_has_device_addr:
17311 case OMPC_atomic_default_mem_order:
17312 case OMPC_device_type:
17313 case OMPC_match:
17314 case OMPC_nontemporal:
17315 case OMPC_order:
17316 case OMPC_at:
17317 case OMPC_severity:
17318 case OMPC_message:
17319 case OMPC_novariants:
17320 case OMPC_nocontext:
17321 case OMPC_detach:
17322 case OMPC_inclusive:
17323 case OMPC_exclusive:
17324 case OMPC_uses_allocators:
17325 case OMPC_affinity:
17326 case OMPC_when:
17327 case OMPC_ompx_dyn_cgroup_mem:
17328 default:
17329 llvm_unreachable("Clause is not allowed.");
17330 }
17331 return Res;
17332}
17333
17335 SourceLocation EndLoc) {
17336 DSAStack->setNowaitRegion();
17337 return new (getASTContext()) OMPNowaitClause(StartLoc, EndLoc);
17338}
17339
17341 SourceLocation EndLoc) {
17342 DSAStack->setUntiedRegion();
17343 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
17344}
17345
17347 SourceLocation EndLoc) {
17348 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
17349}
17350
17352 SourceLocation EndLoc) {
17353 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
17354}
17355
17357 SourceLocation EndLoc) {
17358 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
17359}
17360
17362 SourceLocation EndLoc) {
17363 return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc);
17364}
17365
17367 SourceLocation EndLoc) {
17368 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
17369}
17370
17372 SourceLocation EndLoc) {
17373 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
17374}
17375
17377 SourceLocation EndLoc) {
17378 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
17379}
17380
17382 SourceLocation KindLoc,
17383 SourceLocation StartLoc,
17384 SourceLocation LParenLoc,
17385 SourceLocation EndLoc) {
17386
17388 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
17389 return nullptr;
17390 }
17391 return new (getASTContext())
17392 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
17393}
17394
17396 SourceLocation EndLoc) {
17397 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
17398}
17399
17401 SourceLocation EndLoc) {
17402 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
17403}
17404
17406 SourceLocation EndLoc) {
17407 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
17408}
17409
17411 SourceLocation EndLoc) {
17412 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
17413}
17414
17416 SourceLocation EndLoc) {
17417 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
17418}
17419
17421 SourceLocation EndLoc) {
17422 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
17423}
17424
17426 SourceLocation EndLoc) {
17427 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
17428}
17429
17431 SourceLocation EndLoc) {
17432 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
17433}
17434
17436 SourceLocation EndLoc) {
17437 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
17438}
17439
17441 SourceLocation EndLoc) {
17442 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
17443}
17444
17445OMPClause *
17450
17452 SourceLocation EndLoc) {
17453 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
17454}
17455
17456OMPClause *
17458 SourceLocation EndLoc) {
17459 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
17460}
17461
17463 SourceLocation EndLoc) {
17464 return new (getASTContext()) OMPSelfMapsClause(StartLoc, EndLoc);
17465}
17466
17469 SourceLocation StartLoc,
17470 SourceLocation EndLoc) {
17471
17472 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17473 // At least one action-clause must appear on a directive.
17474 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
17475 unsigned OMPVersion = getLangOpts().OpenMP;
17476 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
17477 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
17478 << Expected << getOpenMPDirectiveName(OMPD_interop, OMPVersion);
17479 return StmtError();
17480 }
17481
17482 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17483 // A depend clause can only appear on the directive if a targetsync
17484 // interop-type is present or the interop-var was initialized with
17485 // the targetsync interop-type.
17486
17487 // If there is any 'init' clause diagnose if there is no 'init' clause with
17488 // interop-type of 'targetsync'. Cases involving other directives cannot be
17489 // diagnosed.
17490 const OMPDependClause *DependClause = nullptr;
17491 bool HasInitClause = false;
17492 bool IsTargetSync = false;
17493 for (const OMPClause *C : Clauses) {
17494 if (IsTargetSync)
17495 break;
17496 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
17497 HasInitClause = true;
17498 if (InitClause->getIsTargetSync())
17499 IsTargetSync = true;
17500 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
17501 DependClause = DC;
17502 }
17503 }
17504 if (DependClause && HasInitClause && !IsTargetSync) {
17505 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
17506 return StmtError();
17507 }
17508
17509 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17510 // Each interop-var may be specified for at most one action-clause of each
17511 // interop construct.
17513 for (OMPClause *C : Clauses) {
17514 OpenMPClauseKind ClauseKind = C->getClauseKind();
17515 std::pair<ValueDecl *, bool> DeclResult;
17516 SourceLocation ELoc;
17517 SourceRange ERange;
17518
17519 if (ClauseKind == OMPC_init) {
17520 auto *E = cast<OMPInitClause>(C)->getInteropVar();
17521 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
17522 } else if (ClauseKind == OMPC_use) {
17523 auto *E = cast<OMPUseClause>(C)->getInteropVar();
17524 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
17525 } else if (ClauseKind == OMPC_destroy) {
17526 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
17527 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
17528 }
17529
17530 if (DeclResult.first) {
17531 if (!InteropVars.insert(DeclResult.first).second) {
17532 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
17533 << DeclResult.first;
17534 return StmtError();
17535 }
17536 }
17537 }
17538
17539 return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc,
17540 Clauses);
17541}
17542
17543static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
17544 SourceLocation VarLoc,
17545 OpenMPClauseKind Kind) {
17546 SourceLocation ELoc;
17547 SourceRange ERange;
17548 Expr *RefExpr = InteropVarExpr;
17549 auto Res = getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
17550 /*AllowArraySection=*/false,
17551 /*AllowAssumedSizeArray=*/false,
17552 /*DiagType=*/"omp_interop_t");
17553
17554 if (Res.second) {
17555 // It will be analyzed later.
17556 return true;
17557 }
17558
17559 if (!Res.first)
17560 return false;
17561
17562 // Interop variable should be of type omp_interop_t.
17563 bool HasError = false;
17564 QualType InteropType;
17565 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
17566 VarLoc, Sema::LookupOrdinaryName);
17567 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
17568 NamedDecl *ND = Result.getFoundDecl();
17569 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
17570 InteropType = QualType(TD->getTypeForDecl(), 0);
17571 } else {
17572 HasError = true;
17573 }
17574 } else {
17575 HasError = true;
17576 }
17577
17578 if (HasError) {
17579 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
17580 << "omp_interop_t";
17581 return false;
17582 }
17583
17584 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
17585 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
17586 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
17587 return false;
17588 }
17589
17590 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17591 // The interop-var passed to init or destroy must be non-const.
17592 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
17593 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
17594 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
17595 << /*non-const*/ 1;
17596 return false;
17597 }
17598 return true;
17599}
17600
17602 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
17603 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
17604
17605 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init))
17606 return nullptr;
17607
17608 // Check prefer_type values. These foreign-runtime-id values are either
17609 // string literals or constant integral expressions.
17610 for (const Expr *E : InteropInfo.PreferTypes) {
17611 if (E->isValueDependent() || E->isTypeDependent() ||
17613 continue;
17615 continue;
17616 if (isa<StringLiteral>(E))
17617 continue;
17618 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
17619 return nullptr;
17620 }
17621
17622 return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo,
17623 StartLoc, LParenLoc, VarLoc, EndLoc);
17624}
17625
17627 SourceLocation StartLoc,
17628 SourceLocation LParenLoc,
17629 SourceLocation VarLoc,
17630 SourceLocation EndLoc) {
17631
17632 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use))
17633 return nullptr;
17634
17635 return new (getASTContext())
17636 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17637}
17638
17640 SourceLocation StartLoc,
17641 SourceLocation LParenLoc,
17642 SourceLocation VarLoc,
17643 SourceLocation EndLoc) {
17644 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
17645 DSAStack->getCurrentDirective() == OMPD_depobj) {
17646 unsigned OMPVersion = getLangOpts().OpenMP;
17647 Diag(StartLoc, diag::err_omp_expected_clause_argument)
17648 << getOpenMPClauseNameForDiag(OMPC_destroy)
17649 << getOpenMPDirectiveName(OMPD_depobj, OMPVersion);
17650 return nullptr;
17651 }
17652 if (InteropVar &&
17653 !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy))
17654 return nullptr;
17655
17656 return new (getASTContext())
17657 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17658}
17659
17661 SourceLocation StartLoc,
17662 SourceLocation LParenLoc,
17663 SourceLocation EndLoc) {
17664 Expr *ValExpr = Condition;
17665 Stmt *HelperValStmt = nullptr;
17666 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17667 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17668 !Condition->isInstantiationDependent() &&
17669 !Condition->containsUnexpandedParameterPack()) {
17670 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
17671 if (Val.isInvalid())
17672 return nullptr;
17673
17674 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
17675
17676 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17677 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
17678 getLangOpts().OpenMP);
17679 if (CaptureRegion != OMPD_unknown &&
17680 !SemaRef.CurContext->isDependentContext()) {
17681 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17682 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17683 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17684 HelperValStmt = buildPreInits(getASTContext(), Captures);
17685 }
17686 }
17687
17688 return new (getASTContext()) OMPNovariantsClause(
17689 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17690}
17691
17693 SourceLocation StartLoc,
17694 SourceLocation LParenLoc,
17695 SourceLocation EndLoc) {
17696 Expr *ValExpr = Condition;
17697 Stmt *HelperValStmt = nullptr;
17698 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17699 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17700 !Condition->isInstantiationDependent() &&
17701 !Condition->containsUnexpandedParameterPack()) {
17702 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
17703 if (Val.isInvalid())
17704 return nullptr;
17705
17706 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
17707
17708 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17709 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext,
17710 getLangOpts().OpenMP);
17711 if (CaptureRegion != OMPD_unknown &&
17712 !SemaRef.CurContext->isDependentContext()) {
17713 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17714 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17715 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17716 HelperValStmt = buildPreInits(getASTContext(), Captures);
17717 }
17718 }
17719
17720 return new (getASTContext()) OMPNocontextClause(
17721 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17722}
17723
17725 SourceLocation StartLoc,
17726 SourceLocation LParenLoc,
17727 SourceLocation EndLoc) {
17728 Expr *ValExpr = ThreadID;
17729 Stmt *HelperValStmt = nullptr;
17730
17731 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17732 OpenMPDirectiveKind CaptureRegion =
17733 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP);
17734 if (CaptureRegion != OMPD_unknown &&
17735 !SemaRef.CurContext->isDependentContext()) {
17736 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17737 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17738 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17739 HelperValStmt = buildPreInits(getASTContext(), Captures);
17740 }
17741
17742 return new (getASTContext()) OMPFilterClause(
17743 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17744}
17745
17747 ArrayRef<Expr *> VarList,
17748 const OMPVarListLocTy &Locs,
17750 SourceLocation StartLoc = Locs.StartLoc;
17751 SourceLocation LParenLoc = Locs.LParenLoc;
17752 SourceLocation EndLoc = Locs.EndLoc;
17753 OMPClause *Res = nullptr;
17754 int ExtraModifier = Data.ExtraModifier;
17755 int OriginalSharingModifier = Data.OriginalSharingModifier;
17756 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
17757 SourceLocation ColonLoc = Data.ColonLoc;
17758 switch (Kind) {
17759 case OMPC_private:
17760 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17761 break;
17762 case OMPC_firstprivate:
17763 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17764 break;
17765 case OMPC_lastprivate:
17766 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
17767 "Unexpected lastprivate modifier.");
17769 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
17770 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
17771 break;
17772 case OMPC_shared:
17773 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
17774 break;
17775 case OMPC_reduction:
17776 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
17777 "Unexpected lastprivate modifier.");
17779 VarList,
17781 ExtraModifier, OriginalSharingModifier),
17782 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
17783 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17784 break;
17785 case OMPC_task_reduction:
17787 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17788 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17789 break;
17790 case OMPC_in_reduction:
17792 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17793 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17794 break;
17795 case OMPC_linear:
17796 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
17797 "Unexpected linear modifier.");
17799 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
17800 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
17801 ColonLoc, Data.StepModifierLoc, EndLoc);
17802 break;
17803 case OMPC_aligned:
17804 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
17805 LParenLoc, ColonLoc, EndLoc);
17806 break;
17807 case OMPC_copyin:
17808 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
17809 break;
17810 case OMPC_copyprivate:
17811 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17812 break;
17813 case OMPC_flush:
17814 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
17815 break;
17816 case OMPC_depend:
17817 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
17818 "Unexpected depend modifier.");
17820 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
17821 ColonLoc, Data.OmpAllMemoryLoc},
17822 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
17823 break;
17824 case OMPC_map:
17825 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
17826 "Unexpected map modifier.");
17828 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
17829 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
17830 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
17831 ExtraModifierLoc, ColonLoc, VarList, Locs);
17832 break;
17833 case OMPC_to:
17834 Res =
17835 ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc,
17836 Data.ReductionOrMapperIdScopeSpec,
17837 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
17838 break;
17839 case OMPC_from:
17840 Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc,
17841 Data.ReductionOrMapperIdScopeSpec,
17842 Data.ReductionOrMapperId, ColonLoc, VarList,
17843 Locs);
17844 break;
17845 case OMPC_use_device_ptr:
17846 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
17847 break;
17848 case OMPC_use_device_addr:
17849 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
17850 break;
17851 case OMPC_is_device_ptr:
17852 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
17853 break;
17854 case OMPC_has_device_addr:
17855 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
17856 break;
17857 case OMPC_allocate: {
17860 SourceLocation Modifier1Loc, Modifier2Loc;
17861 if (!Data.AllocClauseModifiers.empty()) {
17862 assert(Data.AllocClauseModifiers.size() <= 2 &&
17863 "More allocate modifiers than expected");
17864 Modifier1 = Data.AllocClauseModifiers[0];
17865 Modifier1Loc = Data.AllocClauseModifiersLoc[0];
17866 if (Data.AllocClauseModifiers.size() == 2) {
17867 Modifier2 = Data.AllocClauseModifiers[1];
17868 Modifier2Loc = Data.AllocClauseModifiersLoc[1];
17869 }
17870 }
17872 Data.DepModOrTailExpr, Data.AllocateAlignment, Modifier1, Modifier1Loc,
17873 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
17874 EndLoc);
17875 break;
17876 }
17877 case OMPC_nontemporal:
17878 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
17879 break;
17880 case OMPC_inclusive:
17881 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17882 break;
17883 case OMPC_exclusive:
17884 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17885 break;
17886 case OMPC_affinity:
17887 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
17888 Data.DepModOrTailExpr, VarList);
17889 break;
17890 case OMPC_doacross:
17892 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
17893 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
17894 break;
17895 case OMPC_num_teams:
17896 Res = ActOnOpenMPNumTeamsClause(VarList, StartLoc, LParenLoc, EndLoc);
17897 break;
17898 case OMPC_thread_limit:
17899 Res = ActOnOpenMPThreadLimitClause(VarList, StartLoc, LParenLoc, EndLoc);
17900 break;
17901 case OMPC_if:
17902 case OMPC_depobj:
17903 case OMPC_final:
17904 case OMPC_num_threads:
17905 case OMPC_safelen:
17906 case OMPC_simdlen:
17907 case OMPC_sizes:
17908 case OMPC_allocator:
17909 case OMPC_collapse:
17910 case OMPC_default:
17911 case OMPC_proc_bind:
17912 case OMPC_schedule:
17913 case OMPC_ordered:
17914 case OMPC_nowait:
17915 case OMPC_untied:
17916 case OMPC_mergeable:
17917 case OMPC_threadprivate:
17918 case OMPC_groupprivate:
17919 case OMPC_read:
17920 case OMPC_write:
17921 case OMPC_update:
17922 case OMPC_capture:
17923 case OMPC_compare:
17924 case OMPC_seq_cst:
17925 case OMPC_acq_rel:
17926 case OMPC_acquire:
17927 case OMPC_release:
17928 case OMPC_relaxed:
17929 case OMPC_device:
17930 case OMPC_threads:
17931 case OMPC_simd:
17932 case OMPC_priority:
17933 case OMPC_grainsize:
17934 case OMPC_nogroup:
17935 case OMPC_num_tasks:
17936 case OMPC_hint:
17937 case OMPC_dist_schedule:
17938 case OMPC_defaultmap:
17939 case OMPC_unknown:
17940 case OMPC_uniform:
17941 case OMPC_unified_address:
17942 case OMPC_unified_shared_memory:
17943 case OMPC_reverse_offload:
17944 case OMPC_dynamic_allocators:
17945 case OMPC_atomic_default_mem_order:
17946 case OMPC_self_maps:
17947 case OMPC_device_type:
17948 case OMPC_match:
17949 case OMPC_order:
17950 case OMPC_at:
17951 case OMPC_severity:
17952 case OMPC_message:
17953 case OMPC_destroy:
17954 case OMPC_novariants:
17955 case OMPC_nocontext:
17956 case OMPC_detach:
17957 case OMPC_uses_allocators:
17958 case OMPC_when:
17959 case OMPC_bind:
17960 default:
17961 llvm_unreachable("Clause is not allowed.");
17962 }
17963 return Res;
17964}
17965
17967 ExprObjectKind OK,
17968 SourceLocation Loc) {
17969 ExprResult Res = SemaRef.BuildDeclRefExpr(
17970 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
17971 if (!Res.isUsable())
17972 return ExprError();
17973 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
17974 Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
17975 if (!Res.isUsable())
17976 return ExprError();
17977 }
17978 if (VK != VK_LValue && Res.get()->isGLValue()) {
17979 Res = SemaRef.DefaultLvalueConversion(Res.get());
17980 if (!Res.isUsable())
17981 return ExprError();
17982 }
17983 return Res;
17984}
17985
17987 SourceLocation StartLoc,
17988 SourceLocation LParenLoc,
17989 SourceLocation EndLoc) {
17991 SmallVector<Expr *, 8> PrivateCopies;
17992 unsigned OMPVersion = getLangOpts().OpenMP;
17993 bool IsImplicitClause =
17994 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17995 for (Expr *RefExpr : VarList) {
17996 assert(RefExpr && "NULL expr in OpenMP private clause.");
17997 SourceLocation ELoc;
17998 SourceRange ERange;
17999 Expr *SimpleRefExpr = RefExpr;
18000 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
18001 if (Res.second) {
18002 // It will be analyzed later.
18003 Vars.push_back(RefExpr);
18004 PrivateCopies.push_back(nullptr);
18005 }
18006 ValueDecl *D = Res.first;
18007 if (!D)
18008 continue;
18009
18010 QualType Type = D->getType();
18011 auto *VD = dyn_cast<VarDecl>(D);
18012
18013 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18014 // A variable that appears in a private clause must not have an incomplete
18015 // type or a reference type.
18016 if (SemaRef.RequireCompleteType(ELoc, Type,
18017 diag::err_omp_private_incomplete_type))
18018 continue;
18019 Type = Type.getNonReferenceType();
18020
18021 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18022 // A variable that is privatized must not have a const-qualified type
18023 // unless it is of class type with a mutable member. This restriction does
18024 // not apply to the firstprivate clause.
18025 //
18026 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
18027 // A variable that appears in a private clause must not have a
18028 // const-qualified type unless it is of class type with a mutable member.
18029 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc))
18030 continue;
18031
18032 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18033 // in a Construct]
18034 // Variables with the predetermined data-sharing attributes may not be
18035 // listed in data-sharing attributes clauses, except for the cases
18036 // listed below. For these exceptions only, listing a predetermined
18037 // variable in a data-sharing attribute clause is allowed and overrides
18038 // the variable's predetermined data-sharing attributes.
18039 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18040 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
18041 Diag(ELoc, diag::err_omp_wrong_dsa)
18042 << getOpenMPClauseNameForDiag(DVar.CKind)
18043 << getOpenMPClauseNameForDiag(OMPC_private);
18045 continue;
18046 }
18047
18048 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18049 // Variably modified types are not supported for tasks.
18051 isOpenMPTaskingDirective(CurrDir)) {
18052 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18053 << getOpenMPClauseNameForDiag(OMPC_private) << Type
18054 << getOpenMPDirectiveName(CurrDir, OMPVersion);
18055 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
18057 Diag(D->getLocation(),
18058 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18059 << D;
18060 continue;
18061 }
18062
18063 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18064 // A list item cannot appear in both a map clause and a data-sharing
18065 // attribute clause on the same construct
18066 //
18067 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18068 // A list item cannot appear in both a map clause and a data-sharing
18069 // attribute clause on the same construct unless the construct is a
18070 // combined construct.
18071 if ((getLangOpts().OpenMP <= 45 &&
18073 CurrDir == OMPD_target) {
18074 OpenMPClauseKind ConflictKind;
18075 if (DSAStack->checkMappableExprComponentListsForDecl(
18076 VD, /*CurrentRegionOnly=*/true,
18078 OpenMPClauseKind WhereFoundClauseKind) -> bool {
18079 ConflictKind = WhereFoundClauseKind;
18080 return true;
18081 })) {
18082 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18083 << getOpenMPClauseNameForDiag(OMPC_private)
18084 << getOpenMPClauseNameForDiag(ConflictKind)
18085 << getOpenMPDirectiveName(CurrDir, OMPVersion);
18087 continue;
18088 }
18089 }
18090
18091 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
18092 // A variable of class type (or array thereof) that appears in a private
18093 // clause requires an accessible, unambiguous default constructor for the
18094 // class type.
18095 // Generate helper private variable and initialize it with the default
18096 // value. The address of the original variable is replaced by the address of
18097 // the new private variable in CodeGen. This new variable is not added to
18098 // IdResolver, so the code in the OpenMP region uses original variable for
18099 // proper diagnostics.
18100 Type = Type.getUnqualifiedType();
18101 VarDecl *VDPrivate =
18102 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
18103 D->hasAttrs() ? &D->getAttrs() : nullptr,
18104 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18105 SemaRef.ActOnUninitializedDecl(VDPrivate);
18106 if (VDPrivate->isInvalidDecl())
18107 continue;
18108 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18109 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
18110
18111 DeclRefExpr *Ref = nullptr;
18112 if (!VD && !SemaRef.CurContext->isDependentContext()) {
18113 auto *FD = dyn_cast<FieldDecl>(D);
18114 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18115 if (VD)
18117 RefExpr->getExprLoc());
18118 else
18119 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
18120 }
18121 if (!IsImplicitClause)
18122 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
18123 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
18124 ? RefExpr->IgnoreParens()
18125 : Ref);
18126 PrivateCopies.push_back(VDPrivateRefExpr);
18127 }
18128
18129 if (Vars.empty())
18130 return nullptr;
18131
18132 return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
18133 Vars, PrivateCopies);
18134}
18135
18137 SourceLocation StartLoc,
18138 SourceLocation LParenLoc,
18139 SourceLocation EndLoc) {
18141 SmallVector<Expr *, 8> PrivateCopies;
18143 SmallVector<Decl *, 4> ExprCaptures;
18144 bool IsImplicitClause =
18145 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18146 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
18147 unsigned OMPVersion = getLangOpts().OpenMP;
18148
18149 for (Expr *RefExpr : VarList) {
18150 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
18151 SourceLocation ELoc;
18152 SourceRange ERange;
18153 Expr *SimpleRefExpr = RefExpr;
18154 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
18155 if (Res.second) {
18156 // It will be analyzed later.
18157 Vars.push_back(RefExpr);
18158 PrivateCopies.push_back(nullptr);
18159 Inits.push_back(nullptr);
18160 }
18161 ValueDecl *D = Res.first;
18162 if (!D)
18163 continue;
18164
18165 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
18166 QualType Type = D->getType();
18167 auto *VD = dyn_cast<VarDecl>(D);
18168
18169 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18170 // A variable that appears in a private clause must not have an incomplete
18171 // type or a reference type.
18172 if (SemaRef.RequireCompleteType(ELoc, Type,
18173 diag::err_omp_firstprivate_incomplete_type))
18174 continue;
18175 Type = Type.getNonReferenceType();
18176
18177 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
18178 // A variable of class type (or array thereof) that appears in a private
18179 // clause requires an accessible, unambiguous copy constructor for the
18180 // class type.
18181 QualType ElemType =
18183
18184 // If an implicit firstprivate variable found it was checked already.
18185 DSAStackTy::DSAVarData TopDVar;
18186 if (!IsImplicitClause) {
18187 DSAStackTy::DSAVarData DVar =
18188 DSAStack->getTopDSA(D, /*FromParent=*/false);
18189 TopDVar = DVar;
18190 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18191 bool IsConstant = ElemType.isConstant(getASTContext());
18192 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
18193 // A list item that specifies a given variable may not appear in more
18194 // than one clause on the same directive, except that a variable may be
18195 // specified in both firstprivate and lastprivate clauses.
18196 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18197 // A list item may appear in a firstprivate or lastprivate clause but not
18198 // both.
18199 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
18200 (isOpenMPDistributeDirective(CurrDir) ||
18201 DVar.CKind != OMPC_lastprivate) &&
18202 DVar.RefExpr) {
18203 Diag(ELoc, diag::err_omp_wrong_dsa)
18204 << getOpenMPClauseNameForDiag(DVar.CKind)
18205 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
18207 continue;
18208 }
18209
18210 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18211 // in a Construct]
18212 // Variables with the predetermined data-sharing attributes may not be
18213 // listed in data-sharing attributes clauses, except for the cases
18214 // listed below. For these exceptions only, listing a predetermined
18215 // variable in a data-sharing attribute clause is allowed and overrides
18216 // the variable's predetermined data-sharing attributes.
18217 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18218 // in a Construct, C/C++, p.2]
18219 // Variables with const-qualified type having no mutable member may be
18220 // listed in a firstprivate clause, even if they are static data members.
18221 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
18222 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
18223 Diag(ELoc, diag::err_omp_wrong_dsa)
18224 << getOpenMPClauseNameForDiag(DVar.CKind)
18225 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
18227 continue;
18228 }
18229
18230 // OpenMP [2.9.3.4, Restrictions, p.2]
18231 // A list item that is private within a parallel region must not appear
18232 // in a firstprivate clause on a worksharing construct if any of the
18233 // worksharing regions arising from the worksharing construct ever bind
18234 // to any of the parallel regions arising from the parallel construct.
18235 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18236 // A list item that is private within a teams region must not appear in a
18237 // firstprivate clause on a distribute construct if any of the distribute
18238 // regions arising from the distribute construct ever bind to any of the
18239 // teams regions arising from the teams construct.
18240 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18241 // A list item that appears in a reduction clause of a teams construct
18242 // must not appear in a firstprivate clause on a distribute construct if
18243 // any of the distribute regions arising from the distribute construct
18244 // ever bind to any of the teams regions arising from the teams construct.
18245 if ((isOpenMPWorksharingDirective(CurrDir) ||
18246 isOpenMPDistributeDirective(CurrDir)) &&
18247 !isOpenMPParallelDirective(CurrDir) &&
18248 !isOpenMPTeamsDirective(CurrDir)) {
18249 DVar = DSAStack->getImplicitDSA(D, true);
18250 if (DVar.CKind != OMPC_shared &&
18251 (isOpenMPParallelDirective(DVar.DKind) ||
18252 isOpenMPTeamsDirective(DVar.DKind) ||
18253 DVar.DKind == OMPD_unknown)) {
18254 Diag(ELoc, diag::err_omp_required_access)
18255 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
18256 << getOpenMPClauseNameForDiag(OMPC_shared);
18258 continue;
18259 }
18260 }
18261 // OpenMP [2.9.3.4, Restrictions, p.3]
18262 // A list item that appears in a reduction clause of a parallel construct
18263 // must not appear in a firstprivate clause on a worksharing or task
18264 // construct if any of the worksharing or task regions arising from the
18265 // worksharing or task construct ever bind to any of the parallel regions
18266 // arising from the parallel construct.
18267 // OpenMP [2.9.3.4, Restrictions, p.4]
18268 // A list item that appears in a reduction clause in worksharing
18269 // construct must not appear in a firstprivate clause in a task construct
18270 // encountered during execution of any of the worksharing regions arising
18271 // from the worksharing construct.
18272 if (isOpenMPTaskingDirective(CurrDir)) {
18273 DVar = DSAStack->hasInnermostDSA(
18274 D,
18275 [](OpenMPClauseKind C, bool AppliedToPointee) {
18276 return C == OMPC_reduction && !AppliedToPointee;
18277 },
18278 [](OpenMPDirectiveKind K) {
18279 return isOpenMPParallelDirective(K) ||
18282 },
18283 /*FromParent=*/true);
18284 if (DVar.CKind == OMPC_reduction &&
18285 (isOpenMPParallelDirective(DVar.DKind) ||
18286 isOpenMPWorksharingDirective(DVar.DKind) ||
18287 isOpenMPTeamsDirective(DVar.DKind))) {
18288 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
18289 << getOpenMPDirectiveName(DVar.DKind, OMPVersion);
18291 continue;
18292 }
18293 }
18294
18295 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18296 // A list item cannot appear in both a map clause and a data-sharing
18297 // attribute clause on the same construct
18298 //
18299 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18300 // A list item cannot appear in both a map clause and a data-sharing
18301 // attribute clause on the same construct unless the construct is a
18302 // combined construct.
18303 if ((getLangOpts().OpenMP <= 45 &&
18305 CurrDir == OMPD_target) {
18306 OpenMPClauseKind ConflictKind;
18307 if (DSAStack->checkMappableExprComponentListsForDecl(
18308 VD, /*CurrentRegionOnly=*/true,
18309 [&ConflictKind](
18311 OpenMPClauseKind WhereFoundClauseKind) {
18312 ConflictKind = WhereFoundClauseKind;
18313 return true;
18314 })) {
18315 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18316 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
18317 << getOpenMPClauseNameForDiag(ConflictKind)
18318 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
18319 OMPVersion);
18321 continue;
18322 }
18323 }
18324 }
18325
18326 // Variably modified types are not supported for tasks.
18328 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
18329 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18330 << getOpenMPClauseNameForDiag(OMPC_firstprivate) << Type
18331 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
18332 OMPVersion);
18333 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
18335 Diag(D->getLocation(),
18336 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18337 << D;
18338 continue;
18339 }
18340
18341 Type = Type.getUnqualifiedType();
18342 VarDecl *VDPrivate =
18343 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
18344 D->hasAttrs() ? &D->getAttrs() : nullptr,
18345 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18346 // Generate helper private variable and initialize it with the value of the
18347 // original variable. The address of the original variable is replaced by
18348 // the address of the new private variable in the CodeGen. This new variable
18349 // is not added to IdResolver, so the code in the OpenMP region uses
18350 // original variable for proper diagnostics and variable capturing.
18351 Expr *VDInitRefExpr = nullptr;
18352 // For arrays generate initializer for single element and replace it by the
18353 // original array element in CodeGen.
18354 if (Type->isArrayType()) {
18355 VarDecl *VDInit =
18356 buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName());
18357 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc);
18358 Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get();
18359 ElemType = ElemType.getUnqualifiedType();
18360 VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(),
18361 ElemType, ".firstprivate.temp");
18362 InitializedEntity Entity =
18365
18366 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
18367 ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init);
18368 if (Result.isInvalid())
18369 VDPrivate->setInvalidDecl();
18370 else
18371 VDPrivate->setInit(Result.getAs<Expr>());
18372 // Remove temp variable declaration.
18373 getASTContext().Deallocate(VDInitTemp);
18374 } else {
18375 VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type,
18376 ".firstprivate.temp");
18377 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(),
18378 RefExpr->getExprLoc());
18379 SemaRef.AddInitializerToDecl(
18380 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
18381 /*DirectInit=*/false);
18382 }
18383 if (VDPrivate->isInvalidDecl()) {
18384 if (IsImplicitClause) {
18385 Diag(RefExpr->getExprLoc(),
18386 diag::note_omp_task_predetermined_firstprivate_here);
18387 }
18388 continue;
18389 }
18390 SemaRef.CurContext->addDecl(VDPrivate);
18391 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18392 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(),
18393 RefExpr->getExprLoc());
18394 DeclRefExpr *Ref = nullptr;
18395 if (!VD && !SemaRef.CurContext->isDependentContext()) {
18396 if (TopDVar.CKind == OMPC_lastprivate) {
18397 Ref = TopDVar.PrivateCopy;
18398 } else {
18399 auto *FD = dyn_cast<FieldDecl>(D);
18400 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18401 if (VD)
18402 Ref =
18404 RefExpr->getExprLoc());
18405 else
18406 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
18407 if (VD || !isOpenMPCapturedDecl(D))
18408 ExprCaptures.push_back(Ref->getDecl());
18409 }
18410 }
18411 if (!IsImplicitClause)
18412 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
18413 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
18414 ? RefExpr->IgnoreParens()
18415 : Ref);
18416 PrivateCopies.push_back(VDPrivateRefExpr);
18417 Inits.push_back(VDInitRefExpr);
18418 }
18419
18420 if (Vars.empty())
18421 return nullptr;
18422
18424 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
18425 buildPreInits(getASTContext(), ExprCaptures));
18426}
18427
18430 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
18431 SourceLocation LParenLoc, SourceLocation EndLoc) {
18432 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
18433 assert(ColonLoc.isValid() && "Colon location must be valid.");
18434 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
18435 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
18436 /*Last=*/OMPC_LASTPRIVATE_unknown)
18437 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
18438 return nullptr;
18439 }
18440
18442 SmallVector<Expr *, 8> SrcExprs;
18443 SmallVector<Expr *, 8> DstExprs;
18444 SmallVector<Expr *, 8> AssignmentOps;
18445 SmallVector<Decl *, 4> ExprCaptures;
18446 SmallVector<Expr *, 4> ExprPostUpdates;
18447 for (Expr *RefExpr : VarList) {
18448 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18449 SourceLocation ELoc;
18450 SourceRange ERange;
18451 Expr *SimpleRefExpr = RefExpr;
18452 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
18453 if (Res.second) {
18454 // It will be analyzed later.
18455 Vars.push_back(RefExpr);
18456 SrcExprs.push_back(nullptr);
18457 DstExprs.push_back(nullptr);
18458 AssignmentOps.push_back(nullptr);
18459 }
18460 ValueDecl *D = Res.first;
18461 if (!D)
18462 continue;
18463
18464 QualType Type = D->getType();
18465 auto *VD = dyn_cast<VarDecl>(D);
18466
18467 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
18468 // A variable that appears in a lastprivate clause must not have an
18469 // incomplete type or a reference type.
18470 if (SemaRef.RequireCompleteType(ELoc, Type,
18471 diag::err_omp_lastprivate_incomplete_type))
18472 continue;
18473 Type = Type.getNonReferenceType();
18474
18475 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18476 // A variable that is privatized must not have a const-qualified type
18477 // unless it is of class type with a mutable member. This restriction does
18478 // not apply to the firstprivate clause.
18479 //
18480 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
18481 // A variable that appears in a lastprivate clause must not have a
18482 // const-qualified type unless it is of class type with a mutable member.
18483 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc))
18484 continue;
18485
18486 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
18487 // A list item that appears in a lastprivate clause with the conditional
18488 // modifier must be a scalar variable.
18489 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
18490 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
18491 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
18493 Diag(D->getLocation(),
18494 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18495 << D;
18496 continue;
18497 }
18498
18499 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18500 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18501 // in a Construct]
18502 // Variables with the predetermined data-sharing attributes may not be
18503 // listed in data-sharing attributes clauses, except for the cases
18504 // listed below.
18505 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18506 // A list item may appear in a firstprivate or lastprivate clause but not
18507 // both.
18508 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18509 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
18510 (isOpenMPDistributeDirective(CurrDir) ||
18511 DVar.CKind != OMPC_firstprivate) &&
18512 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
18513 Diag(ELoc, diag::err_omp_wrong_dsa)
18514 << getOpenMPClauseNameForDiag(DVar.CKind)
18515 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
18517 continue;
18518 }
18519
18520 // OpenMP [2.14.3.5, Restrictions, p.2]
18521 // A list item that is private within a parallel region, or that appears in
18522 // the reduction clause of a parallel construct, must not appear in a
18523 // lastprivate clause on a worksharing construct if any of the corresponding
18524 // worksharing regions ever binds to any of the corresponding parallel
18525 // regions.
18526 DSAStackTy::DSAVarData TopDVar = DVar;
18527 if (isOpenMPWorksharingDirective(CurrDir) &&
18528 !isOpenMPParallelDirective(CurrDir) &&
18529 !isOpenMPTeamsDirective(CurrDir)) {
18530 DVar = DSAStack->getImplicitDSA(D, true);
18531 if (DVar.CKind != OMPC_shared) {
18532 Diag(ELoc, diag::err_omp_required_access)
18533 << getOpenMPClauseNameForDiag(OMPC_lastprivate)
18534 << getOpenMPClauseNameForDiag(OMPC_shared);
18536 continue;
18537 }
18538 }
18539
18540 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
18541 // A variable of class type (or array thereof) that appears in a
18542 // lastprivate clause requires an accessible, unambiguous default
18543 // constructor for the class type, unless the list item is also specified
18544 // in a firstprivate clause.
18545 // A variable of class type (or array thereof) that appears in a
18546 // lastprivate clause requires an accessible, unambiguous copy assignment
18547 // operator for the class type.
18549 VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(),
18550 Type.getUnqualifiedType(), ".lastprivate.src",
18551 D->hasAttrs() ? &D->getAttrs() : nullptr);
18552 DeclRefExpr *PseudoSrcExpr =
18553 buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc);
18554 VarDecl *DstVD =
18555 buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst",
18556 D->hasAttrs() ? &D->getAttrs() : nullptr);
18557 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
18558 // For arrays generate assignment operation for single element and replace
18559 // it by the original array element in CodeGen.
18560 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
18561 PseudoDstExpr, PseudoSrcExpr);
18562 if (AssignmentOp.isInvalid())
18563 continue;
18564 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
18565 /*DiscardedValue=*/false);
18566 if (AssignmentOp.isInvalid())
18567 continue;
18568
18569 DeclRefExpr *Ref = nullptr;
18570 if (!VD && !SemaRef.CurContext->isDependentContext()) {
18571 if (TopDVar.CKind == OMPC_firstprivate) {
18572 Ref = TopDVar.PrivateCopy;
18573 } else {
18574 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
18575 if (!isOpenMPCapturedDecl(D))
18576 ExprCaptures.push_back(Ref->getDecl());
18577 }
18578 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
18579 (!isOpenMPCapturedDecl(D) &&
18580 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
18581 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
18582 if (!RefRes.isUsable())
18583 continue;
18584 ExprResult PostUpdateRes =
18585 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
18586 SimpleRefExpr, RefRes.get());
18587 if (!PostUpdateRes.isUsable())
18588 continue;
18589 ExprPostUpdates.push_back(
18590 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
18591 }
18592 }
18593 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
18594 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
18595 ? RefExpr->IgnoreParens()
18596 : Ref);
18597 SrcExprs.push_back(PseudoSrcExpr);
18598 DstExprs.push_back(PseudoDstExpr);
18599 AssignmentOps.push_back(AssignmentOp.get());
18600 }
18601
18602 if (Vars.empty())
18603 return nullptr;
18604
18606 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
18607 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
18608 buildPreInits(getASTContext(), ExprCaptures),
18609 buildPostUpdate(SemaRef, ExprPostUpdates));
18610}
18611
18613 SourceLocation StartLoc,
18614 SourceLocation LParenLoc,
18615 SourceLocation EndLoc) {
18617 for (Expr *RefExpr : VarList) {
18618 assert(RefExpr && "NULL expr in OpenMP shared clause.");
18619 SourceLocation ELoc;
18620 SourceRange ERange;
18621 Expr *SimpleRefExpr = RefExpr;
18622 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
18623 if (Res.second) {
18624 // It will be analyzed later.
18625 Vars.push_back(RefExpr);
18626 }
18627 ValueDecl *D = Res.first;
18628 if (!D)
18629 continue;
18630
18631 auto *VD = dyn_cast<VarDecl>(D);
18632 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18633 // in a Construct]
18634 // Variables with the predetermined data-sharing attributes may not be
18635 // listed in data-sharing attributes clauses, except for the cases
18636 // listed below. For these exceptions only, listing a predetermined
18637 // variable in a data-sharing attribute clause is allowed and overrides
18638 // the variable's predetermined data-sharing attributes.
18639 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18640 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
18641 DVar.RefExpr) {
18642 Diag(ELoc, diag::err_omp_wrong_dsa)
18643 << getOpenMPClauseNameForDiag(DVar.CKind)
18644 << getOpenMPClauseNameForDiag(OMPC_shared);
18646 continue;
18647 }
18648
18649 DeclRefExpr *Ref = nullptr;
18650 if (!VD && isOpenMPCapturedDecl(D) &&
18651 !SemaRef.CurContext->isDependentContext())
18652 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
18653 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
18654 Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext())
18655 ? RefExpr->IgnoreParens()
18656 : Ref);
18657 }
18658
18659 if (Vars.empty())
18660 return nullptr;
18661
18662 return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
18663 Vars);
18664}
18665
18666namespace {
18667class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
18668 DSAStackTy *Stack;
18669
18670public:
18671 bool VisitDeclRefExpr(DeclRefExpr *E) {
18672 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
18673 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
18674 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
18675 return false;
18676 if (DVar.CKind != OMPC_unknown)
18677 return true;
18678 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
18679 VD,
18680 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
18681 return isOpenMPPrivate(C) && !AppliedToPointee;
18682 },
18683 [](OpenMPDirectiveKind) { return true; },
18684 /*FromParent=*/true);
18685 return DVarPrivate.CKind != OMPC_unknown;
18686 }
18687 return false;
18688 }
18689 bool VisitStmt(Stmt *S) {
18690 for (Stmt *Child : S->children()) {
18691 if (Child && Visit(Child))
18692 return true;
18693 }
18694 return false;
18695 }
18696 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
18697};
18698} // namespace
18699
18700namespace {
18701// Transform MemberExpression for specified FieldDecl of current class to
18702// DeclRefExpr to specified OMPCapturedExprDecl.
18703class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
18704 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
18705 ValueDecl *Field = nullptr;
18706 DeclRefExpr *CapturedExpr = nullptr;
18707
18708public:
18709 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
18710 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
18711
18712 ExprResult TransformMemberExpr(MemberExpr *E) {
18714 E->getMemberDecl() == Field) {
18715 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
18716 return CapturedExpr;
18717 }
18718 return BaseTransform::TransformMemberExpr(E);
18719 }
18720 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
18721};
18722} // namespace
18723
18724template <typename T, typename U>
18726 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
18727 for (U &Set : Lookups) {
18728 for (auto *D : Set) {
18729 if (T Res = Gen(cast<ValueDecl>(D)))
18730 return Res;
18731 }
18732 }
18733 return T();
18734}
18735
18737 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
18738
18739 for (auto *RD : D->redecls()) {
18740 // Don't bother with extra checks if we already know this one isn't visible.
18741 if (RD == D)
18742 continue;
18743
18744 auto ND = cast<NamedDecl>(RD);
18745 if (LookupResult::isVisible(SemaRef, ND))
18746 return ND;
18747 }
18748
18749 return nullptr;
18750}
18751
18752static void
18754 SourceLocation Loc, QualType Ty,
18756 // Find all of the associated namespaces and classes based on the
18757 // arguments we have.
18758 Sema::AssociatedNamespaceSet AssociatedNamespaces;
18759 Sema::AssociatedClassSet AssociatedClasses;
18760 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
18761 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
18762 AssociatedClasses);
18763
18764 // C++ [basic.lookup.argdep]p3:
18765 // Let X be the lookup set produced by unqualified lookup (3.4.1)
18766 // and let Y be the lookup set produced by argument dependent
18767 // lookup (defined as follows). If X contains [...] then Y is
18768 // empty. Otherwise Y is the set of declarations found in the
18769 // namespaces associated with the argument types as described
18770 // below. The set of declarations found by the lookup of the name
18771 // is the union of X and Y.
18772 //
18773 // Here, we compute Y and add its members to the overloaded
18774 // candidate set.
18775 for (auto *NS : AssociatedNamespaces) {
18776 // When considering an associated namespace, the lookup is the
18777 // same as the lookup performed when the associated namespace is
18778 // used as a qualifier (3.4.3.2) except that:
18779 //
18780 // -- Any using-directives in the associated namespace are
18781 // ignored.
18782 //
18783 // -- Any namespace-scope friend functions declared in
18784 // associated classes are visible within their respective
18785 // namespaces even if they are not visible during an ordinary
18786 // lookup (11.4).
18787 DeclContext::lookup_result R = NS->lookup(Id.getName());
18788 for (auto *D : R) {
18789 auto *Underlying = D;
18790 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
18791 Underlying = USD->getTargetDecl();
18792
18793 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
18794 !isa<OMPDeclareMapperDecl>(Underlying))
18795 continue;
18796
18797 if (!SemaRef.isVisible(D)) {
18798 D = findAcceptableDecl(SemaRef, D);
18799 if (!D)
18800 continue;
18801 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
18802 Underlying = USD->getTargetDecl();
18803 }
18804 Lookups.emplace_back();
18805 Lookups.back().addDecl(Underlying);
18806 }
18807 }
18808}
18809
18810static ExprResult
18812 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
18813 const DeclarationNameInfo &ReductionId, QualType Ty,
18814 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
18815 if (ReductionIdScopeSpec.isInvalid())
18816 return ExprError();
18817 SmallVector<UnresolvedSet<8>, 4> Lookups;
18818 if (S) {
18819 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18820 Lookup.suppressDiagnostics();
18821 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec,
18822 /*ObjectType=*/QualType())) {
18823 NamedDecl *D = Lookup.getRepresentativeDecl();
18824 do {
18825 S = S->getParent();
18826 } while (S && !S->isDeclScope(D));
18827 if (S)
18828 S = S->getParent();
18829 Lookups.emplace_back();
18830 Lookups.back().append(Lookup.begin(), Lookup.end());
18831 Lookup.clear();
18832 }
18833 } else if (auto *ULE =
18834 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
18835 Lookups.push_back(UnresolvedSet<8>());
18836 Decl *PrevD = nullptr;
18837 for (NamedDecl *D : ULE->decls()) {
18838 if (D == PrevD)
18839 Lookups.push_back(UnresolvedSet<8>());
18840 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
18841 Lookups.back().addDecl(DRD);
18842 PrevD = D;
18843 }
18844 }
18845 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
18849 return !D->isInvalidDecl() &&
18850 (D->getType()->isDependentType() ||
18851 D->getType()->isInstantiationDependentType() ||
18852 D->getType()->containsUnexpandedParameterPack());
18853 })) {
18854 UnresolvedSet<8> ResSet;
18855 for (const UnresolvedSet<8> &Set : Lookups) {
18856 if (Set.empty())
18857 continue;
18858 ResSet.append(Set.begin(), Set.end());
18859 // The last item marks the end of all declarations at the specified scope.
18860 ResSet.addDecl(Set[Set.size() - 1]);
18861 }
18863 SemaRef.Context, /*NamingClass=*/nullptr,
18864 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
18865 /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false,
18866 /*KnownInstantiationDependent=*/false);
18867 }
18868 // Lookup inside the classes.
18869 // C++ [over.match.oper]p3:
18870 // For a unary operator @ with an operand of a type whose
18871 // cv-unqualified version is T1, and for a binary operator @ with
18872 // a left operand of a type whose cv-unqualified version is T1 and
18873 // a right operand of a type whose cv-unqualified version is T2,
18874 // three sets of candidate functions, designated member
18875 // candidates, non-member candidates and built-in candidates, are
18876 // constructed as follows:
18877 // -- If T1 is a complete class type or a class currently being
18878 // defined, the set of member candidates is the result of the
18879 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
18880 // the set of member candidates is empty.
18881 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18882 Lookup.suppressDiagnostics();
18883 if (Ty->isRecordType()) {
18884 // Complete the type if it can be completed.
18885 // If the type is neither complete nor being defined, bail out now.
18886 bool IsComplete = SemaRef.isCompleteType(Loc, Ty);
18887 auto *RD = Ty->castAsRecordDecl();
18888 if (IsComplete || RD->isBeingDefined()) {
18889 Lookup.clear();
18890 SemaRef.LookupQualifiedName(Lookup, RD);
18891 if (Lookup.empty()) {
18892 Lookups.emplace_back();
18893 Lookups.back().append(Lookup.begin(), Lookup.end());
18894 }
18895 }
18896 }
18897 // Perform ADL.
18898 if (SemaRef.getLangOpts().CPlusPlus)
18899 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
18901 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
18902 if (!D->isInvalidDecl() &&
18903 SemaRef.Context.hasSameType(D->getType(), Ty))
18904 return D;
18905 return nullptr;
18906 }))
18907 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
18908 VK_LValue, Loc);
18909 if (SemaRef.getLangOpts().CPlusPlus) {
18911 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
18912 if (!D->isInvalidDecl() &&
18913 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
18915 SemaRef.getASTContext()))
18916 return D;
18917 return nullptr;
18918 })) {
18919 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
18920 /*DetectVirtual=*/false);
18921 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
18922 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
18923 VD->getType().getUnqualifiedType()))) {
18924 if (SemaRef.CheckBaseClassAccess(
18925 Loc, VD->getType(), Ty, Paths.front(),
18926 /*DiagID=*/0) != Sema::AR_inaccessible) {
18927 SemaRef.BuildBasePathArray(Paths, BasePath);
18928 return SemaRef.BuildDeclRefExpr(
18929 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc);
18930 }
18931 }
18932 }
18933 }
18934 }
18935 if (ReductionIdScopeSpec.isSet()) {
18936 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
18937 << Ty << Range;
18938 return ExprError();
18939 }
18940 return ExprEmpty();
18941}
18942
18943namespace {
18944/// Data for the reduction-based clauses.
18945struct ReductionData {
18946 /// List of original reduction items.
18947 SmallVector<Expr *, 8> Vars;
18948 /// List of private copies of the reduction items.
18949 SmallVector<Expr *, 8> Privates;
18950 /// LHS expressions for the reduction_op expressions.
18951 SmallVector<Expr *, 8> LHSs;
18952 /// RHS expressions for the reduction_op expressions.
18953 SmallVector<Expr *, 8> RHSs;
18954 /// Reduction operation expression.
18955 SmallVector<Expr *, 8> ReductionOps;
18956 /// inscan copy operation expressions.
18957 SmallVector<Expr *, 8> InscanCopyOps;
18958 /// inscan copy temp array expressions for prefix sums.
18959 SmallVector<Expr *, 8> InscanCopyArrayTemps;
18960 /// inscan copy temp array element expressions for prefix sums.
18961 SmallVector<Expr *, 8> InscanCopyArrayElems;
18962 /// Taskgroup descriptors for the corresponding reduction items in
18963 /// in_reduction clauses.
18964 SmallVector<Expr *, 8> TaskgroupDescriptors;
18965 /// List of captures for clause.
18966 SmallVector<Decl *, 4> ExprCaptures;
18967 /// List of postupdate expressions.
18968 SmallVector<Expr *, 4> ExprPostUpdates;
18969 /// Reduction modifier.
18970 unsigned RedModifier = 0;
18971 /// Original modifier.
18972 unsigned OrigSharingModifier = 0;
18973 /// Private Variable Reduction
18974 SmallVector<bool, 8> IsPrivateVarReduction;
18975 ReductionData() = delete;
18976 /// Reserves required memory for the reduction data.
18977 ReductionData(unsigned Size, unsigned Modifier = 0, unsigned OrgModifier = 0)
18978 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
18979 Vars.reserve(Size);
18980 Privates.reserve(Size);
18981 LHSs.reserve(Size);
18982 RHSs.reserve(Size);
18983 ReductionOps.reserve(Size);
18984 IsPrivateVarReduction.reserve(Size);
18985 if (RedModifier == OMPC_REDUCTION_inscan) {
18986 InscanCopyOps.reserve(Size);
18987 InscanCopyArrayTemps.reserve(Size);
18988 InscanCopyArrayElems.reserve(Size);
18989 }
18990 TaskgroupDescriptors.reserve(Size);
18991 ExprCaptures.reserve(Size);
18992 ExprPostUpdates.reserve(Size);
18993 }
18994 /// Stores reduction item and reduction operation only (required for dependent
18995 /// reduction item).
18996 void push(Expr *Item, Expr *ReductionOp) {
18997 Vars.emplace_back(Item);
18998 Privates.emplace_back(nullptr);
18999 LHSs.emplace_back(nullptr);
19000 RHSs.emplace_back(nullptr);
19001 ReductionOps.emplace_back(ReductionOp);
19002 IsPrivateVarReduction.emplace_back(false);
19003 TaskgroupDescriptors.emplace_back(nullptr);
19004 if (RedModifier == OMPC_REDUCTION_inscan) {
19005 InscanCopyOps.push_back(nullptr);
19006 InscanCopyArrayTemps.push_back(nullptr);
19007 InscanCopyArrayElems.push_back(nullptr);
19008 }
19009 }
19010 /// Stores reduction data.
19011 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
19012 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
19013 Expr *CopyArrayElem, bool IsPrivate) {
19014 Vars.emplace_back(Item);
19015 Privates.emplace_back(Private);
19016 LHSs.emplace_back(LHS);
19017 RHSs.emplace_back(RHS);
19018 ReductionOps.emplace_back(ReductionOp);
19019 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
19020 if (RedModifier == OMPC_REDUCTION_inscan) {
19021 InscanCopyOps.push_back(CopyOp);
19022 InscanCopyArrayTemps.push_back(CopyArrayTemp);
19023 InscanCopyArrayElems.push_back(CopyArrayElem);
19024 } else {
19025 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
19026 CopyArrayElem == nullptr &&
19027 "Copy operation must be used for inscan reductions only.");
19028 }
19029 IsPrivateVarReduction.emplace_back(IsPrivate);
19030 }
19031};
19032} // namespace
19033
19035 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
19036 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
19037 const Expr *Length = OASE->getLength();
19038 if (Length == nullptr) {
19039 // For array sections of the form [1:] or [:], we would need to analyze
19040 // the lower bound...
19041 if (OASE->getColonLocFirst().isValid())
19042 return false;
19043
19044 // This is an array subscript which has implicit length 1!
19045 SingleElement = true;
19046 ArraySizes.push_back(llvm::APSInt::get(1));
19047 } else {
19048 Expr::EvalResult Result;
19049 if (!Length->EvaluateAsInt(Result, Context))
19050 return false;
19051
19052 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19053 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
19054 ArraySizes.push_back(ConstantLengthValue);
19055 }
19056
19057 // Get the base of this array section and walk up from there.
19058 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
19059
19060 // We require length = 1 for all array sections except the right-most to
19061 // guarantee that the memory region is contiguous and has no holes in it.
19062 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) {
19063 Length = TempOASE->getLength();
19064 if (Length == nullptr) {
19065 // For array sections of the form [1:] or [:], we would need to analyze
19066 // the lower bound...
19067 if (OASE->getColonLocFirst().isValid())
19068 return false;
19069
19070 // This is an array subscript which has implicit length 1!
19071 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
19072 ArraySizes.push_back(ConstantOne);
19073 } else {
19074 Expr::EvalResult Result;
19075 if (!Length->EvaluateAsInt(Result, Context))
19076 return false;
19077
19078 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19079 if (ConstantLengthValue.getSExtValue() != 1)
19080 return false;
19081
19082 ArraySizes.push_back(ConstantLengthValue);
19083 }
19084 Base = TempOASE->getBase()->IgnoreParenImpCasts();
19085 }
19086
19087 // If we have a single element, we don't need to add the implicit lengths.
19088 if (!SingleElement) {
19089 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
19090 // Has implicit length 1!
19091 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
19092 ArraySizes.push_back(ConstantOne);
19093 Base = TempASE->getBase()->IgnoreParenImpCasts();
19094 }
19095 }
19096
19097 // This array section can be privatized as a single value or as a constant
19098 // sized array.
19099 return true;
19100}
19101
19102static BinaryOperatorKind
19104 if (BOK == BO_Add)
19105 return BO_AddAssign;
19106 if (BOK == BO_Mul)
19107 return BO_MulAssign;
19108 if (BOK == BO_And)
19109 return BO_AndAssign;
19110 if (BOK == BO_Or)
19111 return BO_OrAssign;
19112 if (BOK == BO_Xor)
19113 return BO_XorAssign;
19114 return BOK;
19115}
19116
19118 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
19119 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19120 SourceLocation ColonLoc, SourceLocation EndLoc,
19121 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19122 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
19123 DeclarationName DN = ReductionId.getName();
19125 BinaryOperatorKind BOK = BO_Comma;
19126
19127 ASTContext &Context = S.Context;
19128 // OpenMP [2.14.3.6, reduction clause]
19129 // C
19130 // reduction-identifier is either an identifier or one of the following
19131 // operators: +, -, *, &, |, ^, && and ||
19132 // C++
19133 // reduction-identifier is either an id-expression or one of the following
19134 // operators: +, -, *, &, |, ^, && and ||
19135 switch (OOK) {
19136 case OO_Plus:
19137 BOK = BO_Add;
19138 break;
19139 case OO_Minus:
19140 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
19141 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
19142 // reduction identifier.
19143 if (S.LangOpts.OpenMP > 52)
19144 BOK = BO_Comma;
19145 else
19146 BOK = BO_Add;
19147 break;
19148 case OO_Star:
19149 BOK = BO_Mul;
19150 break;
19151 case OO_Amp:
19152 BOK = BO_And;
19153 break;
19154 case OO_Pipe:
19155 BOK = BO_Or;
19156 break;
19157 case OO_Caret:
19158 BOK = BO_Xor;
19159 break;
19160 case OO_AmpAmp:
19161 BOK = BO_LAnd;
19162 break;
19163 case OO_PipePipe:
19164 BOK = BO_LOr;
19165 break;
19166 case OO_New:
19167 case OO_Delete:
19168 case OO_Array_New:
19169 case OO_Array_Delete:
19170 case OO_Slash:
19171 case OO_Percent:
19172 case OO_Tilde:
19173 case OO_Exclaim:
19174 case OO_Equal:
19175 case OO_Less:
19176 case OO_Greater:
19177 case OO_LessEqual:
19178 case OO_GreaterEqual:
19179 case OO_PlusEqual:
19180 case OO_MinusEqual:
19181 case OO_StarEqual:
19182 case OO_SlashEqual:
19183 case OO_PercentEqual:
19184 case OO_CaretEqual:
19185 case OO_AmpEqual:
19186 case OO_PipeEqual:
19187 case OO_LessLess:
19188 case OO_GreaterGreater:
19189 case OO_LessLessEqual:
19190 case OO_GreaterGreaterEqual:
19191 case OO_EqualEqual:
19192 case OO_ExclaimEqual:
19193 case OO_Spaceship:
19194 case OO_PlusPlus:
19195 case OO_MinusMinus:
19196 case OO_Comma:
19197 case OO_ArrowStar:
19198 case OO_Arrow:
19199 case OO_Call:
19200 case OO_Subscript:
19201 case OO_Conditional:
19202 case OO_Coawait:
19204 llvm_unreachable("Unexpected reduction identifier");
19205 case OO_None:
19206 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
19207 if (II->isStr("max"))
19208 BOK = BO_GT;
19209 else if (II->isStr("min"))
19210 BOK = BO_LT;
19211 }
19212 break;
19213 }
19214
19215 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
19216 // A reduction clause with the minus (-) operator was deprecated
19217 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
19218 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
19219
19220 SourceRange ReductionIdRange;
19221 if (ReductionIdScopeSpec.isValid())
19222 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
19223 else
19224 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
19225 ReductionIdRange.setEnd(ReductionId.getEndLoc());
19226
19227 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
19228 bool FirstIter = true;
19229 for (Expr *RefExpr : VarList) {
19230 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
19231 // OpenMP [2.1, C/C++]
19232 // A list item is a variable or array section, subject to the restrictions
19233 // specified in Section 2.4 on page 42 and in each of the sections
19234 // describing clauses and directives for which a list appears.
19235 // OpenMP [2.14.3.3, Restrictions, p.1]
19236 // A variable that is part of another variable (as an array or
19237 // structure element) cannot appear in a private clause.
19238 if (!FirstIter && IR != ER)
19239 ++IR;
19240 FirstIter = false;
19241 SourceLocation ELoc;
19242 SourceRange ERange;
19243 bool IsPrivate = false;
19244 Expr *SimpleRefExpr = RefExpr;
19245 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
19246 /*AllowArraySection=*/true);
19247 if (Res.second) {
19248 // Try to find 'declare reduction' corresponding construct before using
19249 // builtin/overloaded operators.
19250 QualType Type = Context.DependentTy;
19251 CXXCastPath BasePath;
19252 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19253 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19254 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19255 Expr *ReductionOp = nullptr;
19256 if (S.CurContext->isDependentContext() &&
19257 (DeclareReductionRef.isUnset() ||
19258 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
19259 ReductionOp = DeclareReductionRef.get();
19260 // It will be analyzed later.
19261 RD.push(RefExpr, ReductionOp);
19262 }
19263 ValueDecl *D = Res.first;
19264 if (!D)
19265 continue;
19266
19267 Expr *TaskgroupDescriptor = nullptr;
19268 QualType Type;
19269 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
19270 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
19271 if (ASE) {
19272 Type = ASE->getType().getNonReferenceType();
19273 } else if (OASE) {
19274 QualType BaseType =
19276 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
19277 Type = ATy->getElementType();
19278 else
19279 Type = BaseType->getPointeeType();
19280 Type = Type.getNonReferenceType();
19281 } else {
19282 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
19283 }
19284 auto *VD = dyn_cast<VarDecl>(D);
19285
19286 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19287 // A variable that appears in a private clause must not have an incomplete
19288 // type or a reference type.
19289 if (S.RequireCompleteType(ELoc, D->getType(),
19290 diag::err_omp_reduction_incomplete_type))
19291 continue;
19292 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19293 // A list item that appears in a reduction clause must not be
19294 // const-qualified.
19295 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
19296 /*AcceptIfMutable=*/false, ASE || OASE))
19297 continue;
19298
19299 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
19300 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
19301 // If a list-item is a reference type then it must bind to the same object
19302 // for all threads of the team.
19303 if (!ASE && !OASE) {
19304 if (VD) {
19305 VarDecl *VDDef = VD->getDefinition();
19306 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
19307 DSARefChecker Check(Stack);
19308 if (Check.Visit(VDDef->getInit())) {
19309 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
19310 << getOpenMPClauseNameForDiag(ClauseKind) << ERange;
19311 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
19312 continue;
19313 }
19314 }
19315 }
19316
19317 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19318 // in a Construct]
19319 // Variables with the predetermined data-sharing attributes may not be
19320 // listed in data-sharing attributes clauses, except for the cases
19321 // listed below. For these exceptions only, listing a predetermined
19322 // variable in a data-sharing attribute clause is allowed and overrides
19323 // the variable's predetermined data-sharing attributes.
19324 // OpenMP [2.14.3.6, Restrictions, p.3]
19325 // Any number of reduction clauses can be specified on the directive,
19326 // but a list item can appear only once in the reduction clauses for that
19327 // directive.
19328 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19329 if (DVar.CKind == OMPC_reduction) {
19330 S.Diag(ELoc, diag::err_omp_once_referenced)
19331 << getOpenMPClauseNameForDiag(ClauseKind);
19332 if (DVar.RefExpr)
19333 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
19334 continue;
19335 }
19336 if (DVar.CKind != OMPC_unknown) {
19337 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19338 << getOpenMPClauseNameForDiag(DVar.CKind)
19339 << getOpenMPClauseNameForDiag(OMPC_reduction);
19340 reportOriginalDsa(S, Stack, D, DVar);
19341 continue;
19342 }
19343
19344 // OpenMP [2.14.3.6, Restrictions, p.1]
19345 // A list item that appears in a reduction clause of a worksharing
19346 // construct must be shared in the parallel regions to which any of the
19347 // worksharing regions arising from the worksharing construct bind.
19348
19349 if (S.getLangOpts().OpenMP <= 52 &&
19351 !isOpenMPParallelDirective(CurrDir) &&
19352 !isOpenMPTeamsDirective(CurrDir)) {
19353 DVar = Stack->getImplicitDSA(D, true);
19354 if (DVar.CKind != OMPC_shared) {
19355 S.Diag(ELoc, diag::err_omp_required_access)
19356 << getOpenMPClauseNameForDiag(OMPC_reduction)
19357 << getOpenMPClauseNameForDiag(OMPC_shared);
19358 reportOriginalDsa(S, Stack, D, DVar);
19359 continue;
19360 }
19361 } else if (isOpenMPWorksharingDirective(CurrDir) &&
19362 !isOpenMPParallelDirective(CurrDir) &&
19363 !isOpenMPTeamsDirective(CurrDir)) {
19364 // OpenMP 6.0 [ 7.6.10 ]
19365 // Support Reduction over private variables with reduction clause.
19366 // A list item in a reduction clause can now be private in the enclosing
19367 // context. For orphaned constructs it is assumed to be shared unless
19368 // the original(private) modifier appears in the clause.
19369 DVar = Stack->getImplicitDSA(D, true);
19370 // Determine if the variable should be considered private
19371 IsPrivate = DVar.CKind != OMPC_shared;
19372 bool IsOrphaned = false;
19373 OpenMPDirectiveKind ParentDir = Stack->getParentDirective();
19374 IsOrphaned = ParentDir == OMPD_unknown;
19375 if ((IsOrphaned &&
19376 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
19377 IsPrivate = true;
19378 }
19379 } else {
19380 // Threadprivates cannot be shared between threads, so dignose if the base
19381 // is a threadprivate variable.
19382 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19383 if (DVar.CKind == OMPC_threadprivate) {
19384 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19385 << getOpenMPClauseNameForDiag(DVar.CKind)
19386 << getOpenMPClauseNameForDiag(OMPC_reduction);
19387 reportOriginalDsa(S, Stack, D, DVar);
19388 continue;
19389 }
19390 }
19391
19392 // Try to find 'declare reduction' corresponding construct before using
19393 // builtin/overloaded operators.
19394 CXXCastPath BasePath;
19395 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19396 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19397 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19398 if (DeclareReductionRef.isInvalid())
19399 continue;
19400 if (S.CurContext->isDependentContext() &&
19401 (DeclareReductionRef.isUnset() ||
19402 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
19403 RD.push(RefExpr, DeclareReductionRef.get());
19404 continue;
19405 }
19406 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
19407 // Not allowed reduction identifier is found.
19408 if (S.LangOpts.OpenMP > 52)
19409 S.Diag(ReductionId.getBeginLoc(),
19410 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
19411 << Type << ReductionIdRange;
19412 else
19413 S.Diag(ReductionId.getBeginLoc(),
19414 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
19415 << Type << ReductionIdRange;
19416 continue;
19417 }
19418
19419 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19420 // The type of a list item that appears in a reduction clause must be valid
19421 // for the reduction-identifier. For a max or min reduction in C, the type
19422 // of the list item must be an allowed arithmetic data type: char, int,
19423 // float, double, or _Bool, possibly modified with long, short, signed, or
19424 // unsigned. For a max or min reduction in C++, the type of the list item
19425 // must be an allowed arithmetic data type: char, wchar_t, int, float,
19426 // double, or bool, possibly modified with long, short, signed, or unsigned.
19427 if (DeclareReductionRef.isUnset()) {
19428 if ((BOK == BO_GT || BOK == BO_LT) &&
19429 !(Type->isScalarType() ||
19430 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
19431 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
19432 << getOpenMPClauseNameForDiag(ClauseKind)
19433 << S.getLangOpts().CPlusPlus;
19434 if (!ASE && !OASE) {
19435 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19437 S.Diag(D->getLocation(),
19438 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19439 << D;
19440 }
19441 continue;
19442 }
19443 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
19444 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
19445 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
19446 << getOpenMPClauseNameForDiag(ClauseKind);
19447 if (!ASE && !OASE) {
19448 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19450 S.Diag(D->getLocation(),
19451 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19452 << D;
19453 }
19454 continue;
19455 }
19456 }
19457
19458 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
19459 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
19460 D->hasAttrs() ? &D->getAttrs() : nullptr);
19461 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
19462 D->hasAttrs() ? &D->getAttrs() : nullptr);
19463 QualType PrivateTy = Type;
19464
19465 // Try if we can determine constant lengths for all array sections and avoid
19466 // the VLA.
19467 bool ConstantLengthOASE = false;
19468 if (OASE) {
19469 bool SingleElement;
19471 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
19472 Context, OASE, SingleElement, ArraySizes);
19473
19474 // If we don't have a single element, we must emit a constant array type.
19475 if (ConstantLengthOASE && !SingleElement) {
19476 for (llvm::APSInt &Size : ArraySizes)
19477 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
19479 /*IndexTypeQuals=*/0);
19480 }
19481 }
19482
19483 if ((OASE && !ConstantLengthOASE) ||
19484 (!OASE && !ASE &&
19486 if (!Context.getTargetInfo().isVLASupported()) {
19487 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
19488 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19489 S.Diag(ELoc, diag::note_vla_unsupported);
19490 continue;
19491 } else {
19492 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19493 S.targetDiag(ELoc, diag::note_vla_unsupported);
19494 }
19495 }
19496 // For arrays/array sections only:
19497 // Create pseudo array type for private copy. The size for this array will
19498 // be generated during codegen.
19499 // For array subscripts or single variables Private Ty is the same as Type
19500 // (type of the variable or single array element).
19501 PrivateTy = Context.getVariableArrayType(
19502 Type,
19503 new (Context)
19504 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
19505 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0);
19506 } else if (!ASE && !OASE &&
19507 Context.getAsArrayType(D->getType().getNonReferenceType())) {
19508 PrivateTy = D->getType().getNonReferenceType();
19509 }
19510 // Private copy.
19511 VarDecl *PrivateVD =
19512 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19513 D->hasAttrs() ? &D->getAttrs() : nullptr,
19514 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19515 // Add initializer for private variable.
19516 Expr *Init = nullptr;
19517 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
19518 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
19519 if (DeclareReductionRef.isUsable()) {
19520 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
19521 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
19522 if (DRD->getInitializer()) {
19523 Init = DRDRef;
19524 RHSVD->setInit(DRDRef);
19526 }
19527 } else {
19528 switch (BOK) {
19529 case BO_Add:
19530 case BO_Xor:
19531 case BO_Or:
19532 case BO_LOr:
19533 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
19535 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
19536 break;
19537 case BO_Mul:
19538 case BO_LAnd:
19539 if (Type->isScalarType() || Type->isAnyComplexType()) {
19540 // '*' and '&&' reduction ops - initializer is '1'.
19541 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
19542 }
19543 break;
19544 case BO_And: {
19545 // '&' reduction op - initializer is '~0'.
19546 QualType OrigType = Type;
19547 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
19548 Type = ComplexTy->getElementType();
19549 if (Type->isRealFloatingType()) {
19550 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
19551 Context.getFloatTypeSemantics(Type));
19552 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19553 Type, ELoc);
19554 } else if (Type->isScalarType()) {
19555 uint64_t Size = Context.getTypeSize(Type);
19556 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
19557 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
19558 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19559 }
19560 if (Init && OrigType->isAnyComplexType()) {
19561 // Init = 0xFFFF + 0xFFFFi;
19562 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
19563 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
19564 }
19565 Type = OrigType;
19566 break;
19567 }
19568 case BO_LT:
19569 case BO_GT: {
19570 // 'min' reduction op - initializer is 'Largest representable number in
19571 // the reduction list item type'.
19572 // 'max' reduction op - initializer is 'Least representable number in
19573 // the reduction list item type'.
19574 if (Type->isIntegerType() || Type->isPointerType()) {
19575 bool IsSigned = Type->hasSignedIntegerRepresentation();
19576 uint64_t Size = Context.getTypeSize(Type);
19577 QualType IntTy =
19578 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
19579 llvm::APInt InitValue =
19580 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
19581 : llvm::APInt::getMinValue(Size)
19582 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
19583 : llvm::APInt::getMaxValue(Size);
19584 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19585 if (Type->isPointerType()) {
19586 // Cast to pointer type.
19588 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
19589 if (CastExpr.isInvalid())
19590 continue;
19591 Init = CastExpr.get();
19592 }
19593 } else if (Type->isRealFloatingType()) {
19594 llvm::APFloat InitValue = llvm::APFloat::getLargest(
19595 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
19596 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19597 Type, ELoc);
19598 }
19599 break;
19600 }
19601 case BO_PtrMemD:
19602 case BO_PtrMemI:
19603 case BO_MulAssign:
19604 case BO_Div:
19605 case BO_Rem:
19606 case BO_Sub:
19607 case BO_Shl:
19608 case BO_Shr:
19609 case BO_LE:
19610 case BO_GE:
19611 case BO_EQ:
19612 case BO_NE:
19613 case BO_Cmp:
19614 case BO_AndAssign:
19615 case BO_XorAssign:
19616 case BO_OrAssign:
19617 case BO_Assign:
19618 case BO_AddAssign:
19619 case BO_SubAssign:
19620 case BO_DivAssign:
19621 case BO_RemAssign:
19622 case BO_ShlAssign:
19623 case BO_ShrAssign:
19624 case BO_Comma:
19625 llvm_unreachable("Unexpected reduction operation");
19626 }
19627 }
19628 if (Init && DeclareReductionRef.isUnset()) {
19629 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
19630 // Store initializer for single element in private copy. Will be used
19631 // during codegen.
19632 PrivateVD->setInit(RHSVD->getInit());
19633 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19634 } else if (!Init) {
19635 S.ActOnUninitializedDecl(RHSVD);
19636 // Store initializer for single element in private copy. Will be used
19637 // during codegen.
19638 PrivateVD->setInit(RHSVD->getInit());
19639 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19640 }
19641 if (RHSVD->isInvalidDecl())
19642 continue;
19643 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
19644 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
19645 << Type << ReductionIdRange;
19646 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19648 S.Diag(D->getLocation(),
19649 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19650 << D;
19651 continue;
19652 }
19653 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
19654 ExprResult ReductionOp;
19655 if (DeclareReductionRef.isUsable()) {
19656 QualType RedTy = DeclareReductionRef.get()->getType();
19657 QualType PtrRedTy = Context.getPointerType(RedTy);
19658 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
19659 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
19660 if (!BasePath.empty()) {
19661 LHS = S.DefaultLvalueConversion(LHS.get());
19662 RHS = S.DefaultLvalueConversion(RHS.get());
19664 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
19665 LHS.get()->getValueKind(), FPOptionsOverride());
19667 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
19668 RHS.get()->getValueKind(), FPOptionsOverride());
19669 }
19671 QualType Params[] = {PtrRedTy, PtrRedTy};
19672 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
19673 auto *OVE = new (Context) OpaqueValueExpr(
19674 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
19675 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
19676 Expr *Args[] = {LHS.get(), RHS.get()};
19677 ReductionOp =
19678 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
19680 } else {
19682 if (Type->isRecordType() && CombBOK != BOK) {
19684 ReductionOp =
19685 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19686 CombBOK, LHSDRE, RHSDRE);
19687 }
19688 if (!ReductionOp.isUsable()) {
19689 ReductionOp =
19690 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
19691 LHSDRE, RHSDRE);
19692 if (ReductionOp.isUsable()) {
19693 if (BOK != BO_LT && BOK != BO_GT) {
19694 ReductionOp =
19695 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19696 BO_Assign, LHSDRE, ReductionOp.get());
19697 } else {
19698 auto *ConditionalOp = new (Context)
19699 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
19700 RHSDRE, Type, VK_LValue, OK_Ordinary);
19701 ReductionOp =
19702 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19703 BO_Assign, LHSDRE, ConditionalOp);
19704 }
19705 }
19706 }
19707 if (ReductionOp.isUsable())
19708 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
19709 /*DiscardedValue=*/false);
19710 if (!ReductionOp.isUsable())
19711 continue;
19712 }
19713
19714 // Add copy operations for inscan reductions.
19715 // LHS = RHS;
19716 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
19717 if (ClauseKind == OMPC_reduction &&
19718 RD.RedModifier == OMPC_REDUCTION_inscan) {
19719 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
19720 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
19721 RHS.get());
19722 if (!CopyOpRes.isUsable())
19723 continue;
19724 CopyOpRes =
19725 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
19726 if (!CopyOpRes.isUsable())
19727 continue;
19728 // For simd directive and simd-based directives in simd mode no need to
19729 // construct temp array, need just a single temp element.
19730 if (Stack->getCurrentDirective() == OMPD_simd ||
19731 (S.getLangOpts().OpenMPSimd &&
19732 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
19733 VarDecl *TempArrayVD =
19734 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19735 D->hasAttrs() ? &D->getAttrs() : nullptr);
19736 // Add a constructor to the temp decl.
19737 S.ActOnUninitializedDecl(TempArrayVD);
19738 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
19739 } else {
19740 // Build temp array for prefix sum.
19741 auto *Dim = new (S.Context)
19744 PrivateTy, Dim, ArraySizeModifier::Normal,
19745 /*IndexTypeQuals=*/0);
19746 VarDecl *TempArrayVD =
19747 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
19748 D->hasAttrs() ? &D->getAttrs() : nullptr);
19749 // Add a constructor to the temp decl.
19750 S.ActOnUninitializedDecl(TempArrayVD);
19751 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
19752 TempArrayElem =
19753 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
19754 auto *Idx = new (S.Context)
19756 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
19757 ELoc, Idx, ELoc);
19758 }
19759 }
19760
19761 // OpenMP [2.15.4.6, Restrictions, p.2]
19762 // A list item that appears in an in_reduction clause of a task construct
19763 // must appear in a task_reduction clause of a construct associated with a
19764 // taskgroup region that includes the participating task in its taskgroup
19765 // set. The construct associated with the innermost region that meets this
19766 // condition must specify the same reduction-identifier as the in_reduction
19767 // clause.
19768 if (ClauseKind == OMPC_in_reduction) {
19769 SourceRange ParentSR;
19770 BinaryOperatorKind ParentBOK;
19771 const Expr *ParentReductionOp = nullptr;
19772 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
19773 DSAStackTy::DSAVarData ParentBOKDSA =
19774 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
19775 ParentBOKTD);
19776 DSAStackTy::DSAVarData ParentReductionOpDSA =
19777 Stack->getTopMostTaskgroupReductionData(
19778 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
19779 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
19780 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
19781 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
19782 (DeclareReductionRef.isUsable() && IsParentBOK) ||
19783 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
19784 bool EmitError = true;
19785 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
19786 llvm::FoldingSetNodeID RedId, ParentRedId;
19787 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
19788 DeclareReductionRef.get()->Profile(RedId, Context,
19789 /*Canonical=*/true);
19790 EmitError = RedId != ParentRedId;
19791 }
19792 if (EmitError) {
19793 S.Diag(ReductionId.getBeginLoc(),
19794 diag::err_omp_reduction_identifier_mismatch)
19795 << ReductionIdRange << RefExpr->getSourceRange();
19796 S.Diag(ParentSR.getBegin(),
19797 diag::note_omp_previous_reduction_identifier)
19798 << ParentSR
19799 << (IsParentBOK ? ParentBOKDSA.RefExpr
19800 : ParentReductionOpDSA.RefExpr)
19801 ->getSourceRange();
19802 continue;
19803 }
19804 }
19805 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
19806 }
19807
19808 DeclRefExpr *Ref = nullptr;
19809 Expr *VarsExpr = RefExpr->IgnoreParens();
19810 if (!VD && !S.CurContext->isDependentContext()) {
19811 if (ASE || OASE) {
19812 TransformExprToCaptures RebuildToCapture(S, D);
19813 VarsExpr =
19814 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
19815 Ref = RebuildToCapture.getCapturedExpr();
19816 } else {
19817 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
19818 }
19819 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
19820 RD.ExprCaptures.emplace_back(Ref->getDecl());
19821 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19822 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
19823 if (!RefRes.isUsable())
19824 continue;
19825 ExprResult PostUpdateRes =
19826 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
19827 RefRes.get());
19828 if (!PostUpdateRes.isUsable())
19829 continue;
19830 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
19831 Stack->getCurrentDirective() == OMPD_taskgroup) {
19832 S.Diag(RefExpr->getExprLoc(),
19833 diag::err_omp_reduction_non_addressable_expression)
19834 << RefExpr->getSourceRange();
19835 continue;
19836 }
19837 RD.ExprPostUpdates.emplace_back(
19838 S.IgnoredValueConversions(PostUpdateRes.get()).get());
19839 }
19840 }
19841 }
19842 // All reduction items are still marked as reduction (to do not increase
19843 // code base size).
19844 unsigned Modifier = RD.RedModifier;
19845 // Consider task_reductions as reductions with task modifier. Required for
19846 // correct analysis of in_reduction clauses.
19847 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
19848 Modifier = OMPC_REDUCTION_task;
19849 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
19850 ASE || OASE);
19851 if (Modifier == OMPC_REDUCTION_task &&
19852 (CurrDir == OMPD_taskgroup ||
19853 ((isOpenMPParallelDirective(CurrDir) ||
19854 isOpenMPWorksharingDirective(CurrDir)) &&
19855 !isOpenMPSimdDirective(CurrDir)))) {
19856 if (DeclareReductionRef.isUsable())
19857 Stack->addTaskgroupReductionData(D, ReductionIdRange,
19858 DeclareReductionRef.get());
19859 else
19860 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
19861 }
19862 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
19863 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
19864 TempArrayElem.get(), IsPrivate);
19865 }
19866 return RD.Vars.empty();
19867}
19868
19870 ArrayRef<Expr *> VarList,
19872 SourceLocation StartLoc, SourceLocation LParenLoc,
19873 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
19874 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19875 ArrayRef<Expr *> UnresolvedReductions) {
19877 static_cast<OpenMPReductionClauseModifier>(Modifiers.ExtraModifier);
19878 OpenMPOriginalSharingModifier OriginalSharingModifier =
19879 static_cast<OpenMPOriginalSharingModifier>(
19880 Modifiers.OriginalSharingModifier);
19881 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
19882 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
19883 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
19884 /*Last=*/OMPC_REDUCTION_unknown)
19885 << getOpenMPClauseNameForDiag(OMPC_reduction);
19886 return nullptr;
19887 }
19888 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
19889 // A reduction clause with the inscan reduction-modifier may only appear on a
19890 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
19891 // construct, a parallel worksharing-loop construct or a parallel
19892 // worksharing-loop SIMD construct.
19893 if (Modifier == OMPC_REDUCTION_inscan &&
19894 (DSAStack->getCurrentDirective() != OMPD_for &&
19895 DSAStack->getCurrentDirective() != OMPD_for_simd &&
19896 DSAStack->getCurrentDirective() != OMPD_simd &&
19897 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
19898 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
19899 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
19900 return nullptr;
19901 }
19902 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
19903 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
19904 StartLoc, LParenLoc, ColonLoc, EndLoc,
19905 ReductionIdScopeSpec, ReductionId,
19906 UnresolvedReductions, RD))
19907 return nullptr;
19908
19910 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
19911 Modifier, RD.Vars,
19912 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19913 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
19914 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
19915 buildPreInits(getASTContext(), RD.ExprCaptures),
19916 buildPostUpdate(SemaRef, RD.ExprPostUpdates), RD.IsPrivateVarReduction,
19917 OriginalSharingModifier);
19918}
19919
19921 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19922 SourceLocation ColonLoc, SourceLocation EndLoc,
19923 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19924 ArrayRef<Expr *> UnresolvedReductions) {
19925 ReductionData RD(VarList.size());
19926 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction,
19927 VarList, StartLoc, LParenLoc, ColonLoc,
19928 EndLoc, ReductionIdScopeSpec, ReductionId,
19929 UnresolvedReductions, RD))
19930 return nullptr;
19931
19933 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19934 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19935 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
19936 buildPreInits(getASTContext(), RD.ExprCaptures),
19937 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
19938}
19939
19941 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19942 SourceLocation ColonLoc, SourceLocation EndLoc,
19943 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19944 ArrayRef<Expr *> UnresolvedReductions) {
19945 ReductionData RD(VarList.size());
19946 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList,
19947 StartLoc, LParenLoc, ColonLoc, EndLoc,
19948 ReductionIdScopeSpec, ReductionId,
19949 UnresolvedReductions, RD))
19950 return nullptr;
19951
19953 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19954 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19955 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
19956 buildPreInits(getASTContext(), RD.ExprCaptures),
19957 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
19958}
19959
19961 SourceLocation LinLoc) {
19962 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
19963 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
19964 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
19965 << getLangOpts().CPlusPlus;
19966 return true;
19967 }
19968 return false;
19969}
19970
19972 OpenMPLinearClauseKind LinKind,
19973 QualType Type, bool IsDeclareSimd) {
19974 const auto *VD = dyn_cast_or_null<VarDecl>(D);
19975 // A variable must not have an incomplete type or a reference type.
19976 if (SemaRef.RequireCompleteType(ELoc, Type,
19977 diag::err_omp_linear_incomplete_type))
19978 return true;
19979 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
19980 !Type->isReferenceType()) {
19981 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
19982 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
19983 return true;
19984 }
19985 Type = Type.getNonReferenceType();
19986
19987 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19988 // A variable that is privatized must not have a const-qualified type
19989 // unless it is of class type with a mutable member. This restriction does
19990 // not apply to the firstprivate clause, nor to the linear clause on
19991 // declarative directives (like declare simd).
19992 if (!IsDeclareSimd &&
19993 rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc))
19994 return true;
19995
19996 // A list item must be of integral or pointer type.
19997 Type = Type.getUnqualifiedType().getCanonicalType();
19998 const auto *Ty = Type.getTypePtrOrNull();
19999 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
20000 !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) {
20001 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
20002 if (D) {
20003 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20005 Diag(D->getLocation(),
20006 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20007 << D;
20008 }
20009 return true;
20010 }
20011 return false;
20012}
20013
20015 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
20016 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
20017 SourceLocation LinLoc, SourceLocation ColonLoc,
20018 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
20020 SmallVector<Expr *, 8> Privates;
20022 SmallVector<Decl *, 4> ExprCaptures;
20023 SmallVector<Expr *, 4> ExprPostUpdates;
20024 // OpenMP 5.2 [Section 5.4.6, linear clause]
20025 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
20026 // 'ref'
20027 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
20028 getLangOpts().OpenMP >= 52)
20029 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
20030 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
20031 LinKind = OMPC_LINEAR_val;
20032 for (Expr *RefExpr : VarList) {
20033 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20034 SourceLocation ELoc;
20035 SourceRange ERange;
20036 Expr *SimpleRefExpr = RefExpr;
20037 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20038 if (Res.second) {
20039 // It will be analyzed later.
20040 Vars.push_back(RefExpr);
20041 Privates.push_back(nullptr);
20042 Inits.push_back(nullptr);
20043 }
20044 ValueDecl *D = Res.first;
20045 if (!D)
20046 continue;
20047
20048 QualType Type = D->getType();
20049 auto *VD = dyn_cast<VarDecl>(D);
20050
20051 // OpenMP [2.14.3.7, linear clause]
20052 // A list-item cannot appear in more than one linear clause.
20053 // A list-item that appears in a linear clause cannot appear in any
20054 // other data-sharing attribute clause.
20055 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
20056 if (DVar.RefExpr) {
20057 Diag(ELoc, diag::err_omp_wrong_dsa)
20058 << getOpenMPClauseNameForDiag(DVar.CKind)
20059 << getOpenMPClauseNameForDiag(OMPC_linear);
20061 continue;
20062 }
20063
20064 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
20065 continue;
20066 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20067
20068 // Build private copy of original var.
20069 VarDecl *Private =
20070 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
20071 D->hasAttrs() ? &D->getAttrs() : nullptr,
20072 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
20073 DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc);
20074 // Build var to save initial value.
20075 VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start");
20076 Expr *InitExpr;
20077 DeclRefExpr *Ref = nullptr;
20078 if (!VD && !SemaRef.CurContext->isDependentContext()) {
20079 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
20080 if (!isOpenMPCapturedDecl(D)) {
20081 ExprCaptures.push_back(Ref->getDecl());
20082 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20083 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
20084 if (!RefRes.isUsable())
20085 continue;
20086 ExprResult PostUpdateRes =
20087 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
20088 SimpleRefExpr, RefRes.get());
20089 if (!PostUpdateRes.isUsable())
20090 continue;
20091 ExprPostUpdates.push_back(
20092 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
20093 }
20094 }
20095 }
20096 if (LinKind == OMPC_LINEAR_uval)
20097 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
20098 else
20099 InitExpr = VD ? SimpleRefExpr : Ref;
20100 SemaRef.AddInitializerToDecl(
20101 Init, SemaRef.DefaultLvalueConversion(InitExpr).get(),
20102 /*DirectInit=*/false);
20103 DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc);
20104
20105 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
20106 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
20107 ? RefExpr->IgnoreParens()
20108 : Ref);
20109 Privates.push_back(PrivateRef);
20110 Inits.push_back(InitRef);
20111 }
20112
20113 if (Vars.empty())
20114 return nullptr;
20115
20116 Expr *StepExpr = Step;
20117 Expr *CalcStepExpr = nullptr;
20118 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
20119 !Step->isInstantiationDependent() &&
20121 SourceLocation StepLoc = Step->getBeginLoc();
20123 if (Val.isInvalid())
20124 return nullptr;
20125 StepExpr = Val.get();
20126
20127 // Build var to save the step value.
20128 VarDecl *SaveVar =
20129 buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step");
20130 ExprResult SaveRef =
20131 buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc);
20132 ExprResult CalcStep = SemaRef.BuildBinOp(
20133 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr);
20134 CalcStep =
20135 SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue=*/false);
20136
20137 // Warn about zero linear step (it would be probably better specified as
20138 // making corresponding variables 'const').
20139 if (std::optional<llvm::APSInt> Result =
20141 if (!Result->isNegative() && !Result->isStrictlyPositive())
20142 Diag(StepLoc, diag::warn_omp_linear_step_zero)
20143 << Vars[0] << (Vars.size() > 1);
20144 } else if (CalcStep.isUsable()) {
20145 // Calculate the step beforehand instead of doing this on each iteration.
20146 // (This is not used if the number of iterations may be kfold-ed).
20147 CalcStepExpr = CalcStep.get();
20148 }
20149 }
20150
20151 return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind,
20152 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
20153 Vars, Privates, Inits, StepExpr, CalcStepExpr,
20154 buildPreInits(getASTContext(), ExprCaptures),
20155 buildPostUpdate(SemaRef, ExprPostUpdates));
20156}
20157
20159 Expr *NumIterations, Sema &SemaRef,
20160 Scope *S, DSAStackTy *Stack) {
20161 // Walk the vars and build update/final expressions for the CodeGen.
20162 SmallVector<Expr *, 8> Updates;
20164 SmallVector<Expr *, 8> UsedExprs;
20165 Expr *Step = Clause.getStep();
20166 Expr *CalcStep = Clause.getCalcStep();
20167 // OpenMP [2.14.3.7, linear clause]
20168 // If linear-step is not specified it is assumed to be 1.
20169 if (!Step)
20170 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
20171 else if (CalcStep)
20172 Step = cast<BinaryOperator>(CalcStep)->getLHS();
20173 bool HasErrors = false;
20174 auto CurInit = Clause.inits().begin();
20175 auto CurPrivate = Clause.privates().begin();
20176 OpenMPLinearClauseKind LinKind = Clause.getModifier();
20177 for (Expr *RefExpr : Clause.varlist()) {
20178 SourceLocation ELoc;
20179 SourceRange ERange;
20180 Expr *SimpleRefExpr = RefExpr;
20181 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20182 ValueDecl *D = Res.first;
20183 if (Res.second || !D) {
20184 Updates.push_back(nullptr);
20185 Finals.push_back(nullptr);
20186 HasErrors = true;
20187 continue;
20188 }
20189 auto &&Info = Stack->isLoopControlVariable(D);
20190 // OpenMP [2.15.11, distribute simd Construct]
20191 // A list item may not appear in a linear clause, unless it is the loop
20192 // iteration variable.
20193 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
20194 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
20195 SemaRef.Diag(ELoc,
20196 diag::err_omp_linear_distribute_var_non_loop_iteration);
20197 Updates.push_back(nullptr);
20198 Finals.push_back(nullptr);
20199 HasErrors = true;
20200 continue;
20201 }
20202 Expr *InitExpr = *CurInit;
20203
20204 // Build privatized reference to the current linear var.
20205 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
20206 Expr *CapturedRef;
20207 if (LinKind == OMPC_LINEAR_uval)
20208 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
20209 else
20210 CapturedRef =
20211 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
20212 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
20213 /*RefersToCapture=*/true);
20214
20215 // Build update: Var = InitExpr + IV * Step
20217 if (!Info.first)
20219 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
20220 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
20221 else
20222 Update = *CurPrivate;
20223 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
20224 /*DiscardedValue=*/false);
20225
20226 // Build final: Var = PrivCopy;
20227 ExprResult Final;
20228 if (!Info.first)
20229 Final = SemaRef.BuildBinOp(
20230 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
20231 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
20232 else
20233 Final = *CurPrivate;
20234 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
20235 /*DiscardedValue=*/false);
20236
20237 if (!Update.isUsable() || !Final.isUsable()) {
20238 Updates.push_back(nullptr);
20239 Finals.push_back(nullptr);
20240 UsedExprs.push_back(nullptr);
20241 HasErrors = true;
20242 } else {
20243 Updates.push_back(Update.get());
20244 Finals.push_back(Final.get());
20245 if (!Info.first)
20246 UsedExprs.push_back(SimpleRefExpr);
20247 }
20248 ++CurInit;
20249 ++CurPrivate;
20250 }
20251 if (Expr *S = Clause.getStep())
20252 UsedExprs.push_back(S);
20253 // Fill the remaining part with the nullptr.
20254 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
20255 Clause.setUpdates(Updates);
20256 Clause.setFinals(Finals);
20257 Clause.setUsedExprs(UsedExprs);
20258 return HasErrors;
20259}
20260
20262 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
20263 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
20265 for (Expr *RefExpr : VarList) {
20266 assert(RefExpr && "NULL expr in OpenMP aligned clause.");
20267 SourceLocation ELoc;
20268 SourceRange ERange;
20269 Expr *SimpleRefExpr = RefExpr;
20270 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20271 if (Res.second) {
20272 // It will be analyzed later.
20273 Vars.push_back(RefExpr);
20274 }
20275 ValueDecl *D = Res.first;
20276 if (!D)
20277 continue;
20278
20279 QualType QType = D->getType();
20280 auto *VD = dyn_cast<VarDecl>(D);
20281
20282 // OpenMP [2.8.1, simd construct, Restrictions]
20283 // The type of list items appearing in the aligned clause must be
20284 // array, pointer, reference to array, or reference to pointer.
20286 const Type *Ty = QType.getTypePtrOrNull();
20287 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
20288 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
20289 << QType << getLangOpts().CPlusPlus << ERange;
20290 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20292 Diag(D->getLocation(),
20293 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20294 << D;
20295 continue;
20296 }
20297
20298 // OpenMP [2.8.1, simd construct, Restrictions]
20299 // A list-item cannot appear in more than one aligned clause.
20300 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
20301 Diag(ELoc, diag::err_omp_used_in_clause_twice)
20302 << 0 << getOpenMPClauseNameForDiag(OMPC_aligned) << ERange;
20303 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
20304 << getOpenMPClauseNameForDiag(OMPC_aligned);
20305 continue;
20306 }
20307
20308 DeclRefExpr *Ref = nullptr;
20309 if (!VD && isOpenMPCapturedDecl(D))
20310 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
20311 Vars.push_back(SemaRef
20312 .DefaultFunctionArrayConversion(
20313 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
20314 .get());
20315 }
20316
20317 // OpenMP [2.8.1, simd construct, Description]
20318 // The parameter of the aligned clause, alignment, must be a constant
20319 // positive integer expression.
20320 // If no optional parameter is specified, implementation-defined default
20321 // alignments for SIMD instructions on the target platforms are assumed.
20322 if (Alignment != nullptr) {
20323 ExprResult AlignResult =
20324 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
20325 if (AlignResult.isInvalid())
20326 return nullptr;
20327 Alignment = AlignResult.get();
20328 }
20329 if (Vars.empty())
20330 return nullptr;
20331
20332 return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc,
20333 ColonLoc, EndLoc, Vars, Alignment);
20334}
20335
20337 SourceLocation StartLoc,
20338 SourceLocation LParenLoc,
20339 SourceLocation EndLoc) {
20341 SmallVector<Expr *, 8> SrcExprs;
20342 SmallVector<Expr *, 8> DstExprs;
20343 SmallVector<Expr *, 8> AssignmentOps;
20344 for (Expr *RefExpr : VarList) {
20345 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
20346 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20347 // It will be analyzed later.
20348 Vars.push_back(RefExpr);
20349 SrcExprs.push_back(nullptr);
20350 DstExprs.push_back(nullptr);
20351 AssignmentOps.push_back(nullptr);
20352 continue;
20353 }
20354
20355 SourceLocation ELoc = RefExpr->getExprLoc();
20356 // OpenMP [2.1, C/C++]
20357 // A list item is a variable name.
20358 // OpenMP [2.14.4.1, Restrictions, p.1]
20359 // A list item that appears in a copyin clause must be threadprivate.
20360 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
20361 if (!DE || !isa<VarDecl>(DE->getDecl())) {
20362 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
20363 << 0 << RefExpr->getSourceRange();
20364 continue;
20365 }
20366
20367 Decl *D = DE->getDecl();
20368 auto *VD = cast<VarDecl>(D);
20369
20370 QualType Type = VD->getType();
20372 // It will be analyzed later.
20373 Vars.push_back(DE);
20374 SrcExprs.push_back(nullptr);
20375 DstExprs.push_back(nullptr);
20376 AssignmentOps.push_back(nullptr);
20377 continue;
20378 }
20379
20380 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
20381 // A list item that appears in a copyin clause must be threadprivate.
20382 if (!DSAStack->isThreadPrivate(VD)) {
20383 unsigned OMPVersion = getLangOpts().OpenMP;
20384 Diag(ELoc, diag::err_omp_required_access)
20385 << getOpenMPClauseNameForDiag(OMPC_copyin)
20386 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion);
20387 continue;
20388 }
20389
20390 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20391 // A variable of class type (or array thereof) that appears in a
20392 // copyin clause requires an accessible, unambiguous copy assignment
20393 // operator for the class type.
20394 QualType ElemType =
20396 VarDecl *SrcVD =
20397 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
20398 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20399 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
20400 SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
20401 VarDecl *DstVD =
20402 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst",
20403 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20404 DeclRefExpr *PseudoDstExpr =
20405 buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc());
20406 // For arrays generate assignment operation for single element and replace
20407 // it by the original array element in CodeGen.
20408 ExprResult AssignmentOp =
20409 SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
20410 PseudoDstExpr, PseudoSrcExpr);
20411 if (AssignmentOp.isInvalid())
20412 continue;
20413 AssignmentOp =
20414 SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
20415 /*DiscardedValue=*/false);
20416 if (AssignmentOp.isInvalid())
20417 continue;
20418
20419 DSAStack->addDSA(VD, DE, OMPC_copyin);
20420 Vars.push_back(DE);
20421 SrcExprs.push_back(PseudoSrcExpr);
20422 DstExprs.push_back(PseudoDstExpr);
20423 AssignmentOps.push_back(AssignmentOp.get());
20424 }
20425
20426 if (Vars.empty())
20427 return nullptr;
20428
20429 return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
20430 Vars, SrcExprs, DstExprs, AssignmentOps);
20431}
20432
20434 SourceLocation StartLoc,
20435 SourceLocation LParenLoc,
20436 SourceLocation EndLoc) {
20438 SmallVector<Expr *, 8> SrcExprs;
20439 SmallVector<Expr *, 8> DstExprs;
20440 SmallVector<Expr *, 8> AssignmentOps;
20441 for (Expr *RefExpr : VarList) {
20442 assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");
20443 SourceLocation ELoc;
20444 SourceRange ERange;
20445 Expr *SimpleRefExpr = RefExpr;
20446 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20447 if (Res.second) {
20448 // It will be analyzed later.
20449 Vars.push_back(RefExpr);
20450 SrcExprs.push_back(nullptr);
20451 DstExprs.push_back(nullptr);
20452 AssignmentOps.push_back(nullptr);
20453 }
20454 ValueDecl *D = Res.first;
20455 if (!D)
20456 continue;
20457
20458 QualType Type = D->getType();
20459 auto *VD = dyn_cast<VarDecl>(D);
20460
20461 // OpenMP [2.14.4.2, Restrictions, p.2]
20462 // A list item that appears in a copyprivate clause may not appear in a
20463 // private or firstprivate clause on the single construct.
20464 if (!VD || !DSAStack->isThreadPrivate(VD)) {
20465 DSAStackTy::DSAVarData DVar =
20466 DSAStack->getTopDSA(D, /*FromParent=*/false);
20467 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
20468 DVar.RefExpr) {
20469 Diag(ELoc, diag::err_omp_wrong_dsa)
20470 << getOpenMPClauseNameForDiag(DVar.CKind)
20471 << getOpenMPClauseNameForDiag(OMPC_copyprivate);
20473 continue;
20474 }
20475
20476 // OpenMP [2.11.4.2, Restrictions, p.1]
20477 // All list items that appear in a copyprivate clause must be either
20478 // threadprivate or private in the enclosing context.
20479 if (DVar.CKind == OMPC_unknown) {
20480 DVar = DSAStack->getImplicitDSA(D, false);
20481 if (DVar.CKind == OMPC_shared) {
20482 Diag(ELoc, diag::err_omp_required_access)
20483 << getOpenMPClauseNameForDiag(OMPC_copyprivate)
20484 << "threadprivate or private in the enclosing context";
20486 continue;
20487 }
20488 }
20489 }
20490
20491 // Variably modified types are not supported.
20493 unsigned OMPVersion = getLangOpts().OpenMP;
20494 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
20495 << getOpenMPClauseNameForDiag(OMPC_copyprivate) << Type
20496 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
20497 OMPVersion);
20498 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20500 Diag(D->getLocation(),
20501 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20502 << D;
20503 continue;
20504 }
20505
20506 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20507 // A variable of class type (or array thereof) that appears in a
20508 // copyin clause requires an accessible, unambiguous copy assignment
20509 // operator for the class type.
20511 .getBaseElementType(Type.getNonReferenceType())
20513 VarDecl *SrcVD =
20514 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
20515 D->hasAttrs() ? &D->getAttrs() : nullptr);
20516 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc);
20517 VarDecl *DstVD =
20518 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
20519 D->hasAttrs() ? &D->getAttrs() : nullptr);
20520 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
20521 ExprResult AssignmentOp = SemaRef.BuildBinOp(
20522 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
20523 if (AssignmentOp.isInvalid())
20524 continue;
20525 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
20526 /*DiscardedValue=*/false);
20527 if (AssignmentOp.isInvalid())
20528 continue;
20529
20530 // No need to mark vars as copyprivate, they are already threadprivate or
20531 // implicitly private.
20532 assert(VD || isOpenMPCapturedDecl(D));
20533 Vars.push_back(
20534 VD ? RefExpr->IgnoreParens()
20535 : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false));
20536 SrcExprs.push_back(PseudoSrcExpr);
20537 DstExprs.push_back(PseudoDstExpr);
20538 AssignmentOps.push_back(AssignmentOp.get());
20539 }
20540
20541 if (Vars.empty())
20542 return nullptr;
20543
20544 return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc,
20545 EndLoc, Vars, SrcExprs, DstExprs,
20546 AssignmentOps);
20547}
20548
20550 SourceLocation StartLoc,
20551 SourceLocation LParenLoc,
20552 SourceLocation EndLoc) {
20553 if (VarList.empty())
20554 return nullptr;
20555
20556 return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
20557 VarList);
20558}
20559
20560/// Tries to find omp_depend_t. type.
20561static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
20562 bool Diagnose = true) {
20563 QualType OMPDependT = Stack->getOMPDependT();
20564 if (!OMPDependT.isNull())
20565 return true;
20566 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
20567 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
20568 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
20569 if (Diagnose)
20570 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
20571 return false;
20572 }
20573 Stack->setOMPDependT(PT.get());
20574 return true;
20575}
20576
20578 SourceLocation StartLoc,
20579 SourceLocation LParenLoc,
20580 SourceLocation EndLoc) {
20581 if (!Depobj)
20582 return nullptr;
20583
20584 bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack);
20585
20586 // OpenMP 5.0, 2.17.10.1 depobj Construct
20587 // depobj is an lvalue expression of type omp_depend_t.
20588 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
20589 !Depobj->isInstantiationDependent() &&
20591 (OMPDependTFound && !getASTContext().typesAreCompatible(
20592 DSAStack->getOMPDependT(), Depobj->getType(),
20593 /*CompareUnqualified=*/true))) {
20594 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20595 << 0 << Depobj->getType() << Depobj->getSourceRange();
20596 }
20597
20598 if (!Depobj->isLValue()) {
20599 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20600 << 1 << Depobj->getSourceRange();
20601 }
20602
20603 return OMPDepobjClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
20604 Depobj);
20605}
20606
20607namespace {
20608// Utility struct that gathers the related info for doacross clause.
20609struct DoacrossDataInfoTy {
20610 // The list of expressions.
20612 // The OperatorOffset for doacross loop.
20613 DSAStackTy::OperatorOffsetTy OpsOffs;
20614 // The depended loop count.
20615 llvm::APSInt TotalDepCount;
20616};
20617} // namespace
20618static DoacrossDataInfoTy
20620 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
20621 SourceLocation EndLoc) {
20622
20624 DSAStackTy::OperatorOffsetTy OpsOffs;
20625 llvm::APSInt DepCounter(/*BitWidth=*/32);
20626 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20627
20628 if (const Expr *OrderedCountExpr =
20629 Stack->getParentOrderedRegionParam().first) {
20630 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
20631 TotalDepCount.setIsUnsigned(/*Val=*/true);
20632 }
20633
20634 for (Expr *RefExpr : VarList) {
20635 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
20636 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20637 // It will be analyzed later.
20638 Vars.push_back(RefExpr);
20639 continue;
20640 }
20641
20642 SourceLocation ELoc = RefExpr->getExprLoc();
20643 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20644 if (!IsSource) {
20645 if (Stack->getParentOrderedRegionParam().first &&
20646 DepCounter >= TotalDepCount) {
20647 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
20648 continue;
20649 }
20650 ++DepCounter;
20651 // OpenMP [2.13.9, Summary]
20652 // depend(dependence-type : vec), where dependence-type is:
20653 // 'sink' and where vec is the iteration vector, which has the form:
20654 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
20655 // where n is the value specified by the ordered clause in the loop
20656 // directive, xi denotes the loop iteration variable of the i-th nested
20657 // loop associated with the loop directive, and di is a constant
20658 // non-negative integer.
20659 if (SemaRef.CurContext->isDependentContext()) {
20660 // It will be analyzed later.
20661 Vars.push_back(RefExpr);
20662 continue;
20663 }
20664 SimpleExpr = SimpleExpr->IgnoreImplicit();
20666 SourceLocation OOLoc;
20667 Expr *LHS = SimpleExpr;
20668 Expr *RHS = nullptr;
20669 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
20670 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
20671 OOLoc = BO->getOperatorLoc();
20672 LHS = BO->getLHS()->IgnoreParenImpCasts();
20673 RHS = BO->getRHS()->IgnoreParenImpCasts();
20674 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
20675 OOK = OCE->getOperator();
20676 OOLoc = OCE->getOperatorLoc();
20677 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20678 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
20679 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
20680 OOK = MCE->getMethodDecl()
20681 ->getNameInfo()
20682 .getName()
20683 .getCXXOverloadedOperator();
20684 OOLoc = MCE->getCallee()->getExprLoc();
20685 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
20686 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20687 }
20688 SourceLocation ELoc;
20689 SourceRange ERange;
20690 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
20691 if (Res.second) {
20692 // It will be analyzed later.
20693 Vars.push_back(RefExpr);
20694 }
20695 ValueDecl *D = Res.first;
20696 if (!D)
20697 continue;
20698
20699 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
20700 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
20701 continue;
20702 }
20703 if (RHS) {
20704 ExprResult RHSRes =
20706 RHS, OMPC_depend, /*StrictlyPositive=*/false);
20707 if (RHSRes.isInvalid())
20708 continue;
20709 }
20710 if (!SemaRef.CurContext->isDependentContext() &&
20711 Stack->getParentOrderedRegionParam().first &&
20712 DepCounter != Stack->isParentLoopControlVariable(D).first) {
20713 const ValueDecl *VD =
20714 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
20715 if (VD)
20716 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20717 << 1 << VD;
20718 else
20719 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20720 << 0;
20721 continue;
20722 }
20723 OpsOffs.emplace_back(RHS, OOK);
20724 }
20725 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20726 }
20727 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
20728 TotalDepCount > VarList.size() &&
20729 Stack->getParentOrderedRegionParam().first &&
20730 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
20731 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
20732 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
20733 }
20734 return {Vars, OpsOffs, TotalDepCount};
20735}
20736
20738 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
20739 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20740 SourceLocation EndLoc) {
20741 OpenMPDependClauseKind DepKind = Data.DepKind;
20742 SourceLocation DepLoc = Data.DepLoc;
20743 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
20744 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
20745 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20746 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_depend);
20747 return nullptr;
20748 }
20749 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
20750 DepKind == OMPC_DEPEND_mutexinoutset) {
20751 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
20752 return nullptr;
20753 }
20754 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
20755 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20756 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
20757 DepKind == OMPC_DEPEND_sink ||
20758 ((getLangOpts().OpenMP < 50 ||
20759 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20760 DepKind == OMPC_DEPEND_depobj))) {
20761 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
20762 OMPC_DEPEND_outallmemory,
20763 OMPC_DEPEND_inoutallmemory};
20764 if (getLangOpts().OpenMP < 50 ||
20765 DSAStack->getCurrentDirective() == OMPD_depobj)
20766 Except.push_back(OMPC_DEPEND_depobj);
20767 if (getLangOpts().OpenMP < 51)
20768 Except.push_back(OMPC_DEPEND_inoutset);
20769 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
20770 ? "depend modifier(iterator) or "
20771 : "";
20772 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20773 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
20774 /*Last=*/OMPC_DEPEND_unknown,
20775 Except)
20776 << getOpenMPClauseNameForDiag(OMPC_depend);
20777 return nullptr;
20778 }
20779 if (DepModifier &&
20780 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
20781 Diag(DepModifier->getExprLoc(),
20782 diag::err_omp_depend_sink_source_with_modifier);
20783 return nullptr;
20784 }
20785 if (DepModifier &&
20786 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
20787 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
20788
20790 DSAStackTy::OperatorOffsetTy OpsOffs;
20791 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20792
20793 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
20794 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
20795 SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
20796 Vars = VarOffset.Vars;
20797 OpsOffs = VarOffset.OpsOffs;
20798 TotalDepCount = VarOffset.TotalDepCount;
20799 } else {
20800 for (Expr *RefExpr : VarList) {
20801 assert(RefExpr && "NULL expr in OpenMP depend clause.");
20802 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20803 // It will be analyzed later.
20804 Vars.push_back(RefExpr);
20805 continue;
20806 }
20807
20808 SourceLocation ELoc = RefExpr->getExprLoc();
20809 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20810 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
20811 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
20812 if (OMPDependTFound)
20813 OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack,
20814 DepKind == OMPC_DEPEND_depobj);
20815 if (DepKind == OMPC_DEPEND_depobj) {
20816 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20817 // List items used in depend clauses with the depobj dependence type
20818 // must be expressions of the omp_depend_t type.
20819 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20820 !RefExpr->isInstantiationDependent() &&
20821 !RefExpr->containsUnexpandedParameterPack() &&
20822 (OMPDependTFound &&
20823 !getASTContext().hasSameUnqualifiedType(
20824 DSAStack->getOMPDependT(), RefExpr->getType()))) {
20825 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20826 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
20827 continue;
20828 }
20829 if (!RefExpr->isLValue()) {
20830 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20831 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
20832 continue;
20833 }
20834 } else {
20835 // OpenMP 5.0 [2.17.11, Restrictions]
20836 // List items used in depend clauses cannot be zero-length array
20837 // sections.
20838 QualType ExprTy = RefExpr->getType().getNonReferenceType();
20839 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
20840 if (OASE) {
20841 QualType BaseType =
20843 if (BaseType.isNull())
20844 return nullptr;
20845 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20846 ExprTy = ATy->getElementType();
20847 else
20848 ExprTy = BaseType->getPointeeType();
20849 if (BaseType.isNull() || ExprTy.isNull())
20850 return nullptr;
20851 ExprTy = ExprTy.getNonReferenceType();
20852 const Expr *Length = OASE->getLength();
20854 if (Length && !Length->isValueDependent() &&
20855 Length->EvaluateAsInt(Result, getASTContext()) &&
20856 Result.Val.getInt().isZero()) {
20857 Diag(ELoc,
20858 diag::err_omp_depend_zero_length_array_section_not_allowed)
20859 << SimpleExpr->getSourceRange();
20860 continue;
20861 }
20862 }
20863
20864 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20865 // List items used in depend clauses with the in, out, inout,
20866 // inoutset, or mutexinoutset dependence types cannot be
20867 // expressions of the omp_depend_t type.
20868 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20869 !RefExpr->isInstantiationDependent() &&
20870 !RefExpr->containsUnexpandedParameterPack() &&
20871 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
20872 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
20873 ExprTy.getTypePtr()))) {
20874 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20875 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20876 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20877 << RefExpr->getSourceRange();
20878 continue;
20879 }
20880
20881 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
20882 if (ASE && !ASE->getBase()->isTypeDependent() &&
20883 !ASE->getBase()
20884 ->getType()
20885 .getNonReferenceType()
20886 ->isPointerType() &&
20887 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
20888 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20889 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20890 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20891 << RefExpr->getSourceRange();
20892 continue;
20893 }
20894
20895 ExprResult Res;
20896 {
20898 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
20899 RefExpr->IgnoreParenImpCasts());
20900 }
20901 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
20903 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20904 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20905 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20906 << RefExpr->getSourceRange();
20907 continue;
20908 }
20909 }
20910 }
20911 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20912 }
20913 }
20914
20915 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
20916 DepKind != OMPC_DEPEND_outallmemory &&
20917 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
20918 return nullptr;
20919
20920 auto *C = OMPDependClause::Create(
20921 getASTContext(), StartLoc, LParenLoc, EndLoc,
20922 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
20923 TotalDepCount.getZExtValue());
20924 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
20925 DSAStack->isParentOrderedRegion())
20926 DSAStack->addDoacrossDependClause(C, OpsOffs);
20927 return C;
20928}
20929
20932 SourceLocation LParenLoc, SourceLocation ModifierLoc,
20933 SourceLocation EndLoc) {
20934 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
20935 "Unexpected device modifier in OpenMP < 50.");
20936
20937 bool ErrorFound = false;
20938 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
20939 std::string Values =
20940 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
20941 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
20942 << Values << getOpenMPClauseNameForDiag(OMPC_device);
20943 ErrorFound = true;
20944 }
20945
20946 Expr *ValExpr = Device;
20947 Stmt *HelperValStmt = nullptr;
20948
20949 // OpenMP [2.9.1, Restrictions]
20950 // The device expression must evaluate to a non-negative integer value.
20951 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device,
20952 /*StrictlyPositive=*/false) ||
20953 ErrorFound;
20954 if (ErrorFound)
20955 return nullptr;
20956
20957 // OpenMP 5.0 [2.12.5, Restrictions]
20958 // In case of ancestor device-modifier, a requires directive with
20959 // the reverse_offload clause must be specified.
20960 if (Modifier == OMPC_DEVICE_ancestor) {
20961 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
20962 SemaRef.targetDiag(
20963 StartLoc,
20964 diag::err_omp_device_ancestor_without_requires_reverse_offload);
20965 ErrorFound = true;
20966 }
20967 }
20968
20969 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
20970 OpenMPDirectiveKind CaptureRegion =
20971 getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP);
20972 if (CaptureRegion != OMPD_unknown &&
20973 !SemaRef.CurContext->isDependentContext()) {
20974 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
20975 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20976 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
20977 HelperValStmt = buildPreInits(getASTContext(), Captures);
20978 }
20979
20980 return new (getASTContext())
20981 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
20982 LParenLoc, ModifierLoc, EndLoc);
20983}
20984
20986 DSAStackTy *Stack, QualType QTy,
20987 bool FullCheck = true) {
20988 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
20989 return false;
20990 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
20991 !QTy.isTriviallyCopyableType(SemaRef.Context))
20992 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
20993 return true;
20994}
20995
20996/// Return true if it can be proven that the provided array expression
20997/// (array section or array subscript) does NOT specify the whole size of the
20998/// array whose base type is \a BaseQTy.
21000 const Expr *E,
21001 QualType BaseQTy) {
21002 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21003
21004 // If this is an array subscript, it refers to the whole size if the size of
21005 // the dimension is constant and equals 1. Also, an array section assumes the
21006 // format of an array subscript if no colon is used.
21007 if (isa<ArraySubscriptExpr>(E) ||
21008 (OASE && OASE->getColonLocFirst().isInvalid())) {
21009 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21010 return ATy->getSExtSize() != 1;
21011 // Size can't be evaluated statically.
21012 return false;
21013 }
21014
21015 assert(OASE && "Expecting array section if not an array subscript.");
21016 const Expr *LowerBound = OASE->getLowerBound();
21017 const Expr *Length = OASE->getLength();
21018
21019 // If there is a lower bound that does not evaluates to zero, we are not
21020 // covering the whole dimension.
21021 if (LowerBound) {
21022 Expr::EvalResult Result;
21023 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
21024 return false; // Can't get the integer value as a constant.
21025
21026 llvm::APSInt ConstLowerBound = Result.Val.getInt();
21027 if (ConstLowerBound.getSExtValue())
21028 return true;
21029 }
21030
21031 // If we don't have a length we covering the whole dimension.
21032 if (!Length)
21033 return false;
21034
21035 // If the base is a pointer, we don't have a way to get the size of the
21036 // pointee.
21037 if (BaseQTy->isPointerType())
21038 return false;
21039
21040 // We can only check if the length is the same as the size of the dimension
21041 // if we have a constant array.
21042 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
21043 if (!CATy)
21044 return false;
21045
21046 Expr::EvalResult Result;
21047 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21048 return false; // Can't get the integer value as a constant.
21049
21050 llvm::APSInt ConstLength = Result.Val.getInt();
21051 return CATy->getSExtSize() != ConstLength.getSExtValue();
21052}
21053
21054// Return true if it can be proven that the provided array expression (array
21055// section or array subscript) does NOT specify a single element of the array
21056// whose base type is \a BaseQTy.
21058 const Expr *E,
21059 QualType BaseQTy) {
21060 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21061
21062 // An array subscript always refer to a single element. Also, an array section
21063 // assumes the format of an array subscript if no colon is used.
21064 if (isa<ArraySubscriptExpr>(E) ||
21065 (OASE && OASE->getColonLocFirst().isInvalid()))
21066 return false;
21067
21068 assert(OASE && "Expecting array section if not an array subscript.");
21069 const Expr *Length = OASE->getLength();
21070
21071 // If we don't have a length we have to check if the array has unitary size
21072 // for this dimension. Also, we should always expect a length if the base type
21073 // is pointer.
21074 if (!Length) {
21075 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21076 return ATy->getSExtSize() != 1;
21077 // We cannot assume anything.
21078 return false;
21079 }
21080
21081 // Check if the length evaluates to 1.
21082 Expr::EvalResult Result;
21083 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21084 return false; // Can't get the integer value as a constant.
21085
21086 llvm::APSInt ConstLength = Result.Val.getInt();
21087 return ConstLength.getSExtValue() != 1;
21088}
21089
21090// The base of elements of list in a map clause have to be either:
21091// - a reference to variable or field.
21092// - a member expression.
21093// - an array expression.
21094//
21095// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
21096// reference to 'r'.
21097//
21098// If we have:
21099//
21100// struct SS {
21101// Bla S;
21102// foo() {
21103// #pragma omp target map (S.Arr[:12]);
21104// }
21105// }
21106//
21107// We want to retrieve the member expression 'this->S';
21108
21109// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
21110// If a list item is an array section, it must specify contiguous storage.
21111//
21112// For this restriction it is sufficient that we make sure only references
21113// to variables or fields and array expressions, and that no array sections
21114// exist except in the rightmost expression (unless they cover the whole
21115// dimension of the array). E.g. these would be invalid:
21116//
21117// r.ArrS[3:5].Arr[6:7]
21118//
21119// r.ArrS[3:5].x
21120//
21121// but these would be valid:
21122// r.ArrS[3].Arr[6:7]
21123//
21124// r.ArrS[3].x
21125namespace {
21126class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
21127 Sema &SemaRef;
21128 OpenMPClauseKind CKind = OMPC_unknown;
21129 OpenMPDirectiveKind DKind = OMPD_unknown;
21131 bool IsNonContiguous = false;
21132 bool NoDiagnose = false;
21133 const Expr *RelevantExpr = nullptr;
21134 bool AllowUnitySizeArraySection = true;
21135 bool AllowWholeSizeArraySection = true;
21136 bool AllowAnotherPtr = true;
21137 SourceLocation ELoc;
21138 SourceRange ERange;
21139
21140 void emitErrorMsg() {
21141 // If nothing else worked, this is not a valid map clause expression.
21142 if (SemaRef.getLangOpts().OpenMP < 50) {
21143 SemaRef.Diag(ELoc,
21144 diag::err_omp_expected_named_var_member_or_array_expression)
21145 << ERange;
21146 } else {
21147 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21148 << getOpenMPClauseNameForDiag(CKind) << ERange;
21149 }
21150 }
21151
21152public:
21153 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
21154 if (!isa<VarDecl>(DRE->getDecl())) {
21155 emitErrorMsg();
21156 return false;
21157 }
21158 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21159 RelevantExpr = DRE;
21160 // Record the component.
21161 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
21162 return true;
21163 }
21164
21165 bool VisitMemberExpr(MemberExpr *ME) {
21166 Expr *E = ME;
21167 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
21168
21169 if (isa<CXXThisExpr>(BaseE)) {
21170 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21171 // We found a base expression: this->Val.
21172 RelevantExpr = ME;
21173 } else {
21174 E = BaseE;
21175 }
21176
21177 if (!isa<FieldDecl>(ME->getMemberDecl())) {
21178 if (!NoDiagnose) {
21179 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
21180 << ME->getSourceRange();
21181 return false;
21182 }
21183 if (RelevantExpr)
21184 return false;
21185 return Visit(E);
21186 }
21187
21188 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
21189
21190 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
21191 // A bit-field cannot appear in a map clause.
21192 //
21193 if (FD->isBitField()) {
21194 if (!NoDiagnose) {
21195 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
21196 << ME->getSourceRange() << getOpenMPClauseNameForDiag(CKind);
21197 return false;
21198 }
21199 if (RelevantExpr)
21200 return false;
21201 return Visit(E);
21202 }
21203
21204 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21205 // If the type of a list item is a reference to a type T then the type
21206 // will be considered to be T for all purposes of this clause.
21207 QualType CurType = BaseE->getType().getNonReferenceType();
21208
21209 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
21210 // A list item cannot be a variable that is a member of a structure with
21211 // a union type.
21212 //
21213 if (CurType->isUnionType()) {
21214 if (!NoDiagnose) {
21215 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
21216 << ME->getSourceRange();
21217 return false;
21218 }
21219 return RelevantExpr || Visit(E);
21220 }
21221
21222 // If we got a member expression, we should not expect any array section
21223 // before that:
21224 //
21225 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
21226 // If a list item is an element of a structure, only the rightmost symbol
21227 // of the variable reference can be an array section.
21228 //
21229 AllowUnitySizeArraySection = false;
21230 AllowWholeSizeArraySection = false;
21231
21232 // Record the component.
21233 Components.emplace_back(ME, FD, IsNonContiguous);
21234 return RelevantExpr || Visit(E);
21235 }
21236
21237 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
21238 Expr *E = AE->getBase()->IgnoreParenImpCasts();
21239
21240 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
21241 if (!NoDiagnose) {
21242 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21243 << 0 << AE->getSourceRange();
21244 return false;
21245 }
21246 return RelevantExpr || Visit(E);
21247 }
21248
21249 // If we got an array subscript that express the whole dimension we
21250 // can have any array expressions before. If it only expressing part of
21251 // the dimension, we can only have unitary-size array expressions.
21253 AllowWholeSizeArraySection = false;
21254
21255 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
21256 Expr::EvalResult Result;
21257 if (!AE->getIdx()->isValueDependent() &&
21258 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
21259 !Result.Val.getInt().isZero()) {
21260 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21261 diag::err_omp_invalid_map_this_expr);
21262 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21263 diag::note_omp_invalid_subscript_on_this_ptr_map);
21264 }
21265 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21266 RelevantExpr = TE;
21267 }
21268
21269 // Record the component - we don't have any declaration associated.
21270 Components.emplace_back(AE, nullptr, IsNonContiguous);
21271
21272 return RelevantExpr || Visit(E);
21273 }
21274
21275 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
21276 // After OMP 5.0 Array section in reduction clause will be implicitly
21277 // mapped
21278 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
21279 "Array sections cannot be implicitly mapped.");
21280 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21281 QualType CurType =
21283
21284 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21285 // If the type of a list item is a reference to a type T then the type
21286 // will be considered to be T for all purposes of this clause.
21287 if (CurType->isReferenceType())
21288 CurType = CurType->getPointeeType();
21289
21290 bool IsPointer = CurType->isAnyPointerType();
21291
21292 if (!IsPointer && !CurType->isArrayType()) {
21293 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21294 << 0 << OASE->getSourceRange();
21295 return false;
21296 }
21297
21298 bool NotWhole =
21299 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
21300 bool NotUnity =
21301 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
21302
21303 if (AllowWholeSizeArraySection) {
21304 // Any array section is currently allowed. Allowing a whole size array
21305 // section implies allowing a unity array section as well.
21306 //
21307 // If this array section refers to the whole dimension we can still
21308 // accept other array sections before this one, except if the base is a
21309 // pointer. Otherwise, only unitary sections are accepted.
21310 if (NotWhole || IsPointer)
21311 AllowWholeSizeArraySection = false;
21312 } else if (DKind == OMPD_target_update &&
21313 SemaRef.getLangOpts().OpenMP >= 50) {
21314 if (IsPointer && !AllowAnotherPtr)
21315 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
21316 << /*array of unknown bound */ 1;
21317 else
21318 IsNonContiguous = true;
21319 } else if (AllowUnitySizeArraySection && NotUnity) {
21320 // A unity or whole array section is not allowed and that is not
21321 // compatible with the properties of the current array section.
21322 if (NoDiagnose)
21323 return false;
21324 SemaRef.Diag(ELoc,
21325 diag::err_array_section_does_not_specify_contiguous_storage)
21326 << OASE->getSourceRange();
21327 return false;
21328 }
21329
21330 if (IsPointer)
21331 AllowAnotherPtr = false;
21332
21333 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
21334 Expr::EvalResult ResultR;
21335 Expr::EvalResult ResultL;
21336 if (!OASE->getLength()->isValueDependent() &&
21337 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
21338 !ResultR.Val.getInt().isOne()) {
21339 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21340 diag::err_omp_invalid_map_this_expr);
21341 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21342 diag::note_omp_invalid_length_on_this_ptr_mapping);
21343 }
21344 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
21345 OASE->getLowerBound()->EvaluateAsInt(ResultL,
21346 SemaRef.getASTContext()) &&
21347 !ResultL.Val.getInt().isZero()) {
21348 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21349 diag::err_omp_invalid_map_this_expr);
21350 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21351 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
21352 }
21353 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21354 RelevantExpr = TE;
21355 }
21356
21357 // Record the component - we don't have any declaration associated.
21358 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
21359 return RelevantExpr || Visit(E);
21360 }
21361 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
21362 Expr *Base = E->getBase();
21363
21364 // Record the component - we don't have any declaration associated.
21365 Components.emplace_back(E, nullptr, IsNonContiguous);
21366
21367 return Visit(Base->IgnoreParenImpCasts());
21368 }
21369
21370 bool VisitUnaryOperator(UnaryOperator *UO) {
21371 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
21372 UO->getOpcode() != UO_Deref) {
21373 emitErrorMsg();
21374 return false;
21375 }
21376 if (!RelevantExpr) {
21377 // Record the component if haven't found base decl.
21378 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
21379 }
21380 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
21381 }
21382 bool VisitBinaryOperator(BinaryOperator *BO) {
21383 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
21384 emitErrorMsg();
21385 return false;
21386 }
21387
21388 // Pointer arithmetic is the only thing we expect to happen here so after we
21389 // make sure the binary operator is a pointer type, the only thing we need
21390 // to do is to visit the subtree that has the same type as root (so that we
21391 // know the other subtree is just an offset)
21392 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
21393 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
21394 Components.emplace_back(BO, nullptr, false);
21395 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
21396 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
21397 "Either LHS or RHS have base decl inside");
21398 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
21399 return RelevantExpr || Visit(LE);
21400 return RelevantExpr || Visit(RE);
21401 }
21402 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
21403 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21404 RelevantExpr = CTE;
21405 Components.emplace_back(CTE, nullptr, IsNonContiguous);
21406 return true;
21407 }
21408 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
21409 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21410 Components.emplace_back(COCE, nullptr, IsNonContiguous);
21411 return true;
21412 }
21413 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
21414 Expr *Source = E->getSourceExpr();
21415 if (!Source) {
21416 emitErrorMsg();
21417 return false;
21418 }
21419 return Visit(Source);
21420 }
21421 bool VisitStmt(Stmt *) {
21422 emitErrorMsg();
21423 return false;
21424 }
21425 const Expr *getFoundBase() const { return RelevantExpr; }
21426 explicit MapBaseChecker(
21427 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
21429 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
21430 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
21431 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
21432};
21433} // namespace
21434
21435/// Return the expression of the base of the mappable expression or null if it
21436/// cannot be determined and do all the necessary checks to see if the
21437/// expression is valid as a standalone mappable expression. In the process,
21438/// record all the components of the expression.
21440 Sema &SemaRef, Expr *E,
21442 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
21443 SourceLocation ELoc = E->getExprLoc();
21444 SourceRange ERange = E->getSourceRange();
21445 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
21446 ERange);
21447 if (Checker.Visit(E->IgnoreParens())) {
21448 // Check if the highest dimension array section has length specified
21449 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
21450 (CKind == OMPC_to || CKind == OMPC_from)) {
21451 auto CI = CurComponents.rbegin();
21452 auto CE = CurComponents.rend();
21453 for (; CI != CE; ++CI) {
21454 const auto *OASE =
21455 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
21456 if (!OASE)
21457 continue;
21458 if (OASE && OASE->getLength())
21459 break;
21460 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
21461 << ERange;
21462 }
21463 }
21464 return Checker.getFoundBase();
21465 }
21466 return nullptr;
21467}
21468
21469// Return true if expression E associated with value VD has conflicts with other
21470// map information.
21472 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
21473 bool CurrentRegionOnly,
21475 OpenMPClauseKind CKind) {
21476 assert(VD && E);
21477 SourceLocation ELoc = E->getExprLoc();
21478 SourceRange ERange = E->getSourceRange();
21479
21480 // In order to easily check the conflicts we need to match each component of
21481 // the expression under test with the components of the expressions that are
21482 // already in the stack.
21483
21484 assert(!CurComponents.empty() && "Map clause expression with no components!");
21485 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
21486 "Map clause expression with unexpected base!");
21487
21488 // Variables to help detecting enclosing problems in data environment nests.
21489 bool IsEnclosedByDataEnvironmentExpr = false;
21490 const Expr *EnclosingExpr = nullptr;
21491
21492 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
21493 VD, CurrentRegionOnly,
21494 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
21495 ERange, CKind, &EnclosingExpr,
21497 StackComponents,
21498 OpenMPClauseKind Kind) {
21499 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
21500 return false;
21501 assert(!StackComponents.empty() &&
21502 "Map clause expression with no components!");
21503 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
21504 "Map clause expression with unexpected base!");
21505 (void)VD;
21506
21507 // The whole expression in the stack.
21508 const Expr *RE = StackComponents.front().getAssociatedExpression();
21509
21510 // Expressions must start from the same base. Here we detect at which
21511 // point both expressions diverge from each other and see if we can
21512 // detect if the memory referred to both expressions is contiguous and
21513 // do not overlap.
21514 auto CI = CurComponents.rbegin();
21515 auto CE = CurComponents.rend();
21516 auto SI = StackComponents.rbegin();
21517 auto SE = StackComponents.rend();
21518 for (; CI != CE && SI != SE; ++CI, ++SI) {
21519
21520 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
21521 // At most one list item can be an array item derived from a given
21522 // variable in map clauses of the same construct.
21523 if (CurrentRegionOnly &&
21524 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
21525 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
21526 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
21527 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
21528 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
21529 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
21530 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
21531 diag::err_omp_multiple_array_items_in_map_clause)
21532 << CI->getAssociatedExpression()->getSourceRange();
21533 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
21534 diag::note_used_here)
21535 << SI->getAssociatedExpression()->getSourceRange();
21536 return true;
21537 }
21538
21539 // Do both expressions have the same kind?
21540 if (CI->getAssociatedExpression()->getStmtClass() !=
21541 SI->getAssociatedExpression()->getStmtClass())
21542 break;
21543
21544 // Are we dealing with different variables/fields?
21545 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
21546 break;
21547 }
21548 // Check if the extra components of the expressions in the enclosing
21549 // data environment are redundant for the current base declaration.
21550 // If they are, the maps completely overlap, which is legal.
21551 for (; SI != SE; ++SI) {
21552 QualType Type;
21553 if (const auto *ASE =
21554 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
21555 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
21556 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
21557 SI->getAssociatedExpression())) {
21558 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21560 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
21561 SI->getAssociatedExpression())) {
21562 Type = OASE->getBase()->getType()->getPointeeType();
21563 }
21564 if (Type.isNull() || Type->isAnyPointerType() ||
21566 SemaRef, SI->getAssociatedExpression(), Type))
21567 break;
21568 }
21569
21570 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21571 // List items of map clauses in the same construct must not share
21572 // original storage.
21573 //
21574 // If the expressions are exactly the same or one is a subset of the
21575 // other, it means they are sharing storage.
21576 if (CI == CE && SI == SE) {
21577 if (CurrentRegionOnly) {
21578 if (CKind == OMPC_map) {
21579 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21580 } else {
21581 assert(CKind == OMPC_to || CKind == OMPC_from);
21582 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21583 << ERange;
21584 }
21585 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21586 << RE->getSourceRange();
21587 return true;
21588 }
21589 // If we find the same expression in the enclosing data environment,
21590 // that is legal.
21591 IsEnclosedByDataEnvironmentExpr = true;
21592 return false;
21593 }
21594
21595 QualType DerivedType =
21596 std::prev(CI)->getAssociatedDeclaration()->getType();
21597 SourceLocation DerivedLoc =
21598 std::prev(CI)->getAssociatedExpression()->getExprLoc();
21599
21600 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21601 // If the type of a list item is a reference to a type T then the type
21602 // will be considered to be T for all purposes of this clause.
21603 DerivedType = DerivedType.getNonReferenceType();
21604
21605 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
21606 // A variable for which the type is pointer and an array section
21607 // derived from that variable must not appear as list items of map
21608 // clauses of the same construct.
21609 //
21610 // Also, cover one of the cases in:
21611 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21612 // If any part of the original storage of a list item has corresponding
21613 // storage in the device data environment, all of the original storage
21614 // must have corresponding storage in the device data environment.
21615 //
21616 if (DerivedType->isAnyPointerType()) {
21617 if (CI == CE || SI == SE) {
21618 SemaRef.Diag(
21619 DerivedLoc,
21620 diag::err_omp_pointer_mapped_along_with_derived_section)
21621 << DerivedLoc;
21622 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21623 << RE->getSourceRange();
21624 return true;
21625 }
21626 if (CI->getAssociatedExpression()->getStmtClass() !=
21627 SI->getAssociatedExpression()->getStmtClass() ||
21628 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
21629 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
21630 assert(CI != CE && SI != SE);
21631 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
21632 << DerivedLoc;
21633 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21634 << RE->getSourceRange();
21635 return true;
21636 }
21637 }
21638
21639 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21640 // List items of map clauses in the same construct must not share
21641 // original storage.
21642 //
21643 // An expression is a subset of the other.
21644 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
21645 if (CKind == OMPC_map) {
21646 if (CI != CE || SI != SE) {
21647 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
21648 // a pointer.
21649 auto Begin =
21650 CI != CE ? CurComponents.begin() : StackComponents.begin();
21651 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
21652 auto It = Begin;
21653 while (It != End && !It->getAssociatedDeclaration())
21654 std::advance(It, 1);
21655 assert(It != End &&
21656 "Expected at least one component with the declaration.");
21657 if (It != Begin && It->getAssociatedDeclaration()
21658 ->getType()
21659 .getCanonicalType()
21660 ->isAnyPointerType()) {
21661 IsEnclosedByDataEnvironmentExpr = false;
21662 EnclosingExpr = nullptr;
21663 return false;
21664 }
21665 }
21666 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21667 } else {
21668 assert(CKind == OMPC_to || CKind == OMPC_from);
21669 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21670 << ERange;
21671 }
21672 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21673 << RE->getSourceRange();
21674 return true;
21675 }
21676
21677 // The current expression uses the same base as other expression in the
21678 // data environment but does not contain it completely.
21679 if (!CurrentRegionOnly && SI != SE)
21680 EnclosingExpr = RE;
21681
21682 // The current expression is a subset of the expression in the data
21683 // environment.
21684 IsEnclosedByDataEnvironmentExpr |=
21685 (!CurrentRegionOnly && CI != CE && SI == SE);
21686
21687 return false;
21688 });
21689
21690 if (CurrentRegionOnly)
21691 return FoundError;
21692
21693 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21694 // If any part of the original storage of a list item has corresponding
21695 // storage in the device data environment, all of the original storage must
21696 // have corresponding storage in the device data environment.
21697 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
21698 // If a list item is an element of a structure, and a different element of
21699 // the structure has a corresponding list item in the device data environment
21700 // prior to a task encountering the construct associated with the map clause,
21701 // then the list item must also have a corresponding list item in the device
21702 // data environment prior to the task encountering the construct.
21703 //
21704 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
21705 SemaRef.Diag(ELoc,
21706 diag::err_omp_original_storage_is_shared_and_does_not_contain)
21707 << ERange;
21708 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
21709 << EnclosingExpr->getSourceRange();
21710 return true;
21711 }
21712
21713 return FoundError;
21714}
21715
21716// Look up the user-defined mapper given the mapper name and mapped type, and
21717// build a reference to it.
21719 CXXScopeSpec &MapperIdScopeSpec,
21720 const DeclarationNameInfo &MapperId,
21721 QualType Type,
21722 Expr *UnresolvedMapper) {
21723 if (MapperIdScopeSpec.isInvalid())
21724 return ExprError();
21725 // Get the actual type for the array type.
21726 if (Type->isArrayType()) {
21727 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
21729 }
21730 // Find all user-defined mappers with the given MapperId.
21731 SmallVector<UnresolvedSet<8>, 4> Lookups;
21732 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
21733 Lookup.suppressDiagnostics();
21734 if (S) {
21735 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
21736 /*ObjectType=*/QualType())) {
21737 NamedDecl *D = Lookup.getRepresentativeDecl();
21738 while (S && !S->isDeclScope(D))
21739 S = S->getParent();
21740 if (S)
21741 S = S->getParent();
21742 Lookups.emplace_back();
21743 Lookups.back().append(Lookup.begin(), Lookup.end());
21744 Lookup.clear();
21745 }
21746 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
21747 // Extract the user-defined mappers with the given MapperId.
21748 Lookups.push_back(UnresolvedSet<8>());
21749 for (NamedDecl *D : ULE->decls()) {
21750 auto *DMD = cast<OMPDeclareMapperDecl>(D);
21751 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
21752 Lookups.back().addDecl(DMD);
21753 }
21754 }
21755 // Defer the lookup for dependent types. The results will be passed through
21756 // UnresolvedMapper on instantiation.
21757 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21761 return !D->isInvalidDecl() &&
21762 (D->getType()->isDependentType() ||
21763 D->getType()->isInstantiationDependentType() ||
21764 D->getType()->containsUnexpandedParameterPack());
21765 })) {
21766 UnresolvedSet<8> URS;
21767 for (const UnresolvedSet<8> &Set : Lookups) {
21768 if (Set.empty())
21769 continue;
21770 URS.append(Set.begin(), Set.end());
21771 }
21773 SemaRef.Context, /*NamingClass=*/nullptr,
21774 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
21775 /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false,
21776 /*KnownInstantiationDependent=*/false);
21777 }
21778 SourceLocation Loc = MapperId.getLoc();
21779 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21780 // The type must be of struct, union or class type in C and C++
21782 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
21783 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
21784 return ExprError();
21785 }
21786 // Perform argument dependent lookup.
21787 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21788 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
21789 // Return the first user-defined mapper with the desired type.
21791 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21792 if (!D->isInvalidDecl() &&
21793 SemaRef.Context.hasSameType(D->getType(), Type))
21794 return D;
21795 return nullptr;
21796 }))
21797 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21798 // Find the first user-defined mapper with a type derived from the desired
21799 // type.
21801 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21802 if (!D->isInvalidDecl() &&
21803 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
21804 !Type.isMoreQualifiedThan(D->getType(),
21805 SemaRef.getASTContext()))
21806 return D;
21807 return nullptr;
21808 })) {
21809 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21810 /*DetectVirtual=*/false);
21811 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
21812 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
21813 VD->getType().getUnqualifiedType()))) {
21814 if (SemaRef.CheckBaseClassAccess(
21815 Loc, VD->getType(), Type, Paths.front(),
21816 /*DiagID=*/0) != Sema::AR_inaccessible) {
21817 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21818 }
21819 }
21820 }
21821 }
21822 // Report error if a mapper is specified, but cannot be found.
21823 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
21824 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
21825 << Type << MapperId.getName();
21826 return ExprError();
21827 }
21828 return ExprEmpty();
21829}
21830
21831namespace {
21832// Utility struct that gathers all the related lists associated with a mappable
21833// expression.
21834struct MappableVarListInfo {
21835 // The list of expressions.
21836 ArrayRef<Expr *> VarList;
21837 // The list of processed expressions.
21838 SmallVector<Expr *, 16> ProcessedVarList;
21839 // The mappble components for each expression.
21841 // The base declaration of the variable.
21842 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
21843 // The reference to the user-defined mapper associated with every expression.
21844 SmallVector<Expr *, 16> UDMapperList;
21845
21846 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
21847 // We have a list of components and base declarations for each entry in the
21848 // variable list.
21849 VarComponents.reserve(VarList.size());
21850 VarBaseDeclarations.reserve(VarList.size());
21851 }
21852};
21853} // namespace
21854
21856 DSAStackTy *Stack,
21858
21859 const RecordDecl *RD = BaseType->getAsRecordDecl();
21860 SourceRange Range = RD->getSourceRange();
21861 DeclarationNameInfo ImplicitName;
21862 // Dummy variable _s for Mapper.
21863 VarDecl *VD = buildVarDecl(S, Range.getEnd(), BaseType, "_s");
21864 DeclRefExpr *MapperVarRef =
21865 buildDeclRefExpr(S, VD, BaseType, SourceLocation());
21866
21867 // Create implicit map clause for mapper.
21869 for (auto *FD : RD->fields()) {
21870 Expr *BE = S.BuildMemberExpr(
21871 MapperVarRef, /*IsArrow=*/false, Range.getBegin(),
21872 NestedNameSpecifierLoc(), Range.getBegin(), FD,
21874 /*HadMultipleCandidates=*/false,
21876 FD->getType(), VK_LValue, OK_Ordinary);
21877 SExprs.push_back(BE);
21878 }
21879 CXXScopeSpec MapperIdScopeSpec;
21880 DeclarationNameInfo MapperId;
21881 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
21882
21883 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
21884 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec,
21885 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
21886 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), SExprs,
21887 OMPVarListLocTy());
21888 Maps.push_back(MapClause);
21889 return MapperVarRef;
21890}
21891
21893 DSAStackTy *Stack) {
21894
21895 // Build impilicit map for mapper
21897 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
21898
21899 const RecordDecl *RD = BaseType->getAsRecordDecl();
21900 // AST context is RD's ParentASTContext().
21901 ASTContext &Ctx = RD->getParentASTContext();
21902 // DeclContext is RD's DeclContext.
21903 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
21904
21905 // Create implicit default mapper for "RD".
21906 DeclarationName MapperId;
21907 auto &DeclNames = Ctx.DeclarationNames;
21908 MapperId = DeclNames.getIdentifier(&Ctx.Idents.get("default"));
21909 auto *DMD = OMPDeclareMapperDecl::Create(Ctx, DCT, SourceLocation(), MapperId,
21910 BaseType, MapperId, Maps, nullptr);
21911 Scope *Scope = S.getScopeForContext(DCT);
21912 if (Scope)
21913 S.PushOnScopeChains(DMD, Scope, /*AddToContext=*/false);
21914 DCT->addDecl(DMD);
21915 DMD->setAccess(clang::AS_none);
21916 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
21917 VD->setDeclContext(DMD);
21918 VD->setLexicalDeclContext(DMD);
21919 DMD->addDecl(VD);
21920 DMD->setMapperVarRef(MapperVarRef);
21921 FieldDecl *FD = *RD->field_begin();
21922 // create mapper refence.
21924 DMD, false, SourceLocation(), BaseType, VK_LValue);
21925}
21926
21927// Look up the user-defined mapper given the mapper name and mapper type,
21928// return true if found one.
21929static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
21930 CXXScopeSpec &MapperIdScopeSpec,
21931 const DeclarationNameInfo &MapperId,
21932 QualType Type) {
21933 // Find all user-defined mappers with the given MapperId.
21934 SmallVector<UnresolvedSet<8>, 4> Lookups;
21935 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
21936 Lookup.suppressDiagnostics();
21937 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
21938 /*ObjectType=*/QualType())) {
21939 NamedDecl *D = Lookup.getRepresentativeDecl();
21940 while (S && !S->isDeclScope(D))
21941 S = S->getParent();
21942 if (S)
21943 S = S->getParent();
21944 Lookups.emplace_back();
21945 Lookups.back().append(Lookup.begin(), Lookup.end());
21946 Lookup.clear();
21947 }
21948 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21952 return !D->isInvalidDecl() &&
21953 (D->getType()->isDependentType() ||
21954 D->getType()->isInstantiationDependentType() ||
21955 D->getType()->containsUnexpandedParameterPack());
21956 }))
21957 return false;
21958 // Perform argument dependent lookup.
21959 SourceLocation Loc = MapperId.getLoc();
21960 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21961 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
21963 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21964 if (!D->isInvalidDecl() &&
21965 SemaRef.Context.hasSameType(D->getType(), Type))
21966 return D;
21967 return nullptr;
21968 }))
21969 return true;
21970 // Find the first user-defined mapper with a type derived from the desired
21971 // type.
21973 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21974 if (!D->isInvalidDecl() &&
21975 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
21976 !Type.isMoreQualifiedThan(D->getType(), SemaRef.getASTContext()))
21977 return D;
21978 return nullptr;
21979 });
21980 if (!VD)
21981 return false;
21982 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21983 /*DetectVirtual=*/false);
21984 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
21985 bool IsAmbiguous = !Paths.isAmbiguous(
21987 if (IsAmbiguous)
21988 return false;
21989 if (SemaRef.CheckBaseClassAccess(Loc, VD->getType(), Type, Paths.front(),
21990 /*DiagID=*/0) != Sema::AR_inaccessible)
21991 return true;
21992 }
21993 return false;
21994}
21995
21996static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
21997 QualType CanonType, const Expr *E) {
21998
21999 // DFS over data members in structures/classes.
22001 {CanonType, nullptr});
22002 llvm::DenseMap<const Type *, bool> Visited;
22003 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
22004 while (!Types.empty()) {
22005 auto [BaseType, CurFD] = Types.pop_back_val();
22006 while (ParentChain.back().second == 0)
22007 ParentChain.pop_back();
22008 --ParentChain.back().second;
22009 if (BaseType.isNull())
22010 continue;
22011 // Only structs/classes are allowed to have mappers.
22012 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
22013 if (!RD)
22014 continue;
22015 auto It = Visited.find(BaseType.getTypePtr());
22016 if (It == Visited.end()) {
22017 // Try to find the associated user-defined mapper.
22018 CXXScopeSpec MapperIdScopeSpec;
22019 DeclarationNameInfo DefaultMapperId;
22021 &S.Context.Idents.get("default")));
22022 DefaultMapperId.setLoc(E->getExprLoc());
22023 bool HasUDMapper =
22024 hasUserDefinedMapper(S, Stack->getCurScope(), MapperIdScopeSpec,
22025 DefaultMapperId, BaseType);
22026 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
22027 }
22028 // Found default mapper.
22029 if (It->second)
22030 return true;
22031 // Check for the "default" mapper for data members.
22032 bool FirstIter = true;
22033 for (FieldDecl *FD : RD->fields()) {
22034 if (!FD)
22035 continue;
22036 QualType FieldTy = FD->getType();
22037 if (FieldTy.isNull() ||
22038 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
22039 continue;
22040 if (FirstIter) {
22041 FirstIter = false;
22042 ParentChain.emplace_back(CurFD, 1);
22043 } else {
22044 ++ParentChain.back().second;
22045 }
22046 Types.emplace_back(FieldTy, FD);
22047 }
22048 }
22049 return false;
22050}
22051
22052// Check the validity of the provided variable list for the provided clause kind
22053// \a CKind. In the check process the valid expressions, mappable expression
22054// components, variables, and user-defined mappers are extracted and used to
22055// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
22056// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
22057// and \a MapperId are expected to be valid if the clause kind is 'map'.
22059 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
22060 MappableVarListInfo &MVLI, SourceLocation StartLoc,
22061 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
22062 ArrayRef<Expr *> UnresolvedMappers,
22064 ArrayRef<OpenMPMapModifierKind> Modifiers = {},
22065 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
22066 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
22067 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
22068 "Unexpected clause kind with mappable expressions!");
22069 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
22070
22071 // If the identifier of user-defined mapper is not specified, it is "default".
22072 // We do not change the actual name in this clause to distinguish whether a
22073 // mapper is specified explicitly, i.e., it is not explicitly specified when
22074 // MapperId.getName() is empty.
22075 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
22076 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
22077 MapperId.setName(DeclNames.getIdentifier(
22078 &SemaRef.getASTContext().Idents.get("default")));
22079 MapperId.setLoc(StartLoc);
22080 }
22081
22082 // Iterators to find the current unresolved mapper expression.
22083 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
22084 bool UpdateUMIt = false;
22085 Expr *UnresolvedMapper = nullptr;
22086
22087 bool HasHoldModifier =
22088 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
22089
22090 // Keep track of the mappable components and base declarations in this clause.
22091 // Each entry in the list is going to have a list of components associated. We
22092 // record each set of the components so that we can build the clause later on.
22093 // In the end we should have the same amount of declarations and component
22094 // lists.
22095
22096 for (Expr *RE : MVLI.VarList) {
22097 assert(RE && "Null expr in omp to/from/map clause");
22098 SourceLocation ELoc = RE->getExprLoc();
22099
22100 // Find the current unresolved mapper expression.
22101 if (UpdateUMIt && UMIt != UMEnd) {
22102 UMIt++;
22103 assert(
22104 UMIt != UMEnd &&
22105 "Expect the size of UnresolvedMappers to match with that of VarList");
22106 }
22107 UpdateUMIt = true;
22108 if (UMIt != UMEnd)
22109 UnresolvedMapper = *UMIt;
22110
22111 const Expr *VE = RE->IgnoreParenLValueCasts();
22112
22113 if (VE->isValueDependent() || VE->isTypeDependent() ||
22114 VE->isInstantiationDependent() ||
22115 VE->containsUnexpandedParameterPack()) {
22116 // Try to find the associated user-defined mapper.
22118 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22119 VE->getType().getCanonicalType(), UnresolvedMapper);
22120 if (ER.isInvalid())
22121 continue;
22122 MVLI.UDMapperList.push_back(ER.get());
22123 // We can only analyze this information once the missing information is
22124 // resolved.
22125 MVLI.ProcessedVarList.push_back(RE);
22126 continue;
22127 }
22128
22130
22131 if (!RE->isLValue()) {
22132 if (SemaRef.getLangOpts().OpenMP < 50) {
22133 SemaRef.Diag(
22134 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
22135 << RE->getSourceRange();
22136 } else {
22137 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22138 << getOpenMPClauseNameForDiag(CKind) << RE->getSourceRange();
22139 }
22140 continue;
22141 }
22142
22144 ValueDecl *CurDeclaration = nullptr;
22145
22146 // Obtain the array or member expression bases if required. Also, fill the
22147 // components array with all the components identified in the process.
22148 const Expr *BE =
22149 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
22150 DSAS->getCurrentDirective(), NoDiagnose);
22151 if (!BE)
22152 continue;
22153
22154 assert(!CurComponents.empty() &&
22155 "Invalid mappable expression information.");
22156
22157 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
22158 // Add store "this" pointer to class in DSAStackTy for future checking
22159 DSAS->addMappedClassesQualTypes(TE->getType());
22160 // Try to find the associated user-defined mapper.
22162 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22163 VE->getType().getCanonicalType(), UnresolvedMapper);
22164 if (ER.isInvalid())
22165 continue;
22166 MVLI.UDMapperList.push_back(ER.get());
22167 // Skip restriction checking for variable or field declarations
22168 MVLI.ProcessedVarList.push_back(RE);
22169 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22170 MVLI.VarComponents.back().append(CurComponents.begin(),
22171 CurComponents.end());
22172 MVLI.VarBaseDeclarations.push_back(nullptr);
22173 continue;
22174 }
22175
22176 // For the following checks, we rely on the base declaration which is
22177 // expected to be associated with the last component. The declaration is
22178 // expected to be a variable or a field (if 'this' is being mapped).
22179 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
22180 assert(CurDeclaration && "Null decl on map clause.");
22181 assert(
22182 CurDeclaration->isCanonicalDecl() &&
22183 "Expecting components to have associated only canonical declarations.");
22184
22185 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
22186 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
22187
22188 assert((VD || FD) && "Only variables or fields are expected here!");
22189 (void)FD;
22190
22191 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
22192 // threadprivate variables cannot appear in a map clause.
22193 // OpenMP 4.5 [2.10.5, target update Construct]
22194 // threadprivate variables cannot appear in a from clause.
22195 if (VD && DSAS->isThreadPrivate(VD)) {
22196 if (NoDiagnose)
22197 continue;
22198 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
22199 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
22201 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
22202 continue;
22203 }
22204
22205 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22206 // A list item cannot appear in both a map clause and a data-sharing
22207 // attribute clause on the same construct.
22208
22209 // Check conflicts with other map clause expressions. We check the conflicts
22210 // with the current construct separately from the enclosing data
22211 // environment, because the restrictions are different. We only have to
22212 // check conflicts across regions for the map clauses.
22213 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
22214 /*CurrentRegionOnly=*/true, CurComponents, CKind))
22215 break;
22216 if (CKind == OMPC_map &&
22217 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
22218 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
22219 /*CurrentRegionOnly=*/false, CurComponents, CKind))
22220 break;
22221
22222 // OpenMP 4.5 [2.10.5, target update Construct]
22223 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22224 // If the type of a list item is a reference to a type T then the type will
22225 // be considered to be T for all purposes of this clause.
22226 auto I = llvm::find_if(
22227 CurComponents,
22229 return MC.getAssociatedDeclaration();
22230 });
22231 assert(I != CurComponents.end() && "Null decl on map clause.");
22232 (void)I;
22233 QualType Type;
22234 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
22235 auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens());
22236 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
22237 if (ASE) {
22238 Type = ASE->getType().getNonReferenceType();
22239 } else if (OASE) {
22240 QualType BaseType =
22242 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
22243 Type = ATy->getElementType();
22244 else
22245 Type = BaseType->getPointeeType();
22246 Type = Type.getNonReferenceType();
22247 } else if (OAShE) {
22248 Type = OAShE->getBase()->getType()->getPointeeType();
22249 } else {
22250 Type = VE->getType();
22251 }
22252
22253 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
22254 // A list item in a to or from clause must have a mappable type.
22255 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22256 // A list item must have a mappable type.
22257 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
22258 DSAS, Type, /*FullCheck=*/true))
22259 continue;
22260
22261 if (CKind == OMPC_map) {
22262 // target enter data
22263 // OpenMP [2.10.2, Restrictions, p. 99]
22264 // A map-type must be specified in all map clauses and must be either
22265 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
22266 // no map type is present.
22267 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
22268 if (DKind == OMPD_target_enter_data &&
22269 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
22270 SemaRef.getLangOpts().OpenMP >= 52)) {
22271 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22272 << (IsMapTypeImplicit ? 1 : 0)
22273 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22274 << getOpenMPDirectiveName(DKind, OMPVersion);
22275 continue;
22276 }
22277
22278 // target exit_data
22279 // OpenMP [2.10.3, Restrictions, p. 102]
22280 // A map-type must be specified in all map clauses and must be either
22281 // from, release, or delete. Starting with OpenMP 5.2 the default map
22282 // type is `from` if no map type is present.
22283 if (DKind == OMPD_target_exit_data &&
22284 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
22285 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
22286 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22287 << (IsMapTypeImplicit ? 1 : 0)
22288 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22289 << getOpenMPDirectiveName(DKind, OMPVersion);
22290 continue;
22291 }
22292
22293 // The 'ompx_hold' modifier is specifically intended to be used on a
22294 // 'target' or 'target data' directive to prevent data from being unmapped
22295 // during the associated statement. It is not permitted on a 'target
22296 // enter data' or 'target exit data' directive, which have no associated
22297 // statement.
22298 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
22299 HasHoldModifier) {
22300 SemaRef.Diag(StartLoc,
22301 diag::err_omp_invalid_map_type_modifier_for_directive)
22303 OMPC_MAP_MODIFIER_ompx_hold)
22304 << getOpenMPDirectiveName(DKind, OMPVersion);
22305 continue;
22306 }
22307
22308 // target, target data
22309 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
22310 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
22311 // A map-type in a map clause must be to, from, tofrom or alloc
22312 if ((DKind == OMPD_target_data ||
22314 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
22315 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
22316 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22317 << (IsMapTypeImplicit ? 1 : 0)
22318 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22319 << getOpenMPDirectiveName(DKind, OMPVersion);
22320 continue;
22321 }
22322
22323 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
22324 // A list item cannot appear in both a map clause and a data-sharing
22325 // attribute clause on the same construct
22326 //
22327 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
22328 // A list item cannot appear in both a map clause and a data-sharing
22329 // attribute clause on the same construct unless the construct is a
22330 // combined construct.
22331 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
22333 DKind == OMPD_target)) {
22334 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
22335 if (isOpenMPPrivate(DVar.CKind)) {
22336 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22337 << getOpenMPClauseNameForDiag(DVar.CKind)
22338 << getOpenMPClauseNameForDiag(OMPC_map)
22339 << getOpenMPDirectiveName(DSAS->getCurrentDirective(),
22340 OMPVersion);
22341 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
22342 continue;
22343 }
22344 }
22345 }
22346
22347 // Try to find the associated user-defined mapper.
22349 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22350 Type.getCanonicalType(), UnresolvedMapper);
22351 if (ER.isInvalid())
22352 continue;
22353
22354 // If no user-defined mapper is found, we need to create an implicit one for
22355 // arrays/array-sections on structs that have members that have
22356 // user-defined mappers. This is needed to ensure that the mapper for the
22357 // member is invoked when mapping each element of the array/array-section.
22358 if (!ER.get()) {
22359 QualType BaseType;
22360
22362 BaseType = VE->getType().getCanonicalType();
22363 if (BaseType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
22364 const auto *OASE = cast<ArraySectionExpr>(VE->IgnoreParenImpCasts());
22365 QualType BType =
22367 QualType ElemType;
22368 if (const auto *ATy = BType->getAsArrayTypeUnsafe())
22369 ElemType = ATy->getElementType();
22370 else
22371 ElemType = BType->getPointeeType();
22372 BaseType = ElemType.getCanonicalType();
22373 }
22374 } else if (VE->getType()->isArrayType()) {
22375 const ArrayType *AT = VE->getType()->getAsArrayTypeUnsafe();
22376 const QualType ElemType = AT->getElementType();
22377 BaseType = ElemType.getCanonicalType();
22378 }
22379
22380 if (!BaseType.isNull() && BaseType->getAsRecordDecl() &&
22381 isImplicitMapperNeeded(SemaRef, DSAS, BaseType, VE)) {
22382 ER = buildImplicitMapper(SemaRef, BaseType, DSAS);
22383 }
22384 }
22385 MVLI.UDMapperList.push_back(ER.get());
22386
22387 // Save the current expression.
22388 MVLI.ProcessedVarList.push_back(RE);
22389
22390 // Store the components in the stack so that they can be used to check
22391 // against other clauses later on.
22392 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
22393 /*WhereFoundClauseKind=*/OMPC_map);
22394
22395 // Save the components and declaration to create the clause. For purposes of
22396 // the clause creation, any component list that has base 'this' uses
22397 // null as base declaration.
22398 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22399 MVLI.VarComponents.back().append(CurComponents.begin(),
22400 CurComponents.end());
22401 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
22402 : CurDeclaration);
22403 }
22404}
22405
22407 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
22408 ArrayRef<SourceLocation> MapTypeModifiersLoc,
22409 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22410 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
22411 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22412 const OMPVarListLocTy &Locs, bool NoDiagnose,
22413 ArrayRef<Expr *> UnresolvedMappers) {
22414 OpenMPMapModifierKind Modifiers[] = {
22420
22421 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
22422 BuiltinType::OMPIterator))
22423 Diag(IteratorModifier->getExprLoc(),
22424 diag::err_omp_map_modifier_not_iterator);
22425
22426 // Process map-type-modifiers, flag errors for duplicate modifiers.
22427 unsigned Count = 0;
22428 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
22429 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
22430 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
22431 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
22432 continue;
22433 }
22434 assert(Count < NumberOfOMPMapClauseModifiers &&
22435 "Modifiers exceed the allowed number of map type modifiers");
22436 Modifiers[Count] = MapTypeModifiers[I];
22437 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
22438 ++Count;
22439 }
22440
22441 MappableVarListInfo MVLI(VarList);
22443 MapperIdScopeSpec, MapperId, UnresolvedMappers,
22444 MapType, Modifiers, IsMapTypeImplicit,
22445 NoDiagnose);
22446
22447 // We need to produce a map clause even if we don't have variables so that
22448 // other diagnostics related with non-existing map clauses are accurate.
22449 return OMPMapClause::Create(
22450 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22451 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
22452 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
22453 MapperId, MapType, IsMapTypeImplicit, MapLoc);
22454}
22455
22458 assert(ParsedType.isUsable());
22459
22460 QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get());
22461 if (ReductionType.isNull())
22462 return QualType();
22463
22464 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
22465 // A type name in a declare reduction directive cannot be a function type, an
22466 // array type, a reference type, or a type qualified with const, volatile or
22467 // restrict.
22468 if (ReductionType.hasQualifiers()) {
22469 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
22470 return QualType();
22471 }
22472
22473 if (ReductionType->isFunctionType()) {
22474 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
22475 return QualType();
22476 }
22477 if (ReductionType->isReferenceType()) {
22478 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
22479 return QualType();
22480 }
22481 if (ReductionType->isArrayType()) {
22482 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
22483 return QualType();
22484 }
22485 return ReductionType;
22486}
22487
22490 Scope *S, DeclContext *DC, DeclarationName Name,
22491 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
22492 AccessSpecifier AS, Decl *PrevDeclInScope) {
22494 Decls.reserve(ReductionTypes.size());
22495
22496 LookupResult Lookup(SemaRef, Name, SourceLocation(),
22498 SemaRef.forRedeclarationInCurContext());
22499 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
22500 // A reduction-identifier may not be re-declared in the current scope for the
22501 // same type or for a type that is compatible according to the base language
22502 // rules.
22503 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22504 OMPDeclareReductionDecl *PrevDRD = nullptr;
22505 bool InCompoundScope = true;
22506 if (S != nullptr) {
22507 // Find previous declaration with the same name not referenced in other
22508 // declarations.
22509 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
22510 InCompoundScope =
22511 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22512 SemaRef.LookupName(Lookup, S);
22513 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22514 /*AllowInlineNamespace=*/false);
22515 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
22516 LookupResult::Filter Filter = Lookup.makeFilter();
22517 while (Filter.hasNext()) {
22518 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
22519 if (InCompoundScope) {
22520 UsedAsPrevious.try_emplace(PrevDecl, false);
22521 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
22522 UsedAsPrevious[D] = true;
22523 }
22524 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22525 PrevDecl->getLocation();
22526 }
22527 Filter.done();
22528 if (InCompoundScope) {
22529 for (const auto &PrevData : UsedAsPrevious) {
22530 if (!PrevData.second) {
22531 PrevDRD = PrevData.first;
22532 break;
22533 }
22534 }
22535 }
22536 } else if (PrevDeclInScope != nullptr) {
22537 auto *PrevDRDInScope = PrevDRD =
22538 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
22539 do {
22540 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
22541 PrevDRDInScope->getLocation();
22542 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
22543 } while (PrevDRDInScope != nullptr);
22544 }
22545 for (const auto &TyData : ReductionTypes) {
22546 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
22547 bool Invalid = false;
22548 if (I != PreviousRedeclTypes.end()) {
22549 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
22550 << TyData.first;
22551 Diag(I->second, diag::note_previous_definition);
22552 Invalid = true;
22553 }
22554 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
22556 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
22557 DC->addDecl(DRD);
22558 DRD->setAccess(AS);
22559 Decls.push_back(DRD);
22560 if (Invalid)
22561 DRD->setInvalidDecl();
22562 else
22563 PrevDRD = DRD;
22564 }
22565
22566 return DeclGroupPtrTy::make(
22567 DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size()));
22568}
22569
22571 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22572
22573 // Enter new function scope.
22574 SemaRef.PushFunctionScope();
22575 SemaRef.setFunctionHasBranchProtectedScope();
22576 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
22577
22578 if (S != nullptr)
22579 SemaRef.PushDeclContext(S, DRD);
22580 else
22581 SemaRef.CurContext = DRD;
22582
22583 SemaRef.PushExpressionEvaluationContext(
22585
22586 QualType ReductionType = DRD->getType();
22587 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
22588 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
22589 // uses semantics of argument handles by value, but it should be passed by
22590 // reference. C lang does not support references, so pass all parameters as
22591 // pointers.
22592 // Create 'T omp_in;' variable.
22593 VarDecl *OmpInParm =
22594 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in");
22595 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
22596 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
22597 // uses semantics of argument handles by value, but it should be passed by
22598 // reference. C lang does not support references, so pass all parameters as
22599 // pointers.
22600 // Create 'T omp_out;' variable.
22601 VarDecl *OmpOutParm =
22602 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out");
22603 if (S != nullptr) {
22604 SemaRef.PushOnScopeChains(OmpInParm, S);
22605 SemaRef.PushOnScopeChains(OmpOutParm, S);
22606 } else {
22607 DRD->addDecl(OmpInParm);
22608 DRD->addDecl(OmpOutParm);
22609 }
22610 Expr *InE =
22611 ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation());
22612 Expr *OutE =
22613 ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation());
22614 DRD->setCombinerData(InE, OutE);
22615}
22616
22618 Expr *Combiner) {
22619 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22620 SemaRef.DiscardCleanupsInEvaluationContext();
22621 SemaRef.PopExpressionEvaluationContext();
22622
22623 SemaRef.PopDeclContext();
22624 SemaRef.PopFunctionScopeInfo();
22625
22626 if (Combiner != nullptr)
22627 DRD->setCombiner(Combiner);
22628 else
22629 DRD->setInvalidDecl();
22630}
22631
22633 Decl *D) {
22634 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22635
22636 // Enter new function scope.
22637 SemaRef.PushFunctionScope();
22638 SemaRef.setFunctionHasBranchProtectedScope();
22639
22640 if (S != nullptr)
22641 SemaRef.PushDeclContext(S, DRD);
22642 else
22643 SemaRef.CurContext = DRD;
22644
22645 SemaRef.PushExpressionEvaluationContext(
22647
22648 QualType ReductionType = DRD->getType();
22649 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
22650 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
22651 // uses semantics of argument handles by value, but it should be passed by
22652 // reference. C lang does not support references, so pass all parameters as
22653 // pointers.
22654 // Create 'T omp_priv;' variable.
22655 VarDecl *OmpPrivParm =
22656 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv");
22657 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
22658 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
22659 // uses semantics of argument handles by value, but it should be passed by
22660 // reference. C lang does not support references, so pass all parameters as
22661 // pointers.
22662 // Create 'T omp_orig;' variable.
22663 VarDecl *OmpOrigParm =
22664 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig");
22665 if (S != nullptr) {
22666 SemaRef.PushOnScopeChains(OmpPrivParm, S);
22667 SemaRef.PushOnScopeChains(OmpOrigParm, S);
22668 } else {
22669 DRD->addDecl(OmpPrivParm);
22670 DRD->addDecl(OmpOrigParm);
22671 }
22672 Expr *OrigE =
22673 ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation());
22674 Expr *PrivE =
22675 ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation());
22676 DRD->setInitializerData(OrigE, PrivE);
22677 return OmpPrivParm;
22678}
22679
22681 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
22682 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22683 SemaRef.DiscardCleanupsInEvaluationContext();
22684 SemaRef.PopExpressionEvaluationContext();
22685
22686 SemaRef.PopDeclContext();
22687 SemaRef.PopFunctionScopeInfo();
22688
22689 if (Initializer != nullptr) {
22690 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
22691 } else if (OmpPrivParm->hasInit()) {
22692 DRD->setInitializer(OmpPrivParm->getInit(),
22693 OmpPrivParm->isDirectInit()
22696 } else {
22697 DRD->setInvalidDecl();
22698 }
22699}
22700
22702 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
22703 for (Decl *D : DeclReductions.get()) {
22704 if (IsValid) {
22705 if (S)
22706 SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
22707 /*AddToContext=*/false);
22708 } else {
22709 D->setInvalidDecl();
22710 }
22711 }
22712 return DeclReductions;
22713}
22714
22716 Declarator &D) {
22717 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
22718 QualType T = TInfo->getType();
22719 if (D.isInvalidType())
22720 return true;
22721
22722 if (getLangOpts().CPlusPlus) {
22723 // Check that there are no default arguments (C++ only).
22724 SemaRef.CheckExtraCXXDefaultArguments(D);
22725 }
22726
22727 return SemaRef.CreateParsedType(T, TInfo);
22728}
22729
22732 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
22733
22734 QualType MapperType = SemaRef.GetTypeFromParser(ParsedType.get());
22735 assert(!MapperType.isNull() && "Expect valid mapper type");
22736
22737 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22738 // The type must be of struct, union or class type in C and C++
22739 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
22740 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
22741 return QualType();
22742 }
22743 return MapperType;
22744}
22745
22747 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
22749 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
22750 LookupResult Lookup(SemaRef, Name, SourceLocation(),
22752 SemaRef.forRedeclarationInCurContext());
22753 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22754 // A mapper-identifier may not be redeclared in the current scope for the
22755 // same type or for a type that is compatible according to the base language
22756 // rules.
22757 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22758 OMPDeclareMapperDecl *PrevDMD = nullptr;
22759 bool InCompoundScope = true;
22760 if (S != nullptr) {
22761 // Find previous declaration with the same name not referenced in other
22762 // declarations.
22763 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
22764 InCompoundScope =
22765 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22766 SemaRef.LookupName(Lookup, S);
22767 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22768 /*AllowInlineNamespace=*/false);
22769 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
22770 LookupResult::Filter Filter = Lookup.makeFilter();
22771 while (Filter.hasNext()) {
22772 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
22773 if (InCompoundScope) {
22774 UsedAsPrevious.try_emplace(PrevDecl, false);
22775 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
22776 UsedAsPrevious[D] = true;
22777 }
22778 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22779 PrevDecl->getLocation();
22780 }
22781 Filter.done();
22782 if (InCompoundScope) {
22783 for (const auto &PrevData : UsedAsPrevious) {
22784 if (!PrevData.second) {
22785 PrevDMD = PrevData.first;
22786 break;
22787 }
22788 }
22789 }
22790 } else if (PrevDeclInScope) {
22791 auto *PrevDMDInScope = PrevDMD =
22792 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
22793 do {
22794 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
22795 PrevDMDInScope->getLocation();
22796 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
22797 } while (PrevDMDInScope != nullptr);
22798 }
22799 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
22800 bool Invalid = false;
22801 if (I != PreviousRedeclTypes.end()) {
22802 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
22803 << MapperType << Name;
22804 Diag(I->second, diag::note_previous_definition);
22805 Invalid = true;
22806 }
22807 // Build expressions for implicit maps of data members with 'default'
22808 // mappers.
22809 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
22810 if (getLangOpts().OpenMP >= 50)
22812 ClausesWithImplicit);
22813 auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name,
22814 MapperType, VN, ClausesWithImplicit,
22815 PrevDMD);
22816 if (S)
22817 SemaRef.PushOnScopeChains(DMD, S);
22818 else
22819 DC->addDecl(DMD);
22820 DMD->setAccess(AS);
22821 if (Invalid)
22822 DMD->setInvalidDecl();
22823
22824 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22825 VD->setDeclContext(DMD);
22826 VD->setLexicalDeclContext(DMD);
22827 DMD->addDecl(VD);
22828 DMD->setMapperVarRef(MapperVarRef);
22829
22831}
22832
22834 Scope *S, QualType MapperType, SourceLocation StartLoc,
22835 DeclarationName VN) {
22836 TypeSourceInfo *TInfo =
22837 getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc);
22838 auto *VD = VarDecl::Create(
22839 getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc,
22840 StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None);
22841 if (S)
22842 SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false);
22843 Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc);
22844 DSAStack->addDeclareMapperVarRef(E);
22845 return E;
22846}
22847
22849 bool IsGlobalVar =
22851 if (DSAStack->getDeclareMapperVarRef()) {
22852 if (IsGlobalVar)
22853 SemaRef.Consumer.HandleTopLevelDecl(DeclGroupRef(VD));
22854 DSAStack->addIteratorVarDecl(VD);
22855 } else {
22856 // Currently, only declare mapper handles global-scope iterator vars.
22857 assert(!IsGlobalVar && "Only declare mapper handles TU-scope iterators.");
22858 }
22859}
22860
22862 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
22863 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
22864 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
22865 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
22866 return true;
22868 return true;
22869 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
22870 return true;
22871 return false;
22872 }
22873 return true;
22874}
22875
22877 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
22878 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
22879}
22880
22882 SourceLocation StartLoc,
22883 SourceLocation LParenLoc,
22884 SourceLocation EndLoc) {
22885 if (VarList.empty())
22886 return nullptr;
22887
22888 for (Expr *ValExpr : VarList) {
22889 // OpenMP [teams Constrcut, Restrictions]
22890 // The num_teams expression must evaluate to a positive integer value.
22891 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams,
22892 /*StrictlyPositive=*/true))
22893 return nullptr;
22894 }
22895
22896 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22898 DKind, OMPC_num_teams, getLangOpts().OpenMP);
22899 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
22900 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
22901 LParenLoc, EndLoc, VarList,
22902 /*PreInit=*/nullptr);
22903
22904 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22906 for (Expr *ValExpr : VarList) {
22907 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22908 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22909 Vars.push_back(ValExpr);
22910 }
22911
22912 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
22913 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
22914 LParenLoc, EndLoc, Vars, PreInit);
22915}
22916
22918 SourceLocation StartLoc,
22919 SourceLocation LParenLoc,
22920 SourceLocation EndLoc) {
22921 if (VarList.empty())
22922 return nullptr;
22923
22924 for (Expr *ValExpr : VarList) {
22925 // OpenMP [teams Constrcut, Restrictions]
22926 // The thread_limit expression must evaluate to a positive integer value.
22927 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit,
22928 /*StrictlyPositive=*/true))
22929 return nullptr;
22930 }
22931
22932 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22934 DKind, OMPC_thread_limit, getLangOpts().OpenMP);
22935 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
22936 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion,
22937 StartLoc, LParenLoc, EndLoc, VarList,
22938 /*PreInit=*/nullptr);
22939
22940 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22942 for (Expr *ValExpr : VarList) {
22943 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22944 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22945 Vars.push_back(ValExpr);
22946 }
22947
22948 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
22949 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion, StartLoc,
22950 LParenLoc, EndLoc, Vars, PreInit);
22951}
22952
22954 SourceLocation StartLoc,
22955 SourceLocation LParenLoc,
22956 SourceLocation EndLoc) {
22957 Expr *ValExpr = Priority;
22958 Stmt *HelperValStmt = nullptr;
22959 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22960
22961 // OpenMP [2.9.1, task Constrcut]
22962 // The priority-value is a non-negative numerical scalar expression.
22964 ValExpr, SemaRef, OMPC_priority,
22965 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
22966 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22967 return nullptr;
22968
22969 return new (getASTContext()) OMPPriorityClause(
22970 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22971}
22972
22974 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
22975 SourceLocation StartLoc, SourceLocation LParenLoc,
22976 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22977 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
22978 "Unexpected grainsize modifier in OpenMP < 51.");
22979
22980 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
22981 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
22983 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22984 << Values << getOpenMPClauseNameForDiag(OMPC_grainsize);
22985 return nullptr;
22986 }
22987
22988 Expr *ValExpr = Grainsize;
22989 Stmt *HelperValStmt = nullptr;
22990 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22991
22992 // OpenMP [2.9.2, taskloop Constrcut]
22993 // The parameter of the grainsize clause must be a positive integer
22994 // expression.
22995 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize,
22996 /*StrictlyPositive=*/true,
22997 /*BuildCapture=*/true,
22998 DSAStack->getCurrentDirective(),
22999 &CaptureRegion, &HelperValStmt))
23000 return nullptr;
23001
23002 return new (getASTContext())
23003 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
23004 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23005}
23006
23008 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
23009 SourceLocation StartLoc, SourceLocation LParenLoc,
23010 SourceLocation ModifierLoc, SourceLocation EndLoc) {
23011 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
23012 "Unexpected num_tasks modifier in OpenMP < 51.");
23013
23014 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
23015 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
23017 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23018 << Values << getOpenMPClauseNameForDiag(OMPC_num_tasks);
23019 return nullptr;
23020 }
23021
23022 Expr *ValExpr = NumTasks;
23023 Stmt *HelperValStmt = nullptr;
23024 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23025
23026 // OpenMP [2.9.2, taskloop Constrcut]
23027 // The parameter of the num_tasks clause must be a positive integer
23028 // expression.
23030 ValExpr, SemaRef, OMPC_num_tasks,
23031 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
23032 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23033 return nullptr;
23034
23035 return new (getASTContext())
23036 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
23037 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23038}
23039
23041 SourceLocation StartLoc,
23042 SourceLocation LParenLoc,
23043 SourceLocation EndLoc) {
23044 // OpenMP [2.13.2, critical construct, Description]
23045 // ... where hint-expression is an integer constant expression that evaluates
23046 // to a valid lock hint.
23047 ExprResult HintExpr =
23048 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
23049 if (HintExpr.isInvalid())
23050 return nullptr;
23051 return new (getASTContext())
23052 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
23053}
23054
23055/// Tries to find omp_event_handle_t type.
23057 DSAStackTy *Stack) {
23058 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
23059 if (!OMPEventHandleT.isNull())
23060 return true;
23061 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
23062 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
23063 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23064 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
23065 return false;
23066 }
23067 Stack->setOMPEventHandleT(PT.get());
23068 return true;
23069}
23070
23072 SourceLocation StartLoc,
23073 SourceLocation LParenLoc,
23074 SourceLocation EndLoc) {
23075 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
23076 !Evt->isInstantiationDependent() &&
23079 return nullptr;
23080 // OpenMP 5.0, 2.10.1 task Construct.
23081 // event-handle is a variable of the omp_event_handle_t type.
23082 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
23083 if (!Ref) {
23084 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23085 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
23086 return nullptr;
23087 }
23088 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
23089 if (!VD) {
23090 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23091 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
23092 return nullptr;
23093 }
23094 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
23095 VD->getType()) ||
23096 VD->getType().isConstant(getASTContext())) {
23097 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23098 << "omp_event_handle_t" << 1 << VD->getType()
23099 << Evt->getSourceRange();
23100 return nullptr;
23101 }
23102 // OpenMP 5.0, 2.10.1 task Construct
23103 // [detach clause]... The event-handle will be considered as if it was
23104 // specified on a firstprivate clause.
23105 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
23106 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
23107 DVar.RefExpr) {
23108 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
23109 << getOpenMPClauseNameForDiag(DVar.CKind)
23110 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
23112 return nullptr;
23113 }
23114 }
23115
23116 return new (getASTContext())
23117 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
23118}
23119
23121 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
23122 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
23123 SourceLocation EndLoc) {
23124 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
23125 std::string Values;
23126 Values += "'";
23127 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
23128 Values += "'";
23129 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23130 << Values << getOpenMPClauseNameForDiag(OMPC_dist_schedule);
23131 return nullptr;
23132 }
23133 Expr *ValExpr = ChunkSize;
23134 Stmt *HelperValStmt = nullptr;
23135 if (ChunkSize) {
23136 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
23137 !ChunkSize->isInstantiationDependent() &&
23138 !ChunkSize->containsUnexpandedParameterPack()) {
23139 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
23140 ExprResult Val =
23141 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
23142 if (Val.isInvalid())
23143 return nullptr;
23144
23145 ValExpr = Val.get();
23146
23147 // OpenMP [2.7.1, Restrictions]
23148 // chunk_size must be a loop invariant integer expression with a positive
23149 // value.
23150 if (std::optional<llvm::APSInt> Result =
23152 if (Result->isSigned() && !Result->isStrictlyPositive()) {
23153 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
23154 << "dist_schedule" << /*strictly positive*/ 1
23155 << ChunkSize->getSourceRange();
23156 return nullptr;
23157 }
23159 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
23160 getLangOpts().OpenMP) != OMPD_unknown &&
23161 !SemaRef.CurContext->isDependentContext()) {
23162 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23163 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23164 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23165 HelperValStmt = buildPreInits(getASTContext(), Captures);
23166 }
23167 }
23168 }
23169
23170 return new (getASTContext())
23171 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
23172 Kind, ValExpr, HelperValStmt);
23173}
23174
23177 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
23178 SourceLocation KindLoc, SourceLocation EndLoc) {
23179 if (getLangOpts().OpenMP < 50) {
23180 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
23181 Kind != OMPC_DEFAULTMAP_scalar) {
23182 std::string Value;
23183 SourceLocation Loc;
23184 Value += "'";
23185 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
23186 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
23187 OMPC_DEFAULTMAP_MODIFIER_tofrom);
23188 Loc = MLoc;
23189 } else {
23190 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
23191 OMPC_DEFAULTMAP_scalar);
23192 Loc = KindLoc;
23193 }
23194 Value += "'";
23195 Diag(Loc, diag::err_omp_unexpected_clause_value)
23196 << Value << getOpenMPClauseNameForDiag(OMPC_defaultmap);
23197 return nullptr;
23198 }
23199 } else {
23200 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
23201 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
23202 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
23203 if (!isDefaultmapKind || !isDefaultmapModifier) {
23204 StringRef KindValue = getLangOpts().OpenMP < 52
23205 ? "'scalar', 'aggregate', 'pointer'"
23206 : "'scalar', 'aggregate', 'pointer', 'all'";
23207 if (getLangOpts().OpenMP == 50) {
23208 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
23209 "'firstprivate', 'none', 'default'";
23210 if (!isDefaultmapKind && isDefaultmapModifier) {
23211 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23212 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
23213 } else if (isDefaultmapKind && !isDefaultmapModifier) {
23214 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23215 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
23216 } else {
23217 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23218 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
23219 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23220 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
23221 }
23222 } else {
23223 StringRef ModifierValue =
23224 getLangOpts().OpenMP < 60
23225 ? "'alloc', 'from', 'to', 'tofrom', "
23226 "'firstprivate', 'none', 'default', 'present'"
23227 : "'storage', 'from', 'to', 'tofrom', "
23228 "'firstprivate', 'private', 'none', 'default', 'present'";
23229 if (!isDefaultmapKind && isDefaultmapModifier) {
23230 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23231 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
23232 } else if (isDefaultmapKind && !isDefaultmapModifier) {
23233 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23234 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
23235 } else {
23236 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23237 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
23238 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23239 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
23240 }
23241 }
23242 return nullptr;
23243 }
23244
23245 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
23246 // At most one defaultmap clause for each category can appear on the
23247 // directive.
23248 if (DSAStack->checkDefaultmapCategory(Kind)) {
23249 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
23250 return nullptr;
23251 }
23252 }
23253 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
23254 // Variable category is not specified - mark all categories.
23255 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
23256 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
23257 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
23258 } else {
23259 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
23260 }
23261
23262 return new (getASTContext())
23263 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
23264}
23265
23268 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
23269 if (!CurLexicalContext->isFileContext() &&
23270 !CurLexicalContext->isExternCContext() &&
23271 !CurLexicalContext->isExternCXXContext() &&
23272 !isa<CXXRecordDecl>(CurLexicalContext) &&
23273 !isa<ClassTemplateDecl>(CurLexicalContext) &&
23274 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
23275 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
23276 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
23277 return false;
23278 }
23279
23280 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23281 if (getLangOpts().HIP)
23282 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
23283
23284 DeclareTargetNesting.push_back(DTCI);
23285 return true;
23286}
23287
23290 assert(!DeclareTargetNesting.empty() &&
23291 "check isInOpenMPDeclareTargetContext() first!");
23292 return DeclareTargetNesting.pop_back_val();
23293}
23294
23297 for (auto &It : DTCI.ExplicitlyMapped)
23298 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
23299}
23300
23302 if (DeclareTargetNesting.empty())
23303 return;
23304 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23305 unsigned OMPVersion = getLangOpts().OpenMP;
23306 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
23307 << getOpenMPDirectiveName(DTCI.Kind, OMPVersion);
23308}
23309
23311 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
23313 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
23314 /*ObjectType=*/QualType(),
23315 /*AllowBuiltinCreation=*/true);
23316
23317 if (Lookup.isAmbiguous())
23318 return nullptr;
23319 Lookup.suppressDiagnostics();
23320
23321 if (!Lookup.isSingleResult()) {
23322 VarOrFuncDeclFilterCCC CCC(SemaRef);
23323 if (TypoCorrection Corrected =
23324 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
23326 SemaRef.diagnoseTypo(Corrected,
23327 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
23328 << Id.getName());
23329 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
23330 return nullptr;
23331 }
23332
23333 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
23334 return nullptr;
23335 }
23336
23337 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
23338 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
23340 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
23341 return nullptr;
23342 }
23343 return ND;
23344}
23345
23347 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
23349 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
23351 "Expected variable, function or function template.");
23352
23353 if (auto *VD = dyn_cast<VarDecl>(ND)) {
23354 // Only global variables can be marked as declare target.
23355 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23356 !VD->isStaticDataMember()) {
23357 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
23358 << VD->getNameAsString();
23359 return;
23360 }
23361 }
23362 // Diagnose marking after use as it may lead to incorrect diagnosis and
23363 // codegen.
23364 if (getLangOpts().OpenMP >= 50 &&
23365 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
23366 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
23367
23368 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23369 if (getLangOpts().HIP)
23370 Diag(Loc, diag::warn_hip_omp_target_directives);
23371
23372 // Explicit declare target lists have precedence.
23373 const unsigned Level = -1;
23374
23375 auto *VD = cast<ValueDecl>(ND);
23376 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23377 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23378 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
23379 (*ActiveAttr)->getLevel() == Level) {
23380 Diag(Loc, diag::err_omp_device_type_mismatch)
23381 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
23382 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
23383 (*ActiveAttr)->getDevType());
23384 return;
23385 }
23386 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
23387 (*ActiveAttr)->getLevel() == Level) {
23388 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
23389 return;
23390 }
23391
23392 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
23393 return;
23394
23395 Expr *IndirectE = nullptr;
23396 bool IsIndirect = false;
23397 if (DTCI.Indirect) {
23398 IndirectE = *DTCI.Indirect;
23399 if (!IndirectE)
23400 IsIndirect = true;
23401 }
23402 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23403 getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level,
23404 SourceRange(Loc, Loc));
23405 ND->addAttr(A);
23406 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
23407 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
23408 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
23409 if (auto *VD = dyn_cast<VarDecl>(ND);
23410 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
23411 VD->hasGlobalStorage())
23413}
23414
23416 Sema &SemaRef, Decl *D) {
23417 if (!D || !isa<VarDecl>(D))
23418 return;
23419 auto *VD = cast<VarDecl>(D);
23420 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
23421 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
23422 if (SemaRef.LangOpts.OpenMP >= 50 &&
23423 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
23424 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
23425 VD->hasGlobalStorage()) {
23426 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
23427 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
23428 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
23429 // If a lambda declaration and definition appears between a
23430 // declare target directive and the matching end declare target
23431 // directive, all variables that are captured by the lambda
23432 // expression must also appear in a to clause.
23433 SemaRef.Diag(VD->getLocation(),
23434 diag::err_omp_lambda_capture_in_declare_target_not_to);
23435 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
23436 << VD << 0 << SR;
23437 return;
23438 }
23439 }
23440 if (MapTy)
23441 return;
23442 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
23443 SemaRef.Diag(SL, diag::note_used_here) << SR;
23444}
23445
23447 Sema &SemaRef, DSAStackTy *Stack,
23448 ValueDecl *VD) {
23449 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
23450 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
23451 /*FullCheck=*/false);
23452}
23453
23455 SourceLocation IdLoc) {
23456 if (!D || D->isInvalidDecl())
23457 return;
23458 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
23459 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
23460 if (auto *VD = dyn_cast<VarDecl>(D)) {
23461 // Only global variables can be marked as declare target.
23462 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23463 !VD->isStaticDataMember())
23464 return;
23465 // 2.10.6: threadprivate variable cannot appear in a declare target
23466 // directive.
23467 if (DSAStack->isThreadPrivate(VD)) {
23468 Diag(SL, diag::err_omp_threadprivate_in_target);
23469 reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false));
23470 return;
23471 }
23472 }
23473 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
23474 D = FTD->getTemplatedDecl();
23475 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
23476 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
23477 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
23478 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
23479 Diag(IdLoc, diag::err_omp_function_in_link_clause);
23480 Diag(FD->getLocation(), diag::note_defined_here) << FD;
23481 return;
23482 }
23483 }
23484 if (auto *VD = dyn_cast<ValueDecl>(D)) {
23485 // Problem if any with var declared with incomplete type will be reported
23486 // as normal, so no need to check it here.
23487 if ((E || !VD->getType()->isIncompleteType()) &&
23489 return;
23490 if (!E && isInOpenMPDeclareTargetContext()) {
23491 // Checking declaration inside declare target region.
23492 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
23494 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23495 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23496 unsigned Level = DeclareTargetNesting.size();
23497 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
23498 return;
23499 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23500 Expr *IndirectE = nullptr;
23501 bool IsIndirect = false;
23502 if (DTCI.Indirect) {
23503 IndirectE = *DTCI.Indirect;
23504 if (!IndirectE)
23505 IsIndirect = true;
23506 }
23507 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23508 getASTContext(),
23509 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
23510 : OMPDeclareTargetDeclAttr::MT_To,
23511 DTCI.DT, IndirectE, IsIndirect, Level,
23512 SourceRange(DTCI.Loc, DTCI.Loc));
23513 D->addAttr(A);
23514 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
23515 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
23516 }
23517 return;
23518 }
23519 }
23520 if (!E)
23521 return;
23523}
23524
23525/// This class visits every VarDecl that the initializer references and adds
23526/// OMPDeclareTargetDeclAttr to each of them.
23527class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
23528 SmallVector<VarDecl *> DeclVector;
23529 Attr *A;
23530
23531public:
23532 /// A StmtVisitor class function that visits all DeclRefExpr and adds
23533 /// OMPDeclareTargetDeclAttr to them.
23535 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
23536 VD->addAttr(A);
23537 DeclVector.push_back(VD);
23538 }
23539 }
23540 /// A function that iterates across each of the Expr's children.
23541 void VisitExpr(Expr *Ex) {
23542 for (auto *Child : Ex->children()) {
23543 Visit(Child);
23544 }
23545 }
23546 /// A function that keeps a record of all the Decls that are variables, has
23547 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
23548 /// each Decl one at a time and use the inherited 'visit' functions to look
23549 /// for DeclRefExpr.
23551 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
23552 DeclVector.push_back(cast<VarDecl>(TD));
23553 llvm::SmallDenseSet<Decl *> Visited;
23554 while (!DeclVector.empty()) {
23555 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
23556 if (!Visited.insert(TargetVarDecl).second)
23557 continue;
23558
23559 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
23560 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
23561 if (Expr *Ex = TargetVarDecl->getInit())
23562 Visit(Ex);
23563 }
23564 }
23565 }
23566};
23567
23568/// Adding OMPDeclareTargetDeclAttr to variables with static storage
23569/// duration that are referenced in the initializer expression list of
23570/// variables with static storage duration in declare target directive.
23572 GlobalDeclRefChecker Checker;
23573 if (isa<VarDecl>(TargetDecl))
23574 Checker.declareTargetInitializer(TargetDecl);
23575}
23576
23578 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23579 ArrayRef<SourceLocation> MotionModifiersLoc,
23580 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23581 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23582 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23586
23587 // Process motion-modifiers, flag errors for duplicate modifiers.
23588 unsigned Count = 0;
23589 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23590 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23591 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23592 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23593 continue;
23594 }
23595 assert(Count < NumberOfOMPMotionModifiers &&
23596 "Modifiers exceed the allowed number of motion modifiers");
23597 Modifiers[Count] = MotionModifiers[I];
23598 ModifiersLoc[Count] = MotionModifiersLoc[I];
23599 ++Count;
23600 }
23601
23602 MappableVarListInfo MVLI(VarList);
23604 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23605 if (MVLI.ProcessedVarList.empty())
23606 return nullptr;
23607
23608 return OMPToClause::Create(
23609 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23610 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23611 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
23612}
23613
23615 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23616 ArrayRef<SourceLocation> MotionModifiersLoc,
23617 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23618 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23619 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23623
23624 // Process motion-modifiers, flag errors for duplicate modifiers.
23625 unsigned Count = 0;
23626 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23627 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23628 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23629 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23630 continue;
23631 }
23632 assert(Count < NumberOfOMPMotionModifiers &&
23633 "Modifiers exceed the allowed number of motion modifiers");
23634 Modifiers[Count] = MotionModifiers[I];
23635 ModifiersLoc[Count] = MotionModifiersLoc[I];
23636 ++Count;
23637 }
23638
23639 MappableVarListInfo MVLI(VarList);
23640 checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
23641 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23642 if (MVLI.ProcessedVarList.empty())
23643 return nullptr;
23644
23645 return OMPFromClause::Create(
23646 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23647 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23648 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
23649}
23650
23651OMPClause *
23653 const OMPVarListLocTy &Locs) {
23654 MappableVarListInfo MVLI(VarList);
23655 SmallVector<Expr *, 8> PrivateCopies;
23657
23658 for (Expr *RefExpr : VarList) {
23659 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
23660 SourceLocation ELoc;
23661 SourceRange ERange;
23662 Expr *SimpleRefExpr = RefExpr;
23663 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23664 if (Res.second) {
23665 // It will be analyzed later.
23666 MVLI.ProcessedVarList.push_back(RefExpr);
23667 PrivateCopies.push_back(nullptr);
23668 Inits.push_back(nullptr);
23669 }
23670 ValueDecl *D = Res.first;
23671 if (!D)
23672 continue;
23673
23674 QualType Type = D->getType();
23675 Type = Type.getNonReferenceType().getUnqualifiedType();
23676
23677 auto *VD = dyn_cast<VarDecl>(D);
23678
23679 // Item should be a pointer or reference to pointer.
23680 if (!Type->isPointerType()) {
23681 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
23682 << 0 << RefExpr->getSourceRange();
23683 continue;
23684 }
23685
23686 // Build the private variable and the expression that refers to it.
23687 auto VDPrivate =
23688 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
23689 D->hasAttrs() ? &D->getAttrs() : nullptr,
23690 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
23691 if (VDPrivate->isInvalidDecl())
23692 continue;
23693
23694 SemaRef.CurContext->addDecl(VDPrivate);
23695 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
23696 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
23697
23698 // Add temporary variable to initialize the private copy of the pointer.
23699 VarDecl *VDInit =
23700 buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp");
23701 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
23702 SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
23703 SemaRef.AddInitializerToDecl(
23704 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
23705 /*DirectInit=*/false);
23706
23707 // If required, build a capture to implement the privatization initialized
23708 // with the current list item value.
23709 DeclRefExpr *Ref = nullptr;
23710 if (!VD)
23711 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
23712 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23713 PrivateCopies.push_back(VDPrivateRefExpr);
23714 Inits.push_back(VDInitRefExpr);
23715
23716 // We need to add a data sharing attribute for this variable to make sure it
23717 // is correctly captured. A variable that shows up in a use_device_ptr has
23718 // similar properties of a first private variable.
23719 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23720
23721 // Create a mappable component for the list item. List items in this clause
23722 // only need a component.
23723 MVLI.VarBaseDeclarations.push_back(D);
23724 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23725 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
23726 /*IsNonContiguous=*/false);
23727 }
23728
23729 if (MVLI.ProcessedVarList.empty())
23730 return nullptr;
23731
23733 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
23734 MVLI.VarBaseDeclarations, MVLI.VarComponents);
23735}
23736
23737OMPClause *
23739 const OMPVarListLocTy &Locs) {
23740 MappableVarListInfo MVLI(VarList);
23741
23742 for (Expr *RefExpr : VarList) {
23743 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
23744 SourceLocation ELoc;
23745 SourceRange ERange;
23746 Expr *SimpleRefExpr = RefExpr;
23747 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23748 /*AllowArraySection=*/true,
23749 /*AllowAssumedSizeArray=*/true);
23750 if (Res.second) {
23751 // It will be analyzed later.
23752 MVLI.ProcessedVarList.push_back(RefExpr);
23753 }
23754 ValueDecl *D = Res.first;
23755 if (!D)
23756 continue;
23757 auto *VD = dyn_cast<VarDecl>(D);
23758
23759 // If required, build a capture to implement the privatization initialized
23760 // with the current list item value.
23761 DeclRefExpr *Ref = nullptr;
23762 if (!VD)
23763 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
23764 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23765
23766 // We need to add a data sharing attribute for this variable to make sure it
23767 // is correctly captured. A variable that shows up in a use_device_addr has
23768 // similar properties of a first private variable.
23769 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23770
23771 // Create a mappable component for the list item. List items in this clause
23772 // only need a component.
23773 MVLI.VarBaseDeclarations.push_back(D);
23774 MVLI.VarComponents.emplace_back();
23775 Expr *Component = SimpleRefExpr;
23776 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23777 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23778 Component =
23779 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
23780 MVLI.VarComponents.back().emplace_back(Component, D,
23781 /*IsNonContiguous=*/false);
23782 }
23783
23784 if (MVLI.ProcessedVarList.empty())
23785 return nullptr;
23786
23788 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23789 MVLI.VarComponents);
23790}
23791
23792OMPClause *
23794 const OMPVarListLocTy &Locs) {
23795 MappableVarListInfo MVLI(VarList);
23796 for (Expr *RefExpr : VarList) {
23797 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
23798 SourceLocation ELoc;
23799 SourceRange ERange;
23800 Expr *SimpleRefExpr = RefExpr;
23801 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23802 if (Res.second) {
23803 // It will be analyzed later.
23804 MVLI.ProcessedVarList.push_back(RefExpr);
23805 }
23806 ValueDecl *D = Res.first;
23807 if (!D)
23808 continue;
23809
23810 QualType Type = D->getType();
23811 // item should be a pointer or array or reference to pointer or array
23812 if (!Type.getNonReferenceType()->isPointerType() &&
23813 !Type.getNonReferenceType()->isArrayType()) {
23814 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
23815 << 0 << RefExpr->getSourceRange();
23816 continue;
23817 }
23818
23819 // Check if the declaration in the clause does not show up in any data
23820 // sharing attribute.
23821 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23822 if (isOpenMPPrivate(DVar.CKind)) {
23823 unsigned OMPVersion = getLangOpts().OpenMP;
23824 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23825 << getOpenMPClauseNameForDiag(DVar.CKind)
23826 << getOpenMPClauseNameForDiag(OMPC_is_device_ptr)
23827 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
23828 OMPVersion);
23830 continue;
23831 }
23832
23833 const Expr *ConflictExpr;
23834 if (DSAStack->checkMappableExprComponentListsForDecl(
23835 D, /*CurrentRegionOnly=*/true,
23836 [&ConflictExpr](
23838 OpenMPClauseKind) -> bool {
23839 ConflictExpr = R.front().getAssociatedExpression();
23840 return true;
23841 })) {
23842 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23843 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23844 << ConflictExpr->getSourceRange();
23845 continue;
23846 }
23847
23848 // Store the components in the stack so that they can be used to check
23849 // against other clauses later on.
23851 SimpleRefExpr, D, /*IsNonContiguous=*/false);
23852 DSAStack->addMappableExpressionComponents(
23853 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
23854
23855 // Record the expression we've just processed.
23856 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
23857
23858 // Create a mappable component for the list item. List items in this clause
23859 // only need a component. We use a null declaration to signal fields in
23860 // 'this'.
23861 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23862 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23863 "Unexpected device pointer expression!");
23864 MVLI.VarBaseDeclarations.push_back(
23865 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23866 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23867 MVLI.VarComponents.back().push_back(MC);
23868 }
23869
23870 if (MVLI.ProcessedVarList.empty())
23871 return nullptr;
23872
23874 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23875 MVLI.VarComponents);
23876}
23877
23878OMPClause *
23880 const OMPVarListLocTy &Locs) {
23881 MappableVarListInfo MVLI(VarList);
23882 for (Expr *RefExpr : VarList) {
23883 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
23884 SourceLocation ELoc;
23885 SourceRange ERange;
23886 Expr *SimpleRefExpr = RefExpr;
23887 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23888 /*AllowArraySection=*/true);
23889 if (Res.second) {
23890 // It will be analyzed later.
23891 MVLI.ProcessedVarList.push_back(RefExpr);
23892 }
23893 ValueDecl *D = Res.first;
23894 if (!D)
23895 continue;
23896
23897 // Check if the declaration in the clause does not show up in any data
23898 // sharing attribute.
23899 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23900 if (isOpenMPPrivate(DVar.CKind)) {
23901 unsigned OMPVersion = getLangOpts().OpenMP;
23902 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23903 << getOpenMPClauseNameForDiag(DVar.CKind)
23904 << getOpenMPClauseNameForDiag(OMPC_has_device_addr)
23905 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
23906 OMPVersion);
23908 continue;
23909 }
23910
23911 const Expr *ConflictExpr;
23912 if (DSAStack->checkMappableExprComponentListsForDecl(
23913 D, /*CurrentRegionOnly=*/true,
23914 [&ConflictExpr](
23916 OpenMPClauseKind) -> bool {
23917 ConflictExpr = R.front().getAssociatedExpression();
23918 return true;
23919 })) {
23920 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23921 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23922 << ConflictExpr->getSourceRange();
23923 continue;
23924 }
23925
23926 // Store the components in the stack so that they can be used to check
23927 // against other clauses later on.
23928 Expr *Component = SimpleRefExpr;
23929 auto *VD = dyn_cast<VarDecl>(D);
23930 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23931 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23932 Component =
23933 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
23935 Component, D, /*IsNonContiguous=*/false);
23936 DSAStack->addMappableExpressionComponents(
23937 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
23938
23939 // Record the expression we've just processed.
23940 if (!VD && !SemaRef.CurContext->isDependentContext()) {
23941 DeclRefExpr *Ref =
23942 buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
23943 assert(Ref && "has_device_addr capture failed");
23944 MVLI.ProcessedVarList.push_back(Ref);
23945 } else
23946 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
23947
23948 // Create a mappable component for the list item. List items in this clause
23949 // only need a component. We use a null declaration to signal fields in
23950 // 'this'.
23951 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23952 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23953 "Unexpected device pointer expression!");
23954 MVLI.VarBaseDeclarations.push_back(
23955 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23956 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23957 MVLI.VarComponents.back().push_back(MC);
23958 }
23959
23960 if (MVLI.ProcessedVarList.empty())
23961 return nullptr;
23962
23964 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23965 MVLI.VarComponents);
23966}
23967
23969 Expr *Allocator, Expr *Alignment,
23970 OpenMPAllocateClauseModifier FirstAllocateModifier,
23971 SourceLocation FirstAllocateModifierLoc,
23972 OpenMPAllocateClauseModifier SecondAllocateModifier,
23973 SourceLocation SecondAllocateModifierLoc, ArrayRef<Expr *> VarList,
23974 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
23975 SourceLocation EndLoc) {
23976 if (Allocator) {
23977 // Allocator expression is dependent - skip it for now and build the
23978 // allocator when instantiated.
23979 bool AllocDependent =
23980 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
23981 Allocator->isInstantiationDependent() ||
23982 Allocator->containsUnexpandedParameterPack());
23983 if (!AllocDependent) {
23984 // OpenMP [2.11.4 allocate Clause, Description]
23985 // allocator is an expression of omp_allocator_handle_t type.
23987 return nullptr;
23988
23989 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
23990 if (AllocatorRes.isInvalid())
23991 return nullptr;
23992 AllocatorRes = SemaRef.PerformImplicitConversion(
23993 AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
23995 /*AllowExplicit=*/true);
23996 if (AllocatorRes.isInvalid())
23997 return nullptr;
23998 Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr;
23999 }
24000 } else {
24001 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
24002 // allocate clauses that appear on a target construct or on constructs in a
24003 // target region must specify an allocator expression unless a requires
24004 // directive with the dynamic_allocators clause is present in the same
24005 // compilation unit.
24006 if (getLangOpts().OpenMPIsTargetDevice &&
24007 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
24008 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
24009 }
24010 if (Alignment) {
24011 bool AlignmentDependent = Alignment->isTypeDependent() ||
24012 Alignment->isValueDependent() ||
24013 Alignment->isInstantiationDependent() ||
24015 if (!AlignmentDependent) {
24016 ExprResult AlignResult =
24017 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_allocate);
24018 Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr;
24019 }
24020 }
24021 // Analyze and build list of variables.
24023 for (Expr *RefExpr : VarList) {
24024 assert(RefExpr && "NULL expr in OpenMP allocate clause.");
24025 SourceLocation ELoc;
24026 SourceRange ERange;
24027 Expr *SimpleRefExpr = RefExpr;
24028 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24029 if (Res.second) {
24030 // It will be analyzed later.
24031 Vars.push_back(RefExpr);
24032 }
24033 ValueDecl *D = Res.first;
24034 if (!D)
24035 continue;
24036
24037 auto *VD = dyn_cast<VarDecl>(D);
24038 DeclRefExpr *Ref = nullptr;
24039 if (!VD && !SemaRef.CurContext->isDependentContext())
24040 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
24041 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
24042 ? RefExpr->IgnoreParens()
24043 : Ref);
24044 }
24045
24046 if (Vars.empty())
24047 return nullptr;
24048
24049 if (Allocator)
24050 DSAStack->addInnerAllocatorExpr(Allocator);
24051
24053 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
24054 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
24055 SecondAllocateModifierLoc, EndLoc, Vars);
24056}
24057
24059 SourceLocation StartLoc,
24060 SourceLocation LParenLoc,
24061 SourceLocation EndLoc) {
24063 for (Expr *RefExpr : VarList) {
24064 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
24065 SourceLocation ELoc;
24066 SourceRange ERange;
24067 Expr *SimpleRefExpr = RefExpr;
24068 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24069 if (Res.second)
24070 // It will be analyzed later.
24071 Vars.push_back(RefExpr);
24072 ValueDecl *D = Res.first;
24073 if (!D)
24074 continue;
24075
24076 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
24077 // A list-item cannot appear in more than one nontemporal clause.
24078 if (const Expr *PrevRef =
24079 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
24080 Diag(ELoc, diag::err_omp_used_in_clause_twice)
24081 << 0 << getOpenMPClauseNameForDiag(OMPC_nontemporal) << ERange;
24082 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
24083 << getOpenMPClauseNameForDiag(OMPC_nontemporal);
24084 continue;
24085 }
24086
24087 Vars.push_back(RefExpr);
24088 }
24089
24090 if (Vars.empty())
24091 return nullptr;
24092
24093 return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc,
24094 EndLoc, Vars);
24095}
24096
24098 Stmt *AStmt,
24099 SourceLocation StartLoc,
24100 SourceLocation EndLoc) {
24101 if (!AStmt)
24102 return StmtError();
24103
24104 SemaRef.setFunctionHasBranchProtectedScope();
24105
24106 return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
24107 AStmt);
24108}
24109
24111 SourceLocation StartLoc,
24112 SourceLocation LParenLoc,
24113 SourceLocation EndLoc) {
24115 for (Expr *RefExpr : VarList) {
24116 assert(RefExpr && "NULL expr in OpenMP inclusive clause.");
24117 SourceLocation ELoc;
24118 SourceRange ERange;
24119 Expr *SimpleRefExpr = RefExpr;
24120 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24121 /*AllowArraySection=*/true);
24122 if (Res.second)
24123 // It will be analyzed later.
24124 Vars.push_back(RefExpr);
24125 ValueDecl *D = Res.first;
24126 if (!D)
24127 continue;
24128
24129 const DSAStackTy::DSAVarData DVar =
24130 DSAStack->getTopDSA(D, /*FromParent=*/true);
24131 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
24132 // A list item that appears in the inclusive or exclusive clause must appear
24133 // in a reduction clause with the inscan modifier on the enclosing
24134 // worksharing-loop, worksharing-loop SIMD, or simd construct.
24135 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
24136 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
24137 << RefExpr->getSourceRange();
24138
24139 if (DSAStack->getParentDirective() != OMPD_unknown)
24140 DSAStack->markDeclAsUsedInScanDirective(D);
24141 Vars.push_back(RefExpr);
24142 }
24143
24144 if (Vars.empty())
24145 return nullptr;
24146
24147 return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
24148 EndLoc, Vars);
24149}
24150
24152 SourceLocation StartLoc,
24153 SourceLocation LParenLoc,
24154 SourceLocation EndLoc) {
24156 for (Expr *RefExpr : VarList) {
24157 assert(RefExpr && "NULL expr in OpenMP exclusive clause.");
24158 SourceLocation ELoc;
24159 SourceRange ERange;
24160 Expr *SimpleRefExpr = RefExpr;
24161 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24162 /*AllowArraySection=*/true);
24163 if (Res.second)
24164 // It will be analyzed later.
24165 Vars.push_back(RefExpr);
24166 ValueDecl *D = Res.first;
24167 if (!D)
24168 continue;
24169
24170 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
24171 DSAStackTy::DSAVarData DVar;
24172 if (ParentDirective != OMPD_unknown)
24173 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
24174 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
24175 // A list item that appears in the inclusive or exclusive clause must appear
24176 // in a reduction clause with the inscan modifier on the enclosing
24177 // worksharing-loop, worksharing-loop SIMD, or simd construct.
24178 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
24179 DVar.Modifier != OMPC_REDUCTION_inscan) {
24180 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
24181 << RefExpr->getSourceRange();
24182 } else {
24183 DSAStack->markDeclAsUsedInScanDirective(D);
24184 }
24185 Vars.push_back(RefExpr);
24186 }
24187
24188 if (Vars.empty())
24189 return nullptr;
24190
24191 return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
24192 EndLoc, Vars);
24193}
24194
24195/// Tries to find omp_alloctrait_t type.
24196static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
24197 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
24198 if (!OMPAlloctraitT.isNull())
24199 return true;
24200 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
24201 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
24202 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
24203 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
24204 return false;
24205 }
24206 Stack->setOMPAlloctraitT(PT.get());
24207 return true;
24208}
24209
24211 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
24213 ASTContext &Context = getASTContext();
24214 // OpenMP [2.12.5, target Construct]
24215 // allocator is an identifier of omp_allocator_handle_t type.
24216 if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack))
24217 return nullptr;
24218 // OpenMP [2.12.5, target Construct]
24219 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
24220 if (llvm::any_of(
24221 Data,
24222 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
24223 !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack))
24224 return nullptr;
24225 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
24226 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
24227 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
24228 StringRef Allocator =
24229 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
24230 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
24231 PredefinedAllocators.insert(SemaRef.LookupSingleName(
24232 SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
24233 }
24234
24236 for (const UsesAllocatorsData &D : Data) {
24237 Expr *AllocatorExpr = nullptr;
24238 // Check allocator expression.
24239 if (D.Allocator->isTypeDependent()) {
24240 AllocatorExpr = D.Allocator;
24241 } else {
24242 // Traits were specified - need to assign new allocator to the specified
24243 // allocator, so it must be an lvalue.
24244 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
24245 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
24246 bool IsPredefinedAllocator = false;
24247 if (DRE) {
24248 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
24249 getAllocatorKind(SemaRef, DSAStack, AllocatorExpr);
24250 IsPredefinedAllocator =
24251 AllocatorTy !=
24252 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
24253 }
24254 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
24255 QualType AllocatorExprType = AllocatorExpr->getType();
24256 bool IsTypeCompatible = IsPredefinedAllocator;
24257 IsTypeCompatible = IsTypeCompatible ||
24258 Context.hasSameUnqualifiedType(AllocatorExprType,
24259 OMPAllocatorHandleT);
24260 IsTypeCompatible =
24261 IsTypeCompatible ||
24262 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
24263 bool IsNonConstantLValue =
24264 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
24265 if (!DRE || !IsTypeCompatible ||
24266 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
24267 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
24268 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
24269 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
24270 continue;
24271 }
24272 // OpenMP [2.12.5, target Construct]
24273 // Predefined allocators appearing in a uses_allocators clause cannot have
24274 // traits specified.
24275 if (IsPredefinedAllocator && D.AllocatorTraits) {
24277 diag::err_omp_predefined_allocator_with_traits)
24279 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
24280 << cast<NamedDecl>(DRE->getDecl())->getName()
24281 << D.Allocator->getSourceRange();
24282 continue;
24283 }
24284 // OpenMP [2.12.5, target Construct]
24285 // Non-predefined allocators appearing in a uses_allocators clause must
24286 // have traits specified.
24287 if (getLangOpts().OpenMP < 52) {
24288 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
24290 diag::err_omp_nonpredefined_allocator_without_traits);
24291 continue;
24292 }
24293 }
24294 // No allocator traits - just convert it to rvalue.
24295 if (!D.AllocatorTraits)
24296 AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
24297 DSAStack->addUsesAllocatorsDecl(
24298 DRE->getDecl(),
24299 IsPredefinedAllocator
24300 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
24301 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
24302 }
24303 Expr *AllocatorTraitsExpr = nullptr;
24304 if (D.AllocatorTraits) {
24306 AllocatorTraitsExpr = D.AllocatorTraits;
24307 } else {
24308 // OpenMP [2.12.5, target Construct]
24309 // Arrays that contain allocator traits that appear in a uses_allocators
24310 // clause must be constant arrays, have constant values and be defined
24311 // in the same scope as the construct in which the clause appears.
24312 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
24313 // Check that traits expr is a constant array.
24314 QualType TraitTy;
24315 if (const ArrayType *Ty =
24316 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
24317 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
24318 TraitTy = ConstArrayTy->getElementType();
24319 if (TraitTy.isNull() ||
24320 !(Context.hasSameUnqualifiedType(TraitTy,
24321 DSAStack->getOMPAlloctraitT()) ||
24322 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
24323 /*CompareUnqualified=*/true))) {
24325 diag::err_omp_expected_array_alloctraits)
24326 << AllocatorTraitsExpr->getType();
24327 continue;
24328 }
24329 // Do not map by default allocator traits if it is a standalone
24330 // variable.
24331 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
24332 DSAStack->addUsesAllocatorsDecl(
24333 DRE->getDecl(),
24334 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
24335 }
24336 }
24337 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
24338 NewD.Allocator = AllocatorExpr;
24339 NewD.AllocatorTraits = AllocatorTraitsExpr;
24340 NewD.LParenLoc = D.LParenLoc;
24341 NewD.RParenLoc = D.RParenLoc;
24342 }
24343 return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc,
24344 EndLoc, NewData);
24345}
24346
24348 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
24349 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
24351 for (Expr *RefExpr : Locators) {
24352 assert(RefExpr && "NULL expr in OpenMP affinity clause.");
24353 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
24354 // It will be analyzed later.
24355 Vars.push_back(RefExpr);
24356 continue;
24357 }
24358
24359 SourceLocation ELoc = RefExpr->getExprLoc();
24360 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
24361
24362 if (!SimpleExpr->isLValue()) {
24363 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24364 << 1 << 0 << RefExpr->getSourceRange();
24365 continue;
24366 }
24367
24368 ExprResult Res;
24369 {
24371 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
24372 }
24373 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
24375 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24376 << 1 << 0 << RefExpr->getSourceRange();
24377 continue;
24378 }
24379 Vars.push_back(SimpleExpr);
24380 }
24381
24382 return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc,
24383 ColonLoc, EndLoc, Modifier, Vars);
24384}
24385
24387 SourceLocation KindLoc,
24388 SourceLocation StartLoc,
24389 SourceLocation LParenLoc,
24390 SourceLocation EndLoc) {
24391 if (Kind == OMPC_BIND_unknown) {
24392 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24393 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
24394 /*Last=*/unsigned(OMPC_BIND_unknown))
24395 << getOpenMPClauseNameForDiag(OMPC_bind);
24396 return nullptr;
24397 }
24398
24399 return OMPBindClause::Create(getASTContext(), Kind, KindLoc, StartLoc,
24400 LParenLoc, EndLoc);
24401}
24402
24404 SourceLocation StartLoc,
24405 SourceLocation LParenLoc,
24406 SourceLocation EndLoc) {
24407 Expr *ValExpr = Size;
24408 Stmt *HelperValStmt = nullptr;
24409
24410 // OpenMP [2.5, Restrictions]
24411 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
24412 // value.
24413 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem,
24414 /*StrictlyPositive=*/false))
24415 return nullptr;
24416
24417 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24419 DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP);
24420 if (CaptureRegion != OMPD_unknown &&
24421 !SemaRef.CurContext->isDependentContext()) {
24422 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
24423 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24424 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
24425 HelperValStmt = buildPreInits(getASTContext(), Captures);
24426 }
24427
24429 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
24430}
24431
24434 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
24435 SourceLocation LParenLoc, SourceLocation EndLoc) {
24436
24437 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
24438 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
24439 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
24440 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
24441 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
24442 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_doacross);
24443 return nullptr;
24444 }
24445
24447 DSAStackTy::OperatorOffsetTy OpsOffs;
24448 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
24449 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
24450 SemaRef,
24451 DepType == OMPC_DOACROSS_source ||
24452 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
24453 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
24454 VarList, DSAStack, EndLoc);
24455 Vars = VarOffset.Vars;
24456 OpsOffs = VarOffset.OpsOffs;
24457 TotalDepCount = VarOffset.TotalDepCount;
24458 auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc,
24459 EndLoc, DepType, DepLoc, ColonLoc, Vars,
24460 TotalDepCount.getZExtValue());
24461 if (DSAStack->isParentOrderedRegion())
24462 DSAStack->addDoacrossDependClause(C, OpsOffs);
24463 return C;
24464}
24465
24467 SourceLocation StartLoc,
24468 SourceLocation LParenLoc,
24469 SourceLocation EndLoc) {
24470 return new (getASTContext())
24471 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
24472}
24473
24475 SourceLocation EndLoc) {
24476 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
24477}
24478
24480 SourceLocation LParenLoc,
24481 SourceLocation EndLoc) {
24482 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
24483}
24484
24488 switch (CK) {
24489 case OMPC_absent:
24490 return OMPAbsentClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
24491 case OMPC_contains:
24492 return OMPContainsClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
24493 default:
24494 llvm_unreachable("Unexpected OpenMP clause");
24495 }
24496}
24497
24499 SourceLocation Loc,
24500 SourceLocation RLoc) {
24501 switch (CK) {
24502 case OMPC_no_openmp:
24503 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
24504 case OMPC_no_openmp_routines:
24505 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
24506 case OMPC_no_parallelism:
24507 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
24508 case OMPC_no_openmp_constructs:
24509 return new (getASTContext()) OMPNoOpenMPConstructsClause(Loc, RLoc);
24510 default:
24511 llvm_unreachable("Unexpected OpenMP clause");
24512 }
24513}
24514
24516 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
24517 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
24518 Expr *Stride, SourceLocation RBLoc) {
24519 ASTContext &Context = getASTContext();
24520 if (Base->hasPlaceholderType() &&
24521 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
24522 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
24523 if (Result.isInvalid())
24524 return ExprError();
24525 Base = Result.get();
24526 }
24527 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
24528 ExprResult Result = SemaRef.CheckPlaceholderExpr(LowerBound);
24529 if (Result.isInvalid())
24530 return ExprError();
24531 Result = SemaRef.DefaultLvalueConversion(Result.get());
24532 if (Result.isInvalid())
24533 return ExprError();
24534 LowerBound = Result.get();
24535 }
24536 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
24537 ExprResult Result = SemaRef.CheckPlaceholderExpr(Length);
24538 if (Result.isInvalid())
24539 return ExprError();
24540 Result = SemaRef.DefaultLvalueConversion(Result.get());
24541 if (Result.isInvalid())
24542 return ExprError();
24543 Length = Result.get();
24544 }
24545 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
24546 ExprResult Result = SemaRef.CheckPlaceholderExpr(Stride);
24547 if (Result.isInvalid())
24548 return ExprError();
24549 Result = SemaRef.DefaultLvalueConversion(Result.get());
24550 if (Result.isInvalid())
24551 return ExprError();
24552 Stride = Result.get();
24553 }
24554
24555 // Build an unanalyzed expression if either operand is type-dependent.
24556 if (Base->isTypeDependent() ||
24557 (LowerBound &&
24558 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
24559 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
24560 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
24561 return new (Context) ArraySectionExpr(
24562 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
24563 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
24564 }
24565
24566 // Perform default conversions.
24568 QualType ResultTy;
24569 if (OriginalTy->isAnyPointerType()) {
24570 ResultTy = OriginalTy->getPointeeType();
24571 } else if (OriginalTy->isArrayType()) {
24572 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
24573 } else {
24574 return ExprError(
24575 Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
24576 << Base->getSourceRange());
24577 }
24578 // C99 6.5.2.1p1
24579 if (LowerBound) {
24580 auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
24581 LowerBound);
24582 if (Res.isInvalid())
24583 return ExprError(Diag(LowerBound->getExprLoc(),
24584 diag::err_omp_typecheck_section_not_integer)
24585 << 0 << LowerBound->getSourceRange());
24586 LowerBound = Res.get();
24587
24588 if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
24589 LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
24590 Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
24591 << 0 << LowerBound->getSourceRange();
24592 }
24593 if (Length) {
24594 auto Res =
24595 PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
24596 if (Res.isInvalid())
24597 return ExprError(Diag(Length->getExprLoc(),
24598 diag::err_omp_typecheck_section_not_integer)
24599 << 1 << Length->getSourceRange());
24600 Length = Res.get();
24601
24602 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
24603 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
24604 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
24605 << 1 << Length->getSourceRange();
24606 }
24607 if (Stride) {
24608 ExprResult Res =
24610 if (Res.isInvalid())
24611 return ExprError(Diag(Stride->getExprLoc(),
24612 diag::err_omp_typecheck_section_not_integer)
24613 << 1 << Stride->getSourceRange());
24614 Stride = Res.get();
24615
24616 if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
24617 Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
24618 Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
24619 << 1 << Stride->getSourceRange();
24620 }
24621
24622 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
24623 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
24624 // type. Note that functions are not objects, and that (in C99 parlance)
24625 // incomplete types are not object types.
24626 if (ResultTy->isFunctionType()) {
24627 Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
24628 << ResultTy << Base->getSourceRange();
24629 return ExprError();
24630 }
24631
24632 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
24633 diag::err_omp_section_incomplete_type, Base))
24634 return ExprError();
24635
24636 if (LowerBound && !OriginalTy->isAnyPointerType()) {
24638 if (LowerBound->EvaluateAsInt(Result, Context)) {
24639 // OpenMP 5.0, [2.1.5 Array Sections]
24640 // The array section must be a subset of the original array.
24641 llvm::APSInt LowerBoundValue = Result.Val.getInt();
24642 if (LowerBoundValue.isNegative()) {
24643 Diag(LowerBound->getExprLoc(),
24644 diag::err_omp_section_not_subset_of_array)
24645 << LowerBound->getSourceRange();
24646 return ExprError();
24647 }
24648 }
24649 }
24650
24651 if (Length) {
24653 if (Length->EvaluateAsInt(Result, Context)) {
24654 // OpenMP 5.0, [2.1.5 Array Sections]
24655 // The length must evaluate to non-negative integers.
24656 llvm::APSInt LengthValue = Result.Val.getInt();
24657 if (LengthValue.isNegative()) {
24658 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
24659 << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
24660 << Length->getSourceRange();
24661 return ExprError();
24662 }
24663 }
24664 } else if (SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.isValid() &&
24665 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
24666 !OriginalTy->isVariableArrayType()))) {
24667 // OpenMP 5.0, [2.1.5 Array Sections]
24668 // When the size of the array dimension is not known, the length must be
24669 // specified explicitly.
24670 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
24671 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
24672 return ExprError();
24673 }
24674
24675 if (Stride) {
24677 if (Stride->EvaluateAsInt(Result, Context)) {
24678 // OpenMP 5.0, [2.1.5 Array Sections]
24679 // The stride must evaluate to a positive integer.
24680 llvm::APSInt StrideValue = Result.Val.getInt();
24681 if (!StrideValue.isStrictlyPositive()) {
24682 Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
24683 << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
24684 << Stride->getSourceRange();
24685 return ExprError();
24686 }
24687 }
24688 }
24689
24690 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
24691 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(Base);
24692 if (Result.isInvalid())
24693 return ExprError();
24694 Base = Result.get();
24695 }
24696 return new (Context) ArraySectionExpr(
24697 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
24698 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
24699}
24700
24702 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
24703 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
24704 ASTContext &Context = getASTContext();
24705 if (Base->hasPlaceholderType()) {
24706 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
24707 if (Result.isInvalid())
24708 return ExprError();
24709 Result = SemaRef.DefaultLvalueConversion(Result.get());
24710 if (Result.isInvalid())
24711 return ExprError();
24712 Base = Result.get();
24713 }
24714 QualType BaseTy = Base->getType();
24715 // Delay analysis of the types/expressions if instantiation/specialization is
24716 // required.
24717 if (!BaseTy->isPointerType() && Base->isTypeDependent())
24718 return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
24719 LParenLoc, RParenLoc, Dims, Brackets);
24720 if (!BaseTy->isPointerType() ||
24721 (!Base->isTypeDependent() &&
24722 BaseTy->getPointeeType()->isIncompleteType()))
24723 return ExprError(Diag(Base->getExprLoc(),
24724 diag::err_omp_non_pointer_type_array_shaping_base)
24725 << Base->getSourceRange());
24726
24727 SmallVector<Expr *, 4> NewDims;
24728 bool ErrorFound = false;
24729 for (Expr *Dim : Dims) {
24730 if (Dim->hasPlaceholderType()) {
24731 ExprResult Result = SemaRef.CheckPlaceholderExpr(Dim);
24732 if (Result.isInvalid()) {
24733 ErrorFound = true;
24734 continue;
24735 }
24736 Result = SemaRef.DefaultLvalueConversion(Result.get());
24737 if (Result.isInvalid()) {
24738 ErrorFound = true;
24739 continue;
24740 }
24741 Dim = Result.get();
24742 }
24743 if (!Dim->isTypeDependent()) {
24746 if (Result.isInvalid()) {
24747 ErrorFound = true;
24748 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
24749 << Dim->getSourceRange();
24750 continue;
24751 }
24752 Dim = Result.get();
24753 Expr::EvalResult EvResult;
24754 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
24755 // OpenMP 5.0, [2.1.4 Array Shaping]
24756 // Each si is an integral type expression that must evaluate to a
24757 // positive integer.
24758 llvm::APSInt Value = EvResult.Val.getInt();
24759 if (!Value.isStrictlyPositive()) {
24760 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
24761 << toString(Value, /*Radix=*/10, /*Signed=*/true)
24762 << Dim->getSourceRange();
24763 ErrorFound = true;
24764 continue;
24765 }
24766 }
24767 }
24768 NewDims.push_back(Dim);
24769 }
24770 if (ErrorFound)
24771 return ExprError();
24772 return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
24773 LParenLoc, RParenLoc, NewDims, Brackets);
24774}
24775
24777 SourceLocation IteratorKwLoc,
24778 SourceLocation LLoc,
24779 SourceLocation RLoc,
24781 ASTContext &Context = getASTContext();
24783 bool IsCorrect = true;
24784 for (const OMPIteratorData &D : Data) {
24785 TypeSourceInfo *TInfo = nullptr;
24786 SourceLocation StartLoc;
24787 QualType DeclTy;
24788 if (!D.Type.getAsOpaquePtr()) {
24789 // OpenMP 5.0, 2.1.6 Iterators
24790 // In an iterator-specifier, if the iterator-type is not specified then
24791 // the type of that iterator is of int type.
24792 DeclTy = Context.IntTy;
24793 StartLoc = D.DeclIdentLoc;
24794 } else {
24795 DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo);
24796 StartLoc = TInfo->getTypeLoc().getBeginLoc();
24797 }
24798
24799 bool IsDeclTyDependent = DeclTy->isDependentType() ||
24800 DeclTy->containsUnexpandedParameterPack() ||
24801 DeclTy->isInstantiationDependentType();
24802 if (!IsDeclTyDependent) {
24803 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
24804 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
24805 // The iterator-type must be an integral or pointer type.
24806 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
24807 << DeclTy;
24808 IsCorrect = false;
24809 continue;
24810 }
24811 if (DeclTy.isConstant(Context)) {
24812 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
24813 // The iterator-type must not be const qualified.
24814 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
24815 << DeclTy;
24816 IsCorrect = false;
24817 continue;
24818 }
24819 }
24820
24821 // Iterator declaration.
24822 assert(D.DeclIdent && "Identifier expected.");
24823 // Always try to create iterator declarator to avoid extra error messages
24824 // about unknown declarations use.
24825 auto *VD =
24826 VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc,
24827 D.DeclIdent, DeclTy, TInfo, SC_None);
24828 VD->setImplicit();
24829 if (S) {
24830 // Check for conflicting previous declaration.
24831 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
24834 Previous.suppressDiagnostics();
24835 SemaRef.LookupName(Previous, S);
24836
24837 SemaRef.FilterLookupForScope(Previous, SemaRef.CurContext, S,
24838 /*ConsiderLinkage=*/false,
24839 /*AllowInlineNamespace=*/false);
24840 if (!Previous.empty()) {
24841 NamedDecl *Old = Previous.getRepresentativeDecl();
24842 Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
24843 Diag(Old->getLocation(), diag::note_previous_definition);
24844 } else {
24845 SemaRef.PushOnScopeChains(VD, S);
24846 }
24847 } else {
24848 SemaRef.CurContext->addDecl(VD);
24849 }
24850
24851 /// Act on the iterator variable declaration.
24853
24854 Expr *Begin = D.Range.Begin;
24855 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
24856 ExprResult BeginRes = SemaRef.PerformImplicitConversion(
24857 Begin, DeclTy, AssignmentAction::Converting);
24858 Begin = BeginRes.get();
24859 }
24860 Expr *End = D.Range.End;
24861 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
24862 ExprResult EndRes = SemaRef.PerformImplicitConversion(
24863 End, DeclTy, AssignmentAction::Converting);
24864 End = EndRes.get();
24865 }
24866 Expr *Step = D.Range.Step;
24867 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
24868 if (!Step->getType()->isIntegralType(Context)) {
24869 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
24870 << Step << Step->getSourceRange();
24871 IsCorrect = false;
24872 continue;
24873 }
24874 std::optional<llvm::APSInt> Result =
24875 Step->getIntegerConstantExpr(Context);
24876 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
24877 // If the step expression of a range-specification equals zero, the
24878 // behavior is unspecified.
24879 if (Result && Result->isZero()) {
24880 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
24881 << Step << Step->getSourceRange();
24882 IsCorrect = false;
24883 continue;
24884 }
24885 }
24886 if (!Begin || !End || !IsCorrect) {
24887 IsCorrect = false;
24888 continue;
24889 }
24890 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
24891 IDElem.IteratorDecl = VD;
24892 IDElem.AssignmentLoc = D.AssignLoc;
24893 IDElem.Range.Begin = Begin;
24894 IDElem.Range.End = End;
24895 IDElem.Range.Step = Step;
24896 IDElem.ColonLoc = D.ColonLoc;
24897 IDElem.SecondColonLoc = D.SecColonLoc;
24898 }
24899 if (!IsCorrect) {
24900 // Invalidate all created iterator declarations if error is found.
24901 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
24902 if (Decl *ID = D.IteratorDecl)
24903 ID->setInvalidDecl();
24904 }
24905 return ExprError();
24906 }
24908 if (!SemaRef.CurContext->isDependentContext()) {
24909 // Build number of ityeration for each iteration range.
24910 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
24911 // ((Begini-Stepi-1-Endi) / -Stepi);
24913 // (Endi - Begini)
24914 ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub,
24915 D.Range.End, D.Range.Begin);
24916 if (!Res.isUsable()) {
24917 IsCorrect = false;
24918 continue;
24919 }
24920 ExprResult St, St1;
24921 if (D.Range.Step) {
24922 St = D.Range.Step;
24923 // (Endi - Begini) + Stepi
24924 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(),
24925 St.get());
24926 if (!Res.isUsable()) {
24927 IsCorrect = false;
24928 continue;
24929 }
24930 // (Endi - Begini) + Stepi - 1
24931 Res = SemaRef.CreateBuiltinBinOp(
24932 D.AssignmentLoc, BO_Sub, Res.get(),
24933 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
24934 if (!Res.isUsable()) {
24935 IsCorrect = false;
24936 continue;
24937 }
24938 // ((Endi - Begini) + Stepi - 1) / Stepi
24939 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(),
24940 St.get());
24941 if (!Res.isUsable()) {
24942 IsCorrect = false;
24943 continue;
24944 }
24945 St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
24946 D.Range.Step);
24947 // (Begini - Endi)
24948 ExprResult Res1 = SemaRef.CreateBuiltinBinOp(
24949 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
24950 if (!Res1.isUsable()) {
24951 IsCorrect = false;
24952 continue;
24953 }
24954 // (Begini - Endi) - Stepi
24955 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(),
24956 St1.get());
24957 if (!Res1.isUsable()) {
24958 IsCorrect = false;
24959 continue;
24960 }
24961 // (Begini - Endi) - Stepi - 1
24962 Res1 = SemaRef.CreateBuiltinBinOp(
24963 D.AssignmentLoc, BO_Sub, Res1.get(),
24964 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
24965 if (!Res1.isUsable()) {
24966 IsCorrect = false;
24967 continue;
24968 }
24969 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
24970 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(),
24971 St1.get());
24972 if (!Res1.isUsable()) {
24973 IsCorrect = false;
24974 continue;
24975 }
24976 // Stepi > 0.
24977 ExprResult CmpRes = SemaRef.CreateBuiltinBinOp(
24978 D.AssignmentLoc, BO_GT, D.Range.Step,
24979 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
24980 if (!CmpRes.isUsable()) {
24981 IsCorrect = false;
24982 continue;
24983 }
24984 Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
24985 CmpRes.get(), Res.get(), Res1.get());
24986 if (!Res.isUsable()) {
24987 IsCorrect = false;
24988 continue;
24989 }
24990 }
24991 Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false);
24992 if (!Res.isUsable()) {
24993 IsCorrect = false;
24994 continue;
24995 }
24996
24997 // Build counter update.
24998 // Build counter.
24999 auto *CounterVD = VarDecl::Create(Context, SemaRef.CurContext,
25000 D.IteratorDecl->getBeginLoc(),
25001 D.IteratorDecl->getBeginLoc(), nullptr,
25002 Res.get()->getType(), nullptr, SC_None);
25003 CounterVD->setImplicit();
25004 ExprResult RefRes =
25005 SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue,
25006 D.IteratorDecl->getBeginLoc());
25007 // Build counter update.
25008 // I = Begini + counter * Stepi;
25009 ExprResult UpdateRes;
25010 if (D.Range.Step) {
25011 UpdateRes = SemaRef.CreateBuiltinBinOp(
25012 D.AssignmentLoc, BO_Mul,
25013 SemaRef.DefaultLvalueConversion(RefRes.get()).get(), St.get());
25014 } else {
25015 UpdateRes = SemaRef.DefaultLvalueConversion(RefRes.get());
25016 }
25017 if (!UpdateRes.isUsable()) {
25018 IsCorrect = false;
25019 continue;
25020 }
25021 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
25022 D.Range.Begin, UpdateRes.get());
25023 if (!UpdateRes.isUsable()) {
25024 IsCorrect = false;
25025 continue;
25026 }
25027 ExprResult VDRes =
25028 SemaRef.BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl),
25029 cast<VarDecl>(D.IteratorDecl)->getType(),
25030 VK_LValue, D.IteratorDecl->getBeginLoc());
25031 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
25032 VDRes.get(), UpdateRes.get());
25033 if (!UpdateRes.isUsable()) {
25034 IsCorrect = false;
25035 continue;
25036 }
25037 UpdateRes =
25038 SemaRef.ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true);
25039 if (!UpdateRes.isUsable()) {
25040 IsCorrect = false;
25041 continue;
25042 }
25043 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
25044 D.AssignmentLoc, UO_PreInc, RefRes.get());
25045 if (!CounterUpdateRes.isUsable()) {
25046 IsCorrect = false;
25047 continue;
25048 }
25049 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(CounterUpdateRes.get(),
25050 /*DiscardedValue=*/true);
25051 if (!CounterUpdateRes.isUsable()) {
25052 IsCorrect = false;
25053 continue;
25054 }
25055 OMPIteratorHelperData &HD = Helpers.emplace_back();
25056 HD.CounterVD = CounterVD;
25057 HD.Upper = Res.get();
25058 HD.Update = UpdateRes.get();
25059 HD.CounterUpdate = CounterUpdateRes.get();
25060 }
25061 } else {
25062 Helpers.assign(ID.size(), {});
25063 }
25064 if (!IsCorrect) {
25065 // Invalidate all created iterator declarations if error is found.
25066 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
25067 if (Decl *ID = D.IteratorDecl)
25068 ID->setInvalidDecl();
25069 }
25070 return ExprError();
25071 }
25072 return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc,
25073 LLoc, RLoc, ID, Helpers);
25074}
25075
25076/// Check if \p AssumptionStr is a known assumption and warn if not.
25078 StringRef AssumptionStr) {
25079 if (llvm::getKnownAssumptionStrings().count(AssumptionStr))
25080 return;
25081
25082 unsigned BestEditDistance = 3;
25083 StringRef Suggestion;
25084 for (const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) {
25085 unsigned EditDistance =
25086 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
25087 if (EditDistance < BestEditDistance) {
25088 Suggestion = KnownAssumptionIt.getKey();
25089 BestEditDistance = EditDistance;
25090 }
25091 }
25092
25093 if (!Suggestion.empty())
25094 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
25095 << AssumptionStr << Suggestion;
25096 else
25097 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
25098 << AssumptionStr;
25099}
25100
25102 // Handle the case where the attribute has a text message.
25103 StringRef Str;
25104 SourceLocation AttrStrLoc;
25105 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
25106 return;
25107
25108 checkOMPAssumeAttr(SemaRef, AttrStrLoc, Str);
25109
25110 D->addAttr(::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
25111}
25112
25114 : 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 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 propageted 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.
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 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:188
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:741
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:817
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:737
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:856
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:3720
QualType getElementType() const
Definition TypeBase.h:3732
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:4923
unsigned getNumParams() const
Definition Decl.h:4961
void setNothrow(bool Nothrow=true)
Definition Decl.cpp:5574
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:5570
ImplicitParamDecl * getParam(unsigned i) const
Definition Decl.h:4963
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:3157
bool isBitField() const
Determines whether this field is a bitfield.
Definition Decl.h:3260
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4767
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
Definition Decl.h:3404
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:1999
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2794
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2771
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition Decl.h:2469
FunctionDecl * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
bool isConsteval() const
Definition Decl.h:2481
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3767
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:5264
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
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:273
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:294
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:300
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:339
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:316
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
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 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:1789
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:8374
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:8285
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:8470
QualType getCanonicalType() const
Definition TypeBase.h:8337
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8379
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:8439
const Type * getTypePtrOrNull() const
Definition TypeBase.h:8289
Represents a struct/union/class.
Definition Decl.h:4309
field_range fields() const
Definition Decl.h:4512
field_iterator field_begin() const
Definition Decl.cpp:5154
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3571
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 * 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.
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:1290
Expr * get() const
Definition Sema.h:7725
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition Sema.h:12409
Abstract base class used for diagnosing integer constant expression violations.
Definition Sema.h:7676
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:854
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition Sema.h:1120
bool isDeclInScope(NamedDecl *D, DeclContext *Ctx, Scope *S=nullptr, bool AllowInlineNamespace=false) const
isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true if 'D' is in Scope 'S',...
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
void BuildBasePathArray(const CXXBasePaths &Paths, CXXCastPath &BasePath)
ExprResult IgnoredValueConversions(Expr *E)
IgnoredValueConversions - Given that an expression's result is syntactically ignored,...
@ LookupOrdinaryName
Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....
Definition Sema.h:9291
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
Definition Sema.h:9332
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
Definition Sema.h:9334
@ LookupAnyName
Look up any declaration with any name.
Definition Sema.h:9336
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:1505
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
Definition Sema.h:4729
@ AR_inaccessible
Definition Sema.h:1659
Scope * getScopeForContext(DeclContext *Ctx)
Determines the active Scope associated with the given declaration context.
Definition Sema.cpp:2311
FPOptionsOverride CurFPFeatureOverrides()
Definition Sema.h:2049
NamedDecl * LookupSingleName(Scope *S, DeclarationName Name, SourceLocation Loc, LookupNameKind NameKind, RedeclarationKind Redecl=RedeclarationKind::NotForRedeclaration)
Look up a name, looking for a single declaration.
ASTContext & Context
Definition Sema.h:1283
void ActOnCapturedRegionError()
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
Definition SemaDecl.cpp: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:925
ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input, bool IsAfterAmp=false)
bool tryCaptureVariable(ValueDecl *Var, SourceLocation Loc, TryCaptureKind Kind, SourceLocation EllipsisLoc, bool BuildAndDiagnose, QualType &CaptureType, QualType &DeclRefType, const unsigned *const FunctionScopeIndexToStopAt)
Try to capture the given variable.
void PopExpressionEvaluationContext()
llvm::SmallSetVector< CXXRecordDecl *, 16 > AssociatedClassSet
Definition Sema.h:9284
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition Sema.h:1191
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
void FindAssociatedClassesAndNamespaces(SourceLocation InstantiationLoc, ArrayRef< Expr * > Args, AssociatedNamespaceSet &AssociatedNamespaces, AssociatedClassSet &AssociatedClasses)
Find the associated classes and namespaces for argument-dependent lookup for a call with the given se...
const LangOptions & getLangOpts() const
Definition Sema.h:918
bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, QualType ObjectType, bool AllowBuiltinCreation=false, bool EnteringContext=false)
Performs name lookup for a name that was parsed in the source code, and may contain a C++ scope speci...
Preprocessor & PP
Definition Sema.h:1282
AccessResult CheckBaseClassAccess(SourceLocation AccessLoc, QualType Base, QualType Derived, const CXXBasePath &Path, unsigned DiagID, bool ForceCheck=false, bool ForceUnprivileged=false)
Checks access for a hierarchy conversion.
const LangOptions & LangOpts
Definition Sema.h:1281
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
Definition Sema.cpp:2557
llvm::SmallSetVector< DeclContext *, 16 > AssociatedNamespaceSet
Definition Sema.h:9283
DeclContext * getCurLexicalContext() const
Definition Sema.h:1124
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, CapturedRegionKind Kind, unsigned NumParams)
ExprResult DefaultLvalueConversion(Expr *E)
Definition SemaExpr.cpp:633
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
Definition Sema.h:15331
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:1418
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:15286
void setFunctionHasBranchProtectedScope()
Definition Sema.cpp:2497
std::pair< StringRef, QualType > CapturedParamNameType
Definition Sema.h:11179
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:6706
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
Definition Sema.h:6675
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
Definition SemaStmt.cpp:75
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
Definition Sema.h:1246
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
void DiscardCleanupsInEvaluationContext()
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, bool ForFoldExpression=false)
ExprResult ActOnIntegerConstant(SourceLocation Loc, int64_t Val)
MemberExpr * BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc, NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl, bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK, ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs=nullptr)
void ActOnUninitializedDecl(Decl *dcl)
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD=nullptr)
Definition Sema.cpp: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:7739
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition Sema.h:8609
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
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:4834
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:3510
SourceLocation getBeginLoc() const
Get the begin source location.
Definition TypeLoc.cpp:193
A container of type source information.
Definition TypeBase.h:8256
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:8267
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:9058
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:8625
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:8621
bool isArithmeticType() const
Definition Type.cpp:2337
bool isPointerType() const
Definition TypeBase.h:8522
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:8922
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9165
bool isReferenceType() const
Definition TypeBase.h:8546
bool isEnumeralType() const
Definition TypeBase.h:8653
bool isScalarType() const
Definition TypeBase.h:8980
bool isVariableArrayType() const
Definition TypeBase.h:8633
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:8872
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:8847
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:8657
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:9021
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:9151
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:9115
bool isFunctionType() const
Definition TypeBase.h:8518
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:8530
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9098
bool isRecordType() const
Definition TypeBase.h:8649
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:711
void setType(QualType newType)
Definition Decl.h:723
QualType getType() const
Definition Decl.h:722
VarDecl * getPotentiallyDecomposedVarDecl()
Definition DeclCXX.cpp:3582
Represents a variable declaration or definition.
Definition Decl.h:925
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:1266
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition Decl.h:1568
TLSKind getTLSKind() const
Definition Decl.cpp:2168
bool hasInit() const
Definition Decl.cpp:2398
void setInitStyle(InitializationStyle Style)
Definition Decl.h:1451
InitializationStyle getInitStyle() const
The style of initialization for this declaration.
Definition Decl.h:1465
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:930
@ CallInit
Call-style initialization (C++98)
Definition Decl.h:933
bool isStaticDataMember() const
Determines whether this is a static data member.
Definition Decl.h:1282
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1225
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition Decl.h:1207
bool isFileVarDecl() const
Returns true for file scoped variable declaration.
Definition Decl.h:1341
const Expr * getInit() const
Definition Decl.h:1367
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition Decl.h:1183
@ TLS_None
Not a TLS variable.
Definition Decl.h:945
void setInit(Expr *I)
Definition Decl.cpp:2477
@ DeclarationOnly
This declaration is only a declaration.
Definition Decl.h:1294
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
Definition Decl.h:1252
bool isDirectInit() const
Whether the initializer is a direct-initializer (list or call).
Definition Decl.h:1470
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
Definition Decl.h:1228
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition Decl.h:1167
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:1261
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Definition Decl.h:1357
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
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:5364
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
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.
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:117
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:5884
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:5349
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.