clang 20.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
15
16#include "TreeTransform.h"
20#include "clang/AST/Decl.h"
21#include "clang/AST/DeclCXX.h"
25#include "clang/AST/StmtCXX.h"
34#include "clang/Sema/Lookup.h"
36#include "clang/Sema/Scope.h"
38#include "clang/Sema/Sema.h"
39#include "llvm/ADT/IndexedMap.h"
40#include "llvm/ADT/PointerEmbeddedInt.h"
41#include "llvm/ADT/STLExtras.h"
42#include "llvm/ADT/Sequence.h"
43#include "llvm/ADT/SetVector.h"
44#include "llvm/ADT/SmallSet.h"
45#include "llvm/ADT/StringExtras.h"
46#include "llvm/Frontend/OpenMP/OMPAssume.h"
47#include "llvm/Frontend/OpenMP/OMPConstants.h"
48#include "llvm/IR/Assumptions.h"
49#include <optional>
50
51using namespace clang;
52using namespace llvm::omp;
53
54//===----------------------------------------------------------------------===//
55// Stack of data-sharing attributes for variables
56//===----------------------------------------------------------------------===//
57
59 Sema &SemaRef, Expr *E,
61 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
62
63namespace {
64/// Default data sharing attributes, which can be applied to directive.
65enum DefaultDataSharingAttributes {
66 DSA_unspecified = 0, /// Data sharing attribute not specified.
67 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
68 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
69 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
70 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
71};
72
73/// Stack for tracking declarations used in OpenMP directives and
74/// clauses and their data-sharing attributes.
75class DSAStackTy {
76public:
77 struct DSAVarData {
78 OpenMPDirectiveKind DKind = OMPD_unknown;
79 OpenMPClauseKind CKind = OMPC_unknown;
80 unsigned Modifier = 0;
81 const Expr *RefExpr = nullptr;
82 DeclRefExpr *PrivateCopy = nullptr;
83 SourceLocation ImplicitDSALoc;
84 bool AppliedToPointee = false;
85 DSAVarData() = default;
86 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
87 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
88 SourceLocation ImplicitDSALoc, unsigned Modifier,
89 bool AppliedToPointee)
90 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
91 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
92 AppliedToPointee(AppliedToPointee) {}
93 };
94 using OperatorOffsetTy =
96 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
97 /// Kind of the declaration used in the uses_allocators clauses.
98 enum class UsesAllocatorsDeclKind {
99 /// Predefined allocator
100 PredefinedAllocator,
101 /// User-defined allocator
102 UserDefinedAllocator,
103 /// The declaration that represent allocator trait
104 AllocatorTrait,
105 };
106
107private:
108 struct DSAInfo {
109 OpenMPClauseKind Attributes = OMPC_unknown;
110 unsigned Modifier = 0;
111 /// Pointer to a reference expression and a flag which shows that the
112 /// variable is marked as lastprivate(true) or not (false).
113 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
114 DeclRefExpr *PrivateCopy = nullptr;
115 /// true if the attribute is applied to the pointee, not the variable
116 /// itself.
117 bool AppliedToPointee = false;
118 };
119 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
120 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
121 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
122 using LoopControlVariablesMapTy =
123 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
124 /// Struct that associates a component with the clause kind where they are
125 /// found.
126 struct MappedExprComponentTy {
128 OpenMPClauseKind Kind = OMPC_unknown;
129 };
130 using MappedExprComponentsTy =
131 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
132 using CriticalsWithHintsTy =
133 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
134 struct ReductionData {
135 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
136 SourceRange ReductionRange;
137 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
138 ReductionData() = default;
139 void set(BinaryOperatorKind BO, SourceRange RR) {
140 ReductionRange = RR;
141 ReductionOp = BO;
142 }
143 void set(const Expr *RefExpr, SourceRange RR) {
144 ReductionRange = RR;
145 ReductionOp = RefExpr;
146 }
147 };
148 using DeclReductionMapTy =
149 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
150 struct DefaultmapInfo {
151 OpenMPDefaultmapClauseModifier ImplicitBehavior =
153 SourceLocation SLoc;
154 DefaultmapInfo() = default;
156 : ImplicitBehavior(M), SLoc(Loc) {}
157 };
158
159 struct SharingMapTy {
160 DeclSAMapTy SharingMap;
161 DeclReductionMapTy ReductionMap;
162 UsedRefMapTy AlignedMap;
163 UsedRefMapTy NontemporalMap;
164 MappedExprComponentsTy MappedExprComponents;
165 LoopControlVariablesMapTy LCVMap;
166 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
167 SourceLocation DefaultAttrLoc;
168 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1];
169 OpenMPDirectiveKind Directive = OMPD_unknown;
170 DeclarationNameInfo DirectiveName;
171 Scope *CurScope = nullptr;
172 DeclContext *Context = nullptr;
173 SourceLocation ConstructLoc;
174 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
175 /// get the data (loop counters etc.) about enclosing loop-based construct.
176 /// This data is required during codegen.
177 DoacrossClauseMapTy DoacrossDepends;
178 /// First argument (Expr *) contains optional argument of the
179 /// 'ordered' clause, the second one is true if the regions has 'ordered'
180 /// clause, false otherwise.
181 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
182 bool RegionHasOrderConcurrent = false;
183 unsigned AssociatedLoops = 1;
184 bool HasMutipleLoops = false;
185 const Decl *PossiblyLoopCounter = nullptr;
186 bool NowaitRegion = false;
187 bool UntiedRegion = false;
188 bool CancelRegion = false;
189 bool LoopStart = false;
190 bool BodyComplete = false;
191 SourceLocation PrevScanLocation;
192 SourceLocation PrevOrderedLocation;
193 SourceLocation InnerTeamsRegionLoc;
194 /// Reference to the taskgroup task_reduction reference expression.
195 Expr *TaskgroupReductionRef = nullptr;
196 llvm::DenseSet<QualType> MappedClassesQualTypes;
197 SmallVector<Expr *, 4> InnerUsedAllocators;
198 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
199 /// List of globals marked as declare target link in this target region
200 /// (isOpenMPTargetExecutionDirective(Directive) == true).
201 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
202 /// List of decls used in inclusive/exclusive clauses of the scan directive.
203 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
204 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
205 UsesAllocatorsDecls;
206 /// Data is required on creating capture fields for implicit
207 /// default first|private clause.
208 struct ImplicitDefaultFDInfoTy {
209 /// Field decl.
210 const FieldDecl *FD = nullptr;
211 /// Nesting stack level
212 size_t StackLevel = 0;
213 /// Capture variable decl.
214 VarDecl *VD = nullptr;
215 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
216 VarDecl *VD)
217 : FD(FD), StackLevel(StackLevel), VD(VD) {}
218 };
219 /// List of captured fields
221 ImplicitDefaultFirstprivateFDs;
222 Expr *DeclareMapperVar = nullptr;
223 SmallVector<VarDecl *, 16> IteratorVarDecls;
224 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
225 Scope *CurScope, SourceLocation Loc)
226 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
227 ConstructLoc(Loc) {}
228 SharingMapTy() = default;
229 };
230
231 using StackTy = SmallVector<SharingMapTy, 4>;
232
233 /// Stack of used declaration and their data-sharing attributes.
234 DeclSAMapTy Threadprivates;
235 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
237 /// true, if check for DSA must be from parent directive, false, if
238 /// from current directive.
239 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
240 Sema &SemaRef;
241 bool ForceCapturing = false;
242 /// true if all the variables in the target executable directives must be
243 /// captured by reference.
244 bool ForceCaptureByReferenceInTargetExecutable = false;
245 CriticalsWithHintsTy Criticals;
246 unsigned IgnoredStackElements = 0;
247
248 /// Iterators over the stack iterate in order from innermost to outermost
249 /// directive.
250 using const_iterator = StackTy::const_reverse_iterator;
251 const_iterator begin() const {
252 return Stack.empty() ? const_iterator()
253 : Stack.back().first.rbegin() + IgnoredStackElements;
254 }
255 const_iterator end() const {
256 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
257 }
258 using iterator = StackTy::reverse_iterator;
259 iterator begin() {
260 return Stack.empty() ? iterator()
261 : Stack.back().first.rbegin() + IgnoredStackElements;
262 }
263 iterator end() {
264 return Stack.empty() ? iterator() : Stack.back().first.rend();
265 }
266
267 // Convenience operations to get at the elements of the stack.
268
269 bool isStackEmpty() const {
270 return Stack.empty() ||
271 Stack.back().second != CurrentNonCapturingFunctionScope ||
272 Stack.back().first.size() <= IgnoredStackElements;
273 }
274 size_t getStackSize() const {
275 return isStackEmpty() ? 0
276 : Stack.back().first.size() - IgnoredStackElements;
277 }
278
279 SharingMapTy *getTopOfStackOrNull() {
280 size_t Size = getStackSize();
281 if (Size == 0)
282 return nullptr;
283 return &Stack.back().first[Size - 1];
284 }
285 const SharingMapTy *getTopOfStackOrNull() const {
286 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
287 }
288 SharingMapTy &getTopOfStack() {
289 assert(!isStackEmpty() && "no current directive");
290 return *getTopOfStackOrNull();
291 }
292 const SharingMapTy &getTopOfStack() const {
293 return const_cast<DSAStackTy &>(*this).getTopOfStack();
294 }
295
296 SharingMapTy *getSecondOnStackOrNull() {
297 size_t Size = getStackSize();
298 if (Size <= 1)
299 return nullptr;
300 return &Stack.back().first[Size - 2];
301 }
302 const SharingMapTy *getSecondOnStackOrNull() const {
303 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
304 }
305
306 /// Get the stack element at a certain level (previously returned by
307 /// \c getNestingLevel).
308 ///
309 /// Note that nesting levels count from outermost to innermost, and this is
310 /// the reverse of our iteration order where new inner levels are pushed at
311 /// the front of the stack.
312 SharingMapTy &getStackElemAtLevel(unsigned Level) {
313 assert(Level < getStackSize() && "no such stack element");
314 return Stack.back().first[Level];
315 }
316 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
317 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
318 }
319
320 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
321
322 /// Checks if the variable is a local for OpenMP region.
323 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
324
325 /// Vector of previously declared requires directives
327 /// omp_allocator_handle_t type.
328 QualType OMPAllocatorHandleT;
329 /// omp_depend_t type.
330 QualType OMPDependT;
331 /// omp_event_handle_t type.
332 QualType OMPEventHandleT;
333 /// omp_alloctrait_t type.
334 QualType OMPAlloctraitT;
335 /// Expression for the predefined allocators.
336 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
337 nullptr};
338 /// Vector of previously encountered target directives
339 SmallVector<SourceLocation, 2> TargetLocations;
340 SourceLocation AtomicLocation;
341 /// Vector of declare variant construct traits.
343
344public:
345 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
346
347 /// Sets omp_allocator_handle_t type.
348 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
349 /// Gets omp_allocator_handle_t type.
350 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
351 /// Sets omp_alloctrait_t type.
352 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
353 /// Gets omp_alloctrait_t type.
354 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
355 /// Sets the given default allocator.
356 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
357 Expr *Allocator) {
358 OMPPredefinedAllocators[AllocatorKind] = Allocator;
359 }
360 /// Returns the specified default allocator.
361 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
362 return OMPPredefinedAllocators[AllocatorKind];
363 }
364 /// Sets omp_depend_t type.
365 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
366 /// Gets omp_depend_t type.
367 QualType getOMPDependT() const { return OMPDependT; }
368
369 /// Sets omp_event_handle_t type.
370 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
371 /// Gets omp_event_handle_t type.
372 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
373
374 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
375 OpenMPClauseKind getClauseParsingMode() const {
376 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
377 return ClauseKindMode;
378 }
379 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
380
381 bool isBodyComplete() const {
382 const SharingMapTy *Top = getTopOfStackOrNull();
383 return Top && Top->BodyComplete;
384 }
385 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
386
387 bool isForceVarCapturing() const { return ForceCapturing; }
388 void setForceVarCapturing(bool V) { ForceCapturing = V; }
389
390 void setForceCaptureByReferenceInTargetExecutable(bool V) {
391 ForceCaptureByReferenceInTargetExecutable = V;
392 }
393 bool isForceCaptureByReferenceInTargetExecutable() const {
394 return ForceCaptureByReferenceInTargetExecutable;
395 }
396
397 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
398 Scope *CurScope, SourceLocation Loc) {
399 assert(!IgnoredStackElements &&
400 "cannot change stack while ignoring elements");
401 if (Stack.empty() ||
402 Stack.back().second != CurrentNonCapturingFunctionScope)
403 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
404 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
405 Stack.back().first.back().DefaultAttrLoc = Loc;
406 }
407
408 void pop() {
409 assert(!IgnoredStackElements &&
410 "cannot change stack while ignoring elements");
411 assert(!Stack.back().first.empty() &&
412 "Data-sharing attributes stack is empty!");
413 Stack.back().first.pop_back();
414 }
415
416 /// RAII object to temporarily leave the scope of a directive when we want to
417 /// logically operate in its parent.
418 class ParentDirectiveScope {
419 DSAStackTy &Self;
420 bool Active;
421
422 public:
423 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
424 : Self(Self), Active(false) {
425 if (Activate)
426 enable();
427 }
428 ~ParentDirectiveScope() { disable(); }
429 void disable() {
430 if (Active) {
431 --Self.IgnoredStackElements;
432 Active = false;
433 }
434 }
435 void enable() {
436 if (!Active) {
437 ++Self.IgnoredStackElements;
438 Active = true;
439 }
440 }
441 };
442
443 /// Marks that we're started loop parsing.
444 void loopInit() {
445 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
446 "Expected loop-based directive.");
447 getTopOfStack().LoopStart = true;
448 }
449 /// Start capturing of the variables in the loop context.
450 void loopStart() {
451 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
452 "Expected loop-based directive.");
453 getTopOfStack().LoopStart = false;
454 }
455 /// true, if variables are captured, false otherwise.
456 bool isLoopStarted() const {
457 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
458 "Expected loop-based directive.");
459 return !getTopOfStack().LoopStart;
460 }
461 /// Marks (or clears) declaration as possibly loop counter.
462 void resetPossibleLoopCounter(const Decl *D = nullptr) {
463 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
464 }
465 /// Gets the possible loop counter decl.
466 const Decl *getPossiblyLoopCounter() const {
467 return getTopOfStack().PossiblyLoopCounter;
468 }
469 /// Start new OpenMP region stack in new non-capturing function.
470 void pushFunction() {
471 assert(!IgnoredStackElements &&
472 "cannot change stack while ignoring elements");
473 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
474 assert(!isa<CapturingScopeInfo>(CurFnScope));
475 CurrentNonCapturingFunctionScope = CurFnScope;
476 }
477 /// Pop region stack for non-capturing function.
478 void popFunction(const FunctionScopeInfo *OldFSI) {
479 assert(!IgnoredStackElements &&
480 "cannot change stack while ignoring elements");
481 if (!Stack.empty() && Stack.back().second == OldFSI) {
482 assert(Stack.back().first.empty());
483 Stack.pop_back();
484 }
485 CurrentNonCapturingFunctionScope = nullptr;
486 for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
487 if (!isa<CapturingScopeInfo>(FSI)) {
488 CurrentNonCapturingFunctionScope = FSI;
489 break;
490 }
491 }
492 }
493
494 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
495 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
496 }
497 const std::pair<const OMPCriticalDirective *, llvm::APSInt>
498 getCriticalWithHint(const DeclarationNameInfo &Name) const {
499 auto I = Criticals.find(Name.getAsString());
500 if (I != Criticals.end())
501 return I->second;
502 return std::make_pair(nullptr, llvm::APSInt());
503 }
504 /// If 'aligned' declaration for given variable \a D was not seen yet,
505 /// add it and return NULL; otherwise return previous occurrence's expression
506 /// for diagnostics.
507 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
508 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
509 /// add it and return NULL; otherwise return previous occurrence's expression
510 /// for diagnostics.
511 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
512
513 /// Register specified variable as loop control variable.
514 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
515 /// Check if the specified variable is a loop control variable for
516 /// current region.
517 /// \return The index of the loop control variable in the list of associated
518 /// for-loops (from outer to inner).
519 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
520 /// Check if the specified variable is a loop control variable for
521 /// parent region.
522 /// \return The index of the loop control variable in the list of associated
523 /// for-loops (from outer to inner).
524 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
525 /// Check if the specified variable is a loop control variable for
526 /// current region.
527 /// \return The index of the loop control variable in the list of associated
528 /// for-loops (from outer to inner).
529 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
530 unsigned Level) const;
531 /// Get the loop control variable for the I-th loop (or nullptr) in
532 /// parent directive.
533 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
534
535 /// Marks the specified decl \p D as used in scan directive.
536 void markDeclAsUsedInScanDirective(ValueDecl *D) {
537 if (SharingMapTy *Stack = getSecondOnStackOrNull())
538 Stack->UsedInScanDirective.insert(D);
539 }
540
541 /// Checks if the specified declaration was used in the inner scan directive.
542 bool isUsedInScanDirective(ValueDecl *D) const {
543 if (const SharingMapTy *Stack = getTopOfStackOrNull())
544 return Stack->UsedInScanDirective.contains(D);
545 return false;
546 }
547
548 /// Adds explicit data sharing attribute to the specified declaration.
549 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
550 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
551 bool AppliedToPointee = false);
552
553 /// Adds additional information for the reduction items with the reduction id
554 /// represented as an operator.
555 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
557 /// Adds additional information for the reduction items with the reduction id
558 /// represented as reduction identifier.
559 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
560 const Expr *ReductionRef);
561 /// Returns the location and reduction operation from the innermost parent
562 /// region for the given \p D.
563 const DSAVarData
564 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
566 Expr *&TaskgroupDescriptor) const;
567 /// Returns the location and reduction operation from the innermost parent
568 /// region for the given \p D.
569 const DSAVarData
570 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
571 const Expr *&ReductionRef,
572 Expr *&TaskgroupDescriptor) const;
573 /// Return reduction reference expression for the current taskgroup or
574 /// parallel/worksharing directives with task reductions.
575 Expr *getTaskgroupReductionRef() const {
576 assert((getTopOfStack().Directive == OMPD_taskgroup ||
577 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
578 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
579 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
580 "taskgroup reference expression requested for non taskgroup or "
581 "parallel/worksharing directive.");
582 return getTopOfStack().TaskgroupReductionRef;
583 }
584 /// Checks if the given \p VD declaration is actually a taskgroup reduction
585 /// descriptor variable at the \p Level of OpenMP regions.
586 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
587 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
588 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
589 ->getDecl() == VD;
590 }
591
592 /// Returns data sharing attributes from top of the stack for the
593 /// specified declaration.
594 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
595 /// Returns data-sharing attributes for the specified declaration.
596 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
597 /// Returns data-sharing attributes for the specified declaration.
598 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
599 /// Checks if the specified variables has data-sharing attributes which
600 /// match specified \a CPred predicate in any directive which matches \a DPred
601 /// predicate.
602 const DSAVarData
603 hasDSA(ValueDecl *D,
604 const llvm::function_ref<bool(OpenMPClauseKind, bool,
605 DefaultDataSharingAttributes)>
606 CPred,
607 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
608 bool FromParent) const;
609 /// Checks if the specified variables has data-sharing attributes which
610 /// match specified \a CPred predicate in any innermost directive which
611 /// matches \a DPred predicate.
612 const DSAVarData
613 hasInnermostDSA(ValueDecl *D,
614 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
615 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
616 bool FromParent) const;
617 /// Checks if the specified variables has explicit data-sharing
618 /// attributes which match specified \a CPred predicate at the specified
619 /// OpenMP region.
620 bool
621 hasExplicitDSA(const ValueDecl *D,
622 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
623 unsigned Level, bool NotLastprivate = false) const;
624
625 /// Returns true if the directive at level \Level matches in the
626 /// specified \a DPred predicate.
627 bool hasExplicitDirective(
628 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
629 unsigned Level) const;
630
631 /// Finds a directive which matches specified \a DPred predicate.
632 bool hasDirective(
633 const llvm::function_ref<bool(
635 DPred,
636 bool FromParent) const;
637
638 /// Returns currently analyzed directive.
639 OpenMPDirectiveKind getCurrentDirective() const {
640 const SharingMapTy *Top = getTopOfStackOrNull();
641 return Top ? Top->Directive : OMPD_unknown;
642 }
643 /// Returns directive kind at specified level.
644 OpenMPDirectiveKind getDirective(unsigned Level) const {
645 assert(!isStackEmpty() && "No directive at specified level.");
646 return getStackElemAtLevel(Level).Directive;
647 }
648 /// Returns the capture region at the specified level.
649 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
650 unsigned OpenMPCaptureLevel) const {
652 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
653 return CaptureRegions[OpenMPCaptureLevel];
654 }
655 /// Returns parent directive.
656 OpenMPDirectiveKind getParentDirective() const {
657 const SharingMapTy *Parent = getSecondOnStackOrNull();
658 return Parent ? Parent->Directive : OMPD_unknown;
659 }
660
661 /// Add requires decl to internal vector
662 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
663
664 /// Checks if the defined 'requires' directive has specified type of clause.
665 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
666 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
667 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
668 return isa<ClauseType>(C);
669 });
670 });
671 }
672
673 /// Checks for a duplicate clause amongst previously declared requires
674 /// directives
675 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
676 bool IsDuplicate = false;
677 for (OMPClause *CNew : ClauseList) {
678 for (const OMPRequiresDecl *D : RequiresDecls) {
679 for (const OMPClause *CPrev : D->clauselists()) {
680 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
681 SemaRef.Diag(CNew->getBeginLoc(),
682 diag::err_omp_requires_clause_redeclaration)
683 << getOpenMPClauseName(CNew->getClauseKind());
684 SemaRef.Diag(CPrev->getBeginLoc(),
685 diag::note_omp_requires_previous_clause)
686 << getOpenMPClauseName(CPrev->getClauseKind());
687 IsDuplicate = true;
688 }
689 }
690 }
691 }
692 return IsDuplicate;
693 }
694
695 /// Add location of previously encountered target to internal vector
696 void addTargetDirLocation(SourceLocation LocStart) {
697 TargetLocations.push_back(LocStart);
698 }
699
700 /// Add location for the first encountered atomic directive.
701 void addAtomicDirectiveLoc(SourceLocation Loc) {
702 if (AtomicLocation.isInvalid())
703 AtomicLocation = Loc;
704 }
705
706 /// Returns the location of the first encountered atomic directive in the
707 /// module.
708 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
709
710 // Return previously encountered target region locations.
711 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
712 return TargetLocations;
713 }
714
715 /// Set default data sharing attribute to none.
716 void setDefaultDSANone(SourceLocation Loc) {
717 getTopOfStack().DefaultAttr = DSA_none;
718 getTopOfStack().DefaultAttrLoc = Loc;
719 }
720 /// Set default data sharing attribute to shared.
721 void setDefaultDSAShared(SourceLocation Loc) {
722 getTopOfStack().DefaultAttr = DSA_shared;
723 getTopOfStack().DefaultAttrLoc = Loc;
724 }
725 /// Set default data sharing attribute to private.
726 void setDefaultDSAPrivate(SourceLocation Loc) {
727 getTopOfStack().DefaultAttr = DSA_private;
728 getTopOfStack().DefaultAttrLoc = Loc;
729 }
730 /// Set default data sharing attribute to firstprivate.
731 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
732 getTopOfStack().DefaultAttr = DSA_firstprivate;
733 getTopOfStack().DefaultAttrLoc = Loc;
734 }
735 /// Set default data mapping attribute to Modifier:Kind
736 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
738 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
739 DMI.ImplicitBehavior = M;
740 DMI.SLoc = Loc;
741 }
742 /// Check whether the implicit-behavior has been set in defaultmap
743 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
744 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
745 return getTopOfStack()
746 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
747 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
748 getTopOfStack()
749 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
750 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
751 getTopOfStack()
752 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
753 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
754 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
756 }
757
758 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
759 return ConstructTraits;
760 }
761 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
762 bool ScopeEntry) {
763 if (ScopeEntry)
764 ConstructTraits.append(Traits.begin(), Traits.end());
765 else
766 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
767 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
768 assert(Top == Trait && "Something left a trait on the stack!");
769 (void)Trait;
770 (void)Top;
771 }
772 }
773
774 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
775 return getStackSize() <= Level ? DSA_unspecified
776 : getStackElemAtLevel(Level).DefaultAttr;
777 }
778 DefaultDataSharingAttributes getDefaultDSA() const {
779 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
780 }
781 SourceLocation getDefaultDSALocation() const {
782 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
783 }
785 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
786 return isStackEmpty()
788 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
789 }
791 getDefaultmapModifierAtLevel(unsigned Level,
792 OpenMPDefaultmapClauseKind Kind) const {
793 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
794 }
795 bool isDefaultmapCapturedByRef(unsigned Level,
796 OpenMPDefaultmapClauseKind Kind) const {
798 getDefaultmapModifierAtLevel(Level, Kind);
799 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
800 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
801 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
802 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
803 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
804 (M == OMPC_DEFAULTMAP_MODIFIER_present);
805 }
806 return true;
807 }
808 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
810 switch (Kind) {
811 case OMPC_DEFAULTMAP_scalar:
812 case OMPC_DEFAULTMAP_pointer:
813 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
814 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
815 (M == OMPC_DEFAULTMAP_MODIFIER_default);
816 case OMPC_DEFAULTMAP_aggregate:
817 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
818 default:
819 break;
820 }
821 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
822 }
823 bool mustBeFirstprivateAtLevel(unsigned Level,
824 OpenMPDefaultmapClauseKind Kind) const {
826 getDefaultmapModifierAtLevel(Level, Kind);
827 return mustBeFirstprivateBase(M, Kind);
828 }
829 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
830 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
831 return mustBeFirstprivateBase(M, Kind);
832 }
833
834 /// Checks if the specified variable is a threadprivate.
835 bool isThreadPrivate(VarDecl *D) {
836 const DSAVarData DVar = getTopDSA(D, false);
837 return isOpenMPThreadPrivate(DVar.CKind);
838 }
839
840 /// Marks current region as ordered (it has an 'ordered' clause).
841 void setOrderedRegion(bool IsOrdered, const Expr *Param,
842 OMPOrderedClause *Clause) {
843 if (IsOrdered)
844 getTopOfStack().OrderedRegion.emplace(Param, Clause);
845 else
846 getTopOfStack().OrderedRegion.reset();
847 }
848 /// Returns true, if region is ordered (has associated 'ordered' clause),
849 /// false - otherwise.
850 bool isOrderedRegion() const {
851 if (const SharingMapTy *Top = getTopOfStackOrNull())
852 return Top->OrderedRegion.has_value();
853 return false;
854 }
855 /// Returns optional parameter for the ordered region.
856 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
857 if (const SharingMapTy *Top = getTopOfStackOrNull())
858 if (Top->OrderedRegion)
859 return *Top->OrderedRegion;
860 return std::make_pair(nullptr, nullptr);
861 }
862 /// Returns true, if parent region is ordered (has associated
863 /// 'ordered' clause), false - otherwise.
864 bool isParentOrderedRegion() const {
865 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
866 return Parent->OrderedRegion.has_value();
867 return false;
868 }
869 /// Returns optional parameter for the ordered region.
870 std::pair<const Expr *, OMPOrderedClause *>
871 getParentOrderedRegionParam() const {
872 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
873 if (Parent->OrderedRegion)
874 return *Parent->OrderedRegion;
875 return std::make_pair(nullptr, nullptr);
876 }
877 /// Marks current region as having an 'order' clause.
878 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
879 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
880 }
881 /// Returns true, if parent region is order (has associated
882 /// 'order' clause), false - otherwise.
883 bool isParentOrderConcurrent() const {
884 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
885 return Parent->RegionHasOrderConcurrent;
886 return false;
887 }
888 /// Marks current region as nowait (it has a 'nowait' clause).
889 void setNowaitRegion(bool IsNowait = true) {
890 getTopOfStack().NowaitRegion = IsNowait;
891 }
892 /// Returns true, if parent region is nowait (has associated
893 /// 'nowait' clause), false - otherwise.
894 bool isParentNowaitRegion() const {
895 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
896 return Parent->NowaitRegion;
897 return false;
898 }
899 /// Marks current region as untied (it has a 'untied' clause).
900 void setUntiedRegion(bool IsUntied = true) {
901 getTopOfStack().UntiedRegion = IsUntied;
902 }
903 /// Return true if current region is untied.
904 bool isUntiedRegion() const {
905 const SharingMapTy *Top = getTopOfStackOrNull();
906 return Top ? Top->UntiedRegion : false;
907 }
908 /// Marks parent region as cancel region.
909 void setParentCancelRegion(bool Cancel = true) {
910 if (SharingMapTy *Parent = getSecondOnStackOrNull())
911 Parent->CancelRegion |= Cancel;
912 }
913 /// Return true if current region has inner cancel construct.
914 bool isCancelRegion() const {
915 const SharingMapTy *Top = getTopOfStackOrNull();
916 return Top ? Top->CancelRegion : false;
917 }
918
919 /// Mark that parent region already has scan directive.
920 void setParentHasScanDirective(SourceLocation Loc) {
921 if (SharingMapTy *Parent = getSecondOnStackOrNull())
922 Parent->PrevScanLocation = Loc;
923 }
924 /// Return true if current region has inner cancel construct.
925 bool doesParentHasScanDirective() const {
926 const SharingMapTy *Top = getSecondOnStackOrNull();
927 return Top ? Top->PrevScanLocation.isValid() : false;
928 }
929 /// Return true if current region has inner cancel construct.
930 SourceLocation getParentScanDirectiveLoc() const {
931 const SharingMapTy *Top = getSecondOnStackOrNull();
932 return Top ? Top->PrevScanLocation : SourceLocation();
933 }
934 /// Mark that parent region already has ordered directive.
935 void setParentHasOrderedDirective(SourceLocation Loc) {
936 if (SharingMapTy *Parent = getSecondOnStackOrNull())
937 Parent->PrevOrderedLocation = Loc;
938 }
939 /// Return true if current region has inner ordered construct.
940 bool doesParentHasOrderedDirective() const {
941 const SharingMapTy *Top = getSecondOnStackOrNull();
942 return Top ? Top->PrevOrderedLocation.isValid() : false;
943 }
944 /// Returns the location of the previously specified ordered directive.
945 SourceLocation getParentOrderedDirectiveLoc() const {
946 const SharingMapTy *Top = getSecondOnStackOrNull();
947 return Top ? Top->PrevOrderedLocation : SourceLocation();
948 }
949
950 /// Set collapse value for the region.
951 void setAssociatedLoops(unsigned Val) {
952 getTopOfStack().AssociatedLoops = Val;
953 if (Val > 1)
954 getTopOfStack().HasMutipleLoops = true;
955 }
956 /// Return collapse value for region.
957 unsigned getAssociatedLoops() const {
958 const SharingMapTy *Top = getTopOfStackOrNull();
959 return Top ? Top->AssociatedLoops : 0;
960 }
961 /// Returns true if the construct is associated with multiple loops.
962 bool hasMutipleLoops() const {
963 const SharingMapTy *Top = getTopOfStackOrNull();
964 return Top ? Top->HasMutipleLoops : false;
965 }
966
967 /// Marks current target region as one with closely nested teams
968 /// region.
969 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
970 if (SharingMapTy *Parent = getSecondOnStackOrNull())
971 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
972 }
973 /// Returns true, if current region has closely nested teams region.
974 bool hasInnerTeamsRegion() const {
975 return getInnerTeamsRegionLoc().isValid();
976 }
977 /// Returns location of the nested teams region (if any).
978 SourceLocation getInnerTeamsRegionLoc() const {
979 const SharingMapTy *Top = getTopOfStackOrNull();
980 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
981 }
982
983 Scope *getCurScope() const {
984 const SharingMapTy *Top = getTopOfStackOrNull();
985 return Top ? Top->CurScope : nullptr;
986 }
987 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
988 SourceLocation getConstructLoc() const {
989 const SharingMapTy *Top = getTopOfStackOrNull();
990 return Top ? Top->ConstructLoc : SourceLocation();
991 }
992
993 /// Do the check specified in \a Check to all component lists and return true
994 /// if any issue is found.
995 bool checkMappableExprComponentListsForDecl(
996 const ValueDecl *VD, bool CurrentRegionOnly,
997 const llvm::function_ref<
1000 Check) const {
1001 if (isStackEmpty())
1002 return false;
1003 auto SI = begin();
1004 auto SE = end();
1005
1006 if (SI == SE)
1007 return false;
1008
1009 if (CurrentRegionOnly)
1010 SE = std::next(SI);
1011 else
1012 std::advance(SI, 1);
1013
1014 for (; SI != SE; ++SI) {
1015 auto MI = SI->MappedExprComponents.find(VD);
1016 if (MI != SI->MappedExprComponents.end())
1018 MI->second.Components)
1019 if (Check(L, MI->second.Kind))
1020 return true;
1021 }
1022 return false;
1023 }
1024
1025 /// Do the check specified in \a Check to all component lists at a given level
1026 /// and return true if any issue is found.
1027 bool checkMappableExprComponentListsForDeclAtLevel(
1028 const ValueDecl *VD, unsigned Level,
1029 const llvm::function_ref<
1032 Check) const {
1033 if (getStackSize() <= Level)
1034 return false;
1035
1036 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1037 auto MI = StackElem.MappedExprComponents.find(VD);
1038 if (MI != StackElem.MappedExprComponents.end())
1040 MI->second.Components)
1041 if (Check(L, MI->second.Kind))
1042 return true;
1043 return false;
1044 }
1045
1046 /// Create a new mappable expression component list associated with a given
1047 /// declaration and initialize it with the provided list of components.
1048 void addMappableExpressionComponents(
1049 const ValueDecl *VD,
1051 OpenMPClauseKind WhereFoundClauseKind) {
1052 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1053 // Create new entry and append the new components there.
1054 MEC.Components.resize(MEC.Components.size() + 1);
1055 MEC.Components.back().append(Components.begin(), Components.end());
1056 MEC.Kind = WhereFoundClauseKind;
1057 }
1058
1059 unsigned getNestingLevel() const {
1060 assert(!isStackEmpty());
1061 return getStackSize() - 1;
1062 }
1063 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1064 SharingMapTy *Parent = getSecondOnStackOrNull();
1065 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1066 Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1067 }
1068 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1069 getDoacrossDependClauses() const {
1070 const SharingMapTy &StackElem = getTopOfStack();
1071 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1072 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1073 return llvm::make_range(Ref.begin(), Ref.end());
1074 }
1075 return llvm::make_range(StackElem.DoacrossDepends.end(),
1076 StackElem.DoacrossDepends.end());
1077 }
1078
1079 // Store types of classes which have been explicitly mapped
1080 void addMappedClassesQualTypes(QualType QT) {
1081 SharingMapTy &StackElem = getTopOfStack();
1082 StackElem.MappedClassesQualTypes.insert(QT);
1083 }
1084
1085 // Return set of mapped classes types
1086 bool isClassPreviouslyMapped(QualType QT) const {
1087 const SharingMapTy &StackElem = getTopOfStack();
1088 return StackElem.MappedClassesQualTypes.contains(QT);
1089 }
1090
1091 /// Adds global declare target to the parent target region.
1092 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1093 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1094 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1095 "Expected declare target link global.");
1096 for (auto &Elem : *this) {
1097 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1098 Elem.DeclareTargetLinkVarDecls.push_back(E);
1099 return;
1100 }
1101 }
1102 }
1103
1104 /// Returns the list of globals with declare target link if current directive
1105 /// is target.
1106 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1107 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1108 "Expected target executable directive.");
1109 return getTopOfStack().DeclareTargetLinkVarDecls;
1110 }
1111
1112 /// Adds list of allocators expressions.
1113 void addInnerAllocatorExpr(Expr *E) {
1114 getTopOfStack().InnerUsedAllocators.push_back(E);
1115 }
1116 /// Return list of used allocators.
1117 ArrayRef<Expr *> getInnerAllocators() const {
1118 return getTopOfStack().InnerUsedAllocators;
1119 }
1120 /// Marks the declaration as implicitly firstprivate nin the task-based
1121 /// regions.
1122 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1123 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1124 }
1125 /// Checks if the decl is implicitly firstprivate in the task-based region.
1126 bool isImplicitTaskFirstprivate(Decl *D) const {
1127 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1128 }
1129
1130 /// Marks decl as used in uses_allocators clause as the allocator.
1131 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1132 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1133 }
1134 /// Checks if specified decl is used in uses allocator clause as the
1135 /// allocator.
1136 std::optional<UsesAllocatorsDeclKind>
1137 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1138 const SharingMapTy &StackElem = getTopOfStack();
1139 auto I = StackElem.UsesAllocatorsDecls.find(D);
1140 if (I == StackElem.UsesAllocatorsDecls.end())
1141 return std::nullopt;
1142 return I->getSecond();
1143 }
1144 std::optional<UsesAllocatorsDeclKind>
1145 isUsesAllocatorsDecl(const Decl *D) const {
1146 const SharingMapTy &StackElem = getTopOfStack();
1147 auto I = StackElem.UsesAllocatorsDecls.find(D);
1148 if (I == StackElem.UsesAllocatorsDecls.end())
1149 return std::nullopt;
1150 return I->getSecond();
1151 }
1152
1153 void addDeclareMapperVarRef(Expr *Ref) {
1154 SharingMapTy &StackElem = getTopOfStack();
1155 StackElem.DeclareMapperVar = Ref;
1156 }
1157 const Expr *getDeclareMapperVarRef() const {
1158 const SharingMapTy *Top = getTopOfStackOrNull();
1159 return Top ? Top->DeclareMapperVar : nullptr;
1160 }
1161
1162 /// Add a new iterator variable.
1163 void addIteratorVarDecl(VarDecl *VD) {
1164 SharingMapTy &StackElem = getTopOfStack();
1165 StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl());
1166 }
1167 /// Check if variable declaration is an iterator VarDecl.
1168 bool isIteratorVarDecl(const VarDecl *VD) const {
1169 const SharingMapTy *Top = getTopOfStackOrNull();
1170 if (!Top)
1171 return false;
1172
1173 return llvm::is_contained(Top->IteratorVarDecls, VD->getCanonicalDecl());
1174 }
1175 /// get captured field from ImplicitDefaultFirstprivateFDs
1176 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1177 const_iterator I = begin();
1178 const_iterator EndI = end();
1179 size_t StackLevel = getStackSize();
1180 for (; I != EndI; ++I) {
1181 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1182 break;
1183 StackLevel--;
1184 }
1185 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1186 if (I == EndI)
1187 return nullptr;
1188 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1189 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1190 return IFD.VD;
1191 return nullptr;
1192 }
1193 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1194 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1195 const_iterator I = begin();
1196 const_iterator EndI = end();
1197 for (; I != EndI; ++I)
1198 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1199 break;
1200 if (I == EndI)
1201 return false;
1202 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1203 if (IFD.VD == VD)
1204 return true;
1205 return false;
1206 }
1207 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1208 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1209 iterator I = begin();
1210 const_iterator EndI = end();
1211 size_t StackLevel = getStackSize();
1212 for (; I != EndI; ++I) {
1213 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1214 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1215 break;
1216 }
1217 StackLevel--;
1218 }
1219 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1220 }
1221};
1222
1223bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1224 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1225}
1226
1227bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1228 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1229 DKind == OMPD_unknown;
1230}
1231
1232} // namespace
1233
1234static const Expr *getExprAsWritten(const Expr *E) {
1235 if (const auto *FE = dyn_cast<FullExpr>(E))
1236 E = FE->getSubExpr();
1237
1238 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1239 E = MTE->getSubExpr();
1240
1241 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1242 E = Binder->getSubExpr();
1243
1244 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1245 E = ICE->getSubExprAsWritten();
1246 return E->IgnoreParens();
1247}
1248
1250 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1251}
1252
1253static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1254 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1255 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1256 D = ME->getMemberDecl();
1257
1258 D = cast<ValueDecl>(D->getCanonicalDecl());
1259 return D;
1260}
1261
1263 return const_cast<ValueDecl *>(
1264 getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1265}
1266
1267DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1268 ValueDecl *D) const {
1269 D = getCanonicalDecl(D);
1270 auto *VD = dyn_cast<VarDecl>(D);
1271 const auto *FD = dyn_cast<FieldDecl>(D);
1272 DSAVarData DVar;
1273 if (Iter == end()) {
1274 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1275 // in a region but not in construct]
1276 // File-scope or namespace-scope variables referenced in called routines
1277 // in the region are shared unless they appear in a threadprivate
1278 // directive.
1279 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1280 DVar.CKind = OMPC_shared;
1281
1282 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1283 // in a region but not in construct]
1284 // Variables with static storage duration that are declared in called
1285 // routines in the region are shared.
1286 if (VD && VD->hasGlobalStorage())
1287 DVar.CKind = OMPC_shared;
1288
1289 // Non-static data members are shared by default.
1290 if (FD)
1291 DVar.CKind = OMPC_shared;
1292
1293 return DVar;
1294 }
1295
1296 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1297 // in a Construct, C/C++, predetermined, p.1]
1298 // Variables with automatic storage duration that are declared in a scope
1299 // inside the construct are private.
1300 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1301 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1302 DVar.CKind = OMPC_private;
1303 return DVar;
1304 }
1305
1306 DVar.DKind = Iter->Directive;
1307 // Explicitly specified attributes and local variables with predetermined
1308 // attributes.
1309 if (Iter->SharingMap.count(D)) {
1310 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1311 DVar.RefExpr = Data.RefExpr.getPointer();
1312 DVar.PrivateCopy = Data.PrivateCopy;
1313 DVar.CKind = Data.Attributes;
1314 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1315 DVar.Modifier = Data.Modifier;
1316 DVar.AppliedToPointee = Data.AppliedToPointee;
1317 return DVar;
1318 }
1319
1320 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1321 // in a Construct, C/C++, implicitly determined, p.1]
1322 // In a parallel or task construct, the data-sharing attributes of these
1323 // variables are determined by the default clause, if present.
1324 switch (Iter->DefaultAttr) {
1325 case DSA_shared:
1326 DVar.CKind = OMPC_shared;
1327 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1328 return DVar;
1329 case DSA_none:
1330 return DVar;
1331 case DSA_firstprivate:
1332 if (VD && VD->getStorageDuration() == SD_Static &&
1333 VD->getDeclContext()->isFileContext()) {
1334 DVar.CKind = OMPC_unknown;
1335 } else {
1336 DVar.CKind = OMPC_firstprivate;
1337 }
1338 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1339 return DVar;
1340 case DSA_private:
1341 // each variable with static storage duration that is declared
1342 // in a namespace or global scope and referenced in the construct,
1343 // and that does not have a predetermined data-sharing attribute
1344 if (VD && VD->getStorageDuration() == SD_Static &&
1345 VD->getDeclContext()->isFileContext()) {
1346 DVar.CKind = OMPC_unknown;
1347 } else {
1348 DVar.CKind = OMPC_private;
1349 }
1350 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1351 return DVar;
1352 case DSA_unspecified:
1353 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1354 // in a Construct, implicitly determined, p.2]
1355 // In a parallel construct, if no default clause is present, these
1356 // variables are shared.
1357 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1358 if ((isOpenMPParallelDirective(DVar.DKind) &&
1359 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1360 isOpenMPTeamsDirective(DVar.DKind)) {
1361 DVar.CKind = OMPC_shared;
1362 return DVar;
1363 }
1364
1365 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1366 // in a Construct, implicitly determined, p.4]
1367 // In a task construct, if no default clause is present, a variable that in
1368 // the enclosing context is determined to be shared by all implicit tasks
1369 // bound to the current team is shared.
1370 if (isOpenMPTaskingDirective(DVar.DKind)) {
1371 DSAVarData DVarTemp;
1372 const_iterator I = Iter, E = end();
1373 do {
1374 ++I;
1375 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1376 // Referenced in a Construct, implicitly determined, p.6]
1377 // In a task construct, if no default clause is present, a variable
1378 // whose data-sharing attribute is not determined by the rules above is
1379 // firstprivate.
1380 DVarTemp = getDSA(I, D);
1381 if (DVarTemp.CKind != OMPC_shared) {
1382 DVar.RefExpr = nullptr;
1383 DVar.CKind = OMPC_firstprivate;
1384 return DVar;
1385 }
1386 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1387 DVar.CKind =
1388 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1389 return DVar;
1390 }
1391 }
1392 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1393 // in a Construct, implicitly determined, p.3]
1394 // For constructs other than task, if no default clause is present, these
1395 // variables inherit their data-sharing attributes from the enclosing
1396 // context.
1397 return getDSA(++Iter, D);
1398}
1399
1400const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1401 const Expr *NewDE) {
1402 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1403 D = getCanonicalDecl(D);
1404 SharingMapTy &StackElem = getTopOfStack();
1405 auto [It, Inserted] = StackElem.AlignedMap.try_emplace(D, NewDE);
1406 if (Inserted) {
1407 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1408 return nullptr;
1409 }
1410 assert(It->second && "Unexpected nullptr expr in the aligned map");
1411 return It->second;
1412}
1413
1414const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1415 const Expr *NewDE) {
1416 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1417 D = getCanonicalDecl(D);
1418 SharingMapTy &StackElem = getTopOfStack();
1419 auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(D, NewDE);
1420 if (Inserted) {
1421 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1422 return nullptr;
1423 }
1424 assert(It->second && "Unexpected nullptr expr in the aligned map");
1425 return It->second;
1426}
1427
1428void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1429 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1430 D = getCanonicalDecl(D);
1431 SharingMapTy &StackElem = getTopOfStack();
1432 StackElem.LCVMap.try_emplace(
1433 D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1434}
1435
1436const DSAStackTy::LCDeclInfo
1437DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1438 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1439 D = getCanonicalDecl(D);
1440 const SharingMapTy &StackElem = getTopOfStack();
1441 auto It = StackElem.LCVMap.find(D);
1442 if (It != StackElem.LCVMap.end())
1443 return It->second;
1444 return {0, nullptr};
1445}
1446
1447const DSAStackTy::LCDeclInfo
1448DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1449 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1450 D = getCanonicalDecl(D);
1451 for (unsigned I = Level + 1; I > 0; --I) {
1452 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1453 auto It = StackElem.LCVMap.find(D);
1454 if (It != StackElem.LCVMap.end())
1455 return It->second;
1456 }
1457 return {0, nullptr};
1458}
1459
1460const DSAStackTy::LCDeclInfo
1461DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1462 const SharingMapTy *Parent = getSecondOnStackOrNull();
1463 assert(Parent && "Data-sharing attributes stack is empty");
1464 D = getCanonicalDecl(D);
1465 auto It = Parent->LCVMap.find(D);
1466 if (It != Parent->LCVMap.end())
1467 return It->second;
1468 return {0, nullptr};
1469}
1470
1471const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1472 const SharingMapTy *Parent = getSecondOnStackOrNull();
1473 assert(Parent && "Data-sharing attributes stack is empty");
1474 if (Parent->LCVMap.size() < I)
1475 return nullptr;
1476 for (const auto &Pair : Parent->LCVMap)
1477 if (Pair.second.first == I)
1478 return Pair.first;
1479 return nullptr;
1480}
1481
1482void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1483 DeclRefExpr *PrivateCopy, unsigned Modifier,
1484 bool AppliedToPointee) {
1485 D = getCanonicalDecl(D);
1486 if (A == OMPC_threadprivate) {
1487 DSAInfo &Data = Threadprivates[D];
1488 Data.Attributes = A;
1489 Data.RefExpr.setPointer(E);
1490 Data.PrivateCopy = nullptr;
1491 Data.Modifier = Modifier;
1492 } else {
1493 DSAInfo &Data = getTopOfStack().SharingMap[D];
1494 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1495 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1496 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1497 (isLoopControlVariable(D).first && A == OMPC_private));
1498 Data.Modifier = Modifier;
1499 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1500 Data.RefExpr.setInt(/*IntVal=*/true);
1501 return;
1502 }
1503 const bool IsLastprivate =
1504 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1505 Data.Attributes = A;
1506 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1507 Data.PrivateCopy = PrivateCopy;
1508 Data.AppliedToPointee = AppliedToPointee;
1509 if (PrivateCopy) {
1510 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1511 Data.Modifier = Modifier;
1512 Data.Attributes = A;
1513 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1514 Data.PrivateCopy = nullptr;
1515 Data.AppliedToPointee = AppliedToPointee;
1516 }
1517 }
1518}
1519
1520/// Build a variable declaration for OpenMP loop iteration variable.
1522 StringRef Name, const AttrVec *Attrs = nullptr,
1523 DeclRefExpr *OrigRef = nullptr) {
1524 DeclContext *DC = SemaRef.CurContext;
1525 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1527 auto *Decl =
1528 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
1529 if (Attrs) {
1530 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1531 I != E; ++I)
1532 Decl->addAttr(*I);
1533 }
1534 Decl->setImplicit();
1535 if (OrigRef) {
1536 Decl->addAttr(
1537 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1538 }
1539 return Decl;
1540}
1541
1544 bool RefersToCapture = false) {
1545 D->setReferenced();
1546 D->markUsed(S.Context);
1548 SourceLocation(), D, RefersToCapture, Loc, Ty,
1549 VK_LValue);
1550}
1551
1552void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1553 BinaryOperatorKind BOK) {
1554 D = getCanonicalDecl(D);
1555 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1556 assert(
1557 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1558 "Additional reduction info may be specified only for reduction items.");
1559 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1560 assert(ReductionData.ReductionRange.isInvalid() &&
1561 (getTopOfStack().Directive == OMPD_taskgroup ||
1562 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1563 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1564 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1565 "Additional reduction info may be specified only once for reduction "
1566 "items.");
1567 ReductionData.set(BOK, SR);
1568 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1569 if (!TaskgroupReductionRef) {
1570 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1571 SemaRef.Context.VoidPtrTy, ".task_red.");
1572 TaskgroupReductionRef =
1573 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1574 }
1575}
1576
1577void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1578 const Expr *ReductionRef) {
1579 D = getCanonicalDecl(D);
1580 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1581 assert(
1582 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1583 "Additional reduction info may be specified only for reduction items.");
1584 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1585 assert(ReductionData.ReductionRange.isInvalid() &&
1586 (getTopOfStack().Directive == OMPD_taskgroup ||
1587 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1588 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1589 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1590 "Additional reduction info may be specified only once for reduction "
1591 "items.");
1592 ReductionData.set(ReductionRef, SR);
1593 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1594 if (!TaskgroupReductionRef) {
1595 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1596 SemaRef.Context.VoidPtrTy, ".task_red.");
1597 TaskgroupReductionRef =
1598 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1599 }
1600}
1601
1602const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1603 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1604 Expr *&TaskgroupDescriptor) const {
1605 D = getCanonicalDecl(D);
1606 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1607 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1608 const DSAInfo &Data = I->SharingMap.lookup(D);
1609 if (Data.Attributes != OMPC_reduction ||
1610 Data.Modifier != OMPC_REDUCTION_task)
1611 continue;
1612 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1613 if (!ReductionData.ReductionOp ||
1614 isa<const Expr *>(ReductionData.ReductionOp))
1615 return DSAVarData();
1616 SR = ReductionData.ReductionRange;
1617 BOK = cast<ReductionData::BOKPtrType>(ReductionData.ReductionOp);
1618 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1619 "expression for the descriptor is not "
1620 "set.");
1621 TaskgroupDescriptor = I->TaskgroupReductionRef;
1622 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1623 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1624 /*AppliedToPointee=*/false);
1625 }
1626 return DSAVarData();
1627}
1628
1629const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1630 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1631 Expr *&TaskgroupDescriptor) const {
1632 D = getCanonicalDecl(D);
1633 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1634 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1635 const DSAInfo &Data = I->SharingMap.lookup(D);
1636 if (Data.Attributes != OMPC_reduction ||
1637 Data.Modifier != OMPC_REDUCTION_task)
1638 continue;
1639 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1640 if (!ReductionData.ReductionOp ||
1641 !isa<const Expr *>(ReductionData.ReductionOp))
1642 return DSAVarData();
1643 SR = ReductionData.ReductionRange;
1644 ReductionRef = cast<const Expr *>(ReductionData.ReductionOp);
1645 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1646 "expression for the descriptor is not "
1647 "set.");
1648 TaskgroupDescriptor = I->TaskgroupReductionRef;
1649 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1650 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1651 /*AppliedToPointee=*/false);
1652 }
1653 return DSAVarData();
1654}
1655
1656bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1657 D = D->getCanonicalDecl();
1658 for (const_iterator E = end(); I != E; ++I) {
1659 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1660 isOpenMPTargetExecutionDirective(I->Directive)) {
1661 if (I->CurScope) {
1662 Scope *TopScope = I->CurScope->getParent();
1663 Scope *CurScope = getCurScope();
1664 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1665 CurScope = CurScope->getParent();
1666 return CurScope != TopScope;
1667 }
1668 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1669 if (I->Context == DC)
1670 return true;
1671 return false;
1672 }
1673 }
1674 return false;
1675}
1676
1678 bool AcceptIfMutable = true,
1679 bool *IsClassType = nullptr) {
1680 ASTContext &Context = SemaRef.getASTContext();
1681 Type = Type.getNonReferenceType().getCanonicalType();
1682 bool IsConstant = Type.isConstant(Context);
1683 Type = Context.getBaseElementType(Type);
1684 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1686 : nullptr;
1687 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1688 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1689 RD = CTD->getTemplatedDecl();
1690 if (IsClassType)
1691 *IsClassType = RD;
1692 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1693 RD->hasDefinition() && RD->hasMutableFields());
1694}
1695
1696static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1698 SourceLocation ELoc,
1699 bool AcceptIfMutable = true,
1700 bool ListItemNotVar = false) {
1701 ASTContext &Context = SemaRef.getASTContext();
1702 bool IsClassType;
1703 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
1704 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1705 : IsClassType ? diag::err_omp_const_not_mutable_variable
1706 : diag::err_omp_const_variable;
1707 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseName(CKind);
1708 if (!ListItemNotVar && D) {
1709 const VarDecl *VD = dyn_cast<VarDecl>(D);
1710 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1712 SemaRef.Diag(D->getLocation(),
1713 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1714 << D;
1715 }
1716 return true;
1717 }
1718 return false;
1719}
1720
1721const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1722 bool FromParent) {
1723 D = getCanonicalDecl(D);
1724 DSAVarData DVar;
1725
1726 auto *VD = dyn_cast<VarDecl>(D);
1727 auto TI = Threadprivates.find(D);
1728 if (TI != Threadprivates.end()) {
1729 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1730 DVar.CKind = OMPC_threadprivate;
1731 DVar.Modifier = TI->getSecond().Modifier;
1732 return DVar;
1733 }
1734 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1735 DVar.RefExpr = buildDeclRefExpr(
1736 SemaRef, VD, D->getType().getNonReferenceType(),
1737 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1738 DVar.CKind = OMPC_threadprivate;
1739 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1740 return DVar;
1741 }
1742 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1743 // in a Construct, C/C++, predetermined, p.1]
1744 // Variables appearing in threadprivate directives are threadprivate.
1745 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1746 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1747 SemaRef.getLangOpts().OpenMPUseTLS &&
1748 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1749 (VD && VD->getStorageClass() == SC_Register &&
1750 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1751 DVar.RefExpr = buildDeclRefExpr(
1752 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1753 DVar.CKind = OMPC_threadprivate;
1754 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1755 return DVar;
1756 }
1757 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1758 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1759 !isLoopControlVariable(D).first) {
1760 const_iterator IterTarget =
1761 std::find_if(begin(), end(), [](const SharingMapTy &Data) {
1762 return isOpenMPTargetExecutionDirective(Data.Directive);
1763 });
1764 if (IterTarget != end()) {
1765 const_iterator ParentIterTarget = IterTarget + 1;
1766 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1767 if (isOpenMPLocal(VD, Iter)) {
1768 DVar.RefExpr =
1769 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1770 D->getLocation());
1771 DVar.CKind = OMPC_threadprivate;
1772 return DVar;
1773 }
1774 }
1775 if (!isClauseParsingMode() || IterTarget != begin()) {
1776 auto DSAIter = IterTarget->SharingMap.find(D);
1777 if (DSAIter != IterTarget->SharingMap.end() &&
1778 isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1779 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1780 DVar.CKind = OMPC_threadprivate;
1781 return DVar;
1782 }
1783 const_iterator End = end();
1784 if (!SemaRef.OpenMP().isOpenMPCapturedByRef(
1785 D, std::distance(ParentIterTarget, End),
1786 /*OpenMPCaptureLevel=*/0)) {
1787 DVar.RefExpr =
1788 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1789 IterTarget->ConstructLoc);
1790 DVar.CKind = OMPC_threadprivate;
1791 return DVar;
1792 }
1793 }
1794 }
1795 }
1796
1797 if (isStackEmpty())
1798 // Not in OpenMP execution region and top scope was already checked.
1799 return DVar;
1800
1801 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1802 // in a Construct, C/C++, predetermined, p.4]
1803 // Static data members are shared.
1804 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1805 // in a Construct, C/C++, predetermined, p.7]
1806 // Variables with static storage duration that are declared in a scope
1807 // inside the construct are shared.
1808 if (VD && VD->isStaticDataMember()) {
1809 // Check for explicitly specified attributes.
1810 const_iterator I = begin();
1811 const_iterator EndI = end();
1812 if (FromParent && I != EndI)
1813 ++I;
1814 if (I != EndI) {
1815 auto It = I->SharingMap.find(D);
1816 if (It != I->SharingMap.end()) {
1817 const DSAInfo &Data = It->getSecond();
1818 DVar.RefExpr = Data.RefExpr.getPointer();
1819 DVar.PrivateCopy = Data.PrivateCopy;
1820 DVar.CKind = Data.Attributes;
1821 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1822 DVar.DKind = I->Directive;
1823 DVar.Modifier = Data.Modifier;
1824 DVar.AppliedToPointee = Data.AppliedToPointee;
1825 return DVar;
1826 }
1827 }
1828
1829 DVar.CKind = OMPC_shared;
1830 return DVar;
1831 }
1832
1833 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1834 // The predetermined shared attribute for const-qualified types having no
1835 // mutable members was removed after OpenMP 3.1.
1836 if (SemaRef.LangOpts.OpenMP <= 31) {
1837 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1838 // in a Construct, C/C++, predetermined, p.6]
1839 // Variables with const qualified type having no mutable member are
1840 // shared.
1841 if (isConstNotMutableType(SemaRef, D->getType())) {
1842 // Variables with const-qualified type having no mutable member may be
1843 // listed in a firstprivate clause, even if they are static data members.
1844 DSAVarData DVarTemp = hasInnermostDSA(
1845 D,
1846 [](OpenMPClauseKind C, bool) {
1847 return C == OMPC_firstprivate || C == OMPC_shared;
1848 },
1849 MatchesAlways, FromParent);
1850 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1851 return DVarTemp;
1852
1853 DVar.CKind = OMPC_shared;
1854 return DVar;
1855 }
1856 }
1857
1858 // Explicitly specified attributes and local variables with predetermined
1859 // attributes.
1860 const_iterator I = begin();
1861 const_iterator EndI = end();
1862 if (FromParent && I != EndI)
1863 ++I;
1864 if (I == EndI)
1865 return DVar;
1866 auto It = I->SharingMap.find(D);
1867 if (It != I->SharingMap.end()) {
1868 const DSAInfo &Data = It->getSecond();
1869 DVar.RefExpr = Data.RefExpr.getPointer();
1870 DVar.PrivateCopy = Data.PrivateCopy;
1871 DVar.CKind = Data.Attributes;
1872 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1873 DVar.DKind = I->Directive;
1874 DVar.Modifier = Data.Modifier;
1875 DVar.AppliedToPointee = Data.AppliedToPointee;
1876 }
1877
1878 return DVar;
1879}
1880
1881const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1882 bool FromParent) const {
1883 if (isStackEmpty()) {
1884 const_iterator I;
1885 return getDSA(I, D);
1886 }
1887 D = getCanonicalDecl(D);
1888 const_iterator StartI = begin();
1889 const_iterator EndI = end();
1890 if (FromParent && StartI != EndI)
1891 ++StartI;
1892 return getDSA(StartI, D);
1893}
1894
1895const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1896 unsigned Level) const {
1897 if (getStackSize() <= Level)
1898 return DSAVarData();
1899 D = getCanonicalDecl(D);
1900 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1901 return getDSA(StartI, D);
1902}
1903
1904const DSAStackTy::DSAVarData
1905DSAStackTy::hasDSA(ValueDecl *D,
1906 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1907 DefaultDataSharingAttributes)>
1908 CPred,
1909 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1910 bool FromParent) const {
1911 if (isStackEmpty())
1912 return {};
1913 D = getCanonicalDecl(D);
1914 const_iterator I = begin();
1915 const_iterator EndI = end();
1916 if (FromParent && I != EndI)
1917 ++I;
1918 for (; I != EndI; ++I) {
1919 if (!DPred(I->Directive) &&
1920 !isImplicitOrExplicitTaskingRegion(I->Directive))
1921 continue;
1922 const_iterator NewI = I;
1923 DSAVarData DVar = getDSA(NewI, D);
1924 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1925 return DVar;
1926 }
1927 return {};
1928}
1929
1930const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1931 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1932 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1933 bool FromParent) const {
1934 if (isStackEmpty())
1935 return {};
1936 D = getCanonicalDecl(D);
1937 const_iterator StartI = begin();
1938 const_iterator EndI = end();
1939 if (FromParent && StartI != EndI)
1940 ++StartI;
1941 if (StartI == EndI || !DPred(StartI->Directive))
1942 return {};
1943 const_iterator NewI = StartI;
1944 DSAVarData DVar = getDSA(NewI, D);
1945 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1946 ? DVar
1947 : DSAVarData();
1948}
1949
1950bool DSAStackTy::hasExplicitDSA(
1951 const ValueDecl *D,
1952 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1953 unsigned Level, bool NotLastprivate) const {
1954 if (getStackSize() <= Level)
1955 return false;
1956 D = getCanonicalDecl(D);
1957 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1958 auto I = StackElem.SharingMap.find(D);
1959 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1960 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1961 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1962 return true;
1963 // Check predetermined rules for the loop control variables.
1964 auto LI = StackElem.LCVMap.find(D);
1965 if (LI != StackElem.LCVMap.end())
1966 return CPred(OMPC_private, /*AppliedToPointee=*/false);
1967 return false;
1968}
1969
1970bool DSAStackTy::hasExplicitDirective(
1971 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1972 unsigned Level) const {
1973 if (getStackSize() <= Level)
1974 return false;
1975 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1976 return DPred(StackElem.Directive);
1977}
1978
1979bool DSAStackTy::hasDirective(
1980 const llvm::function_ref<bool(OpenMPDirectiveKind,
1982 DPred,
1983 bool FromParent) const {
1984 // We look only in the enclosing region.
1985 size_t Skip = FromParent ? 2 : 1;
1986 for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
1987 I != E; ++I) {
1988 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
1989 return true;
1990 }
1991 return false;
1992}
1993
1994void SemaOpenMP::InitDataSharingAttributesStack() {
1995 VarDataSharingAttributesStack = new DSAStackTy(SemaRef);
1996}
1997
1998#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
1999
2000void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2001
2002void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2003 DSAStack->popFunction(OldFSI);
2004}
2005
2007 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2008 "Expected OpenMP device compilation.");
2010}
2011
2012namespace {
2013/// Status of the function emission on the host/device.
2014enum class FunctionEmissionStatus {
2015 Emitted,
2016 Discarded,
2017 Unknown,
2018};
2019} // anonymous namespace
2020
2023 const FunctionDecl *FD) {
2024 assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&
2025 "Expected OpenMP device compilation.");
2026
2027 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2028 if (FD) {
2030 switch (FES) {
2032 Kind = SemaDiagnosticBuilder::K_Immediate;
2033 break;
2035 // TODO: We should always delay diagnostics here in case a target
2036 // region is in a function we do not emit. However, as the
2037 // current diagnostics are associated with the function containing
2038 // the target region and we do not emit that one, we would miss out
2039 // on diagnostics for the target region itself. We need to anchor
2040 // the diagnostics with the new generated function *or* ensure we
2041 // emit diagnostics associated with the surrounding function.
2043 ? SemaDiagnosticBuilder::K_Deferred
2044 : SemaDiagnosticBuilder::K_Immediate;
2045 break;
2048 Kind = SemaDiagnosticBuilder::K_Nop;
2049 break;
2051 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2052 break;
2053 }
2054 }
2055
2056 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2057}
2058
2061 const FunctionDecl *FD) {
2062 assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice &&
2063 "Expected OpenMP host compilation.");
2064
2065 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2066 if (FD) {
2068 switch (FES) {
2070 Kind = SemaDiagnosticBuilder::K_Immediate;
2071 break;
2073 Kind = SemaDiagnosticBuilder::K_Deferred;
2074 break;
2078 Kind = SemaDiagnosticBuilder::K_Nop;
2079 break;
2080 }
2081 }
2082
2083 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2084}
2085
2088 if (LO.OpenMP <= 45) {
2090 return OMPC_DEFAULTMAP_scalar;
2091 return OMPC_DEFAULTMAP_aggregate;
2092 }
2094 return OMPC_DEFAULTMAP_pointer;
2096 return OMPC_DEFAULTMAP_scalar;
2097 return OMPC_DEFAULTMAP_aggregate;
2098}
2099
2101 unsigned OpenMPCaptureLevel) const {
2102 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2103
2104 ASTContext &Ctx = getASTContext();
2105 bool IsByRef = true;
2106
2107 // Find the directive that is associated with the provided scope.
2108 D = cast<ValueDecl>(D->getCanonicalDecl());
2109 QualType Ty = D->getType();
2110
2111 bool IsVariableUsedInMapClause = false;
2112 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2113 // This table summarizes how a given variable should be passed to the device
2114 // given its type and the clauses where it appears. This table is based on
2115 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2116 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2117 //
2118 // =========================================================================
2119 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2120 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2121 // =========================================================================
2122 // | scl | | | | - | | bycopy|
2123 // | scl | | - | x | - | - | bycopy|
2124 // | scl | | x | - | - | - | null |
2125 // | scl | x | | | - | | byref |
2126 // | scl | x | - | x | - | - | bycopy|
2127 // | scl | x | x | - | - | - | null |
2128 // | scl | | - | - | - | x | byref |
2129 // | scl | x | - | - | - | x | byref |
2130 //
2131 // | agg | n.a. | | | - | | byref |
2132 // | agg | n.a. | - | x | - | - | byref |
2133 // | agg | n.a. | x | - | - | - | null |
2134 // | agg | n.a. | - | - | - | x | byref |
2135 // | agg | n.a. | - | - | - | x[] | byref |
2136 //
2137 // | ptr | n.a. | | | - | | bycopy|
2138 // | ptr | n.a. | - | x | - | - | bycopy|
2139 // | ptr | n.a. | x | - | - | - | null |
2140 // | ptr | n.a. | - | - | - | x | byref |
2141 // | ptr | n.a. | - | - | - | x[] | bycopy|
2142 // | ptr | n.a. | - | - | x | | bycopy|
2143 // | ptr | n.a. | - | - | x | x | bycopy|
2144 // | ptr | n.a. | - | - | x | x[] | bycopy|
2145 // =========================================================================
2146 // Legend:
2147 // scl - scalar
2148 // ptr - pointer
2149 // agg - aggregate
2150 // x - applies
2151 // - - invalid in this combination
2152 // [] - mapped with an array section
2153 // byref - should be mapped by reference
2154 // byval - should be mapped by value
2155 // null - initialize a local variable to null on the device
2156 //
2157 // Observations:
2158 // - All scalar declarations that show up in a map clause have to be passed
2159 // by reference, because they may have been mapped in the enclosing data
2160 // environment.
2161 // - If the scalar value does not fit the size of uintptr, it has to be
2162 // passed by reference, regardless the result in the table above.
2163 // - For pointers mapped by value that have either an implicit map or an
2164 // array section, the runtime library may pass the NULL value to the
2165 // device instead of the value passed to it by the compiler.
2166
2167 if (Ty->isReferenceType())
2168 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2169
2170 // Locate map clauses and see if the variable being captured is referred to
2171 // in any of those clauses. Here we only care about variables, not fields,
2172 // because fields are part of aggregates.
2173 bool IsVariableAssociatedWithSection = false;
2174
2175 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2176 D, Level,
2177 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2179 MapExprComponents,
2180 OpenMPClauseKind WhereFoundClauseKind) {
2181 // Both map and has_device_addr clauses information influences how a
2182 // variable is captured. E.g. is_device_ptr does not require changing
2183 // the default behavior.
2184 if (WhereFoundClauseKind != OMPC_map &&
2185 WhereFoundClauseKind != OMPC_has_device_addr)
2186 return false;
2187
2188 auto EI = MapExprComponents.rbegin();
2189 auto EE = MapExprComponents.rend();
2190
2191 assert(EI != EE && "Invalid map expression!");
2192
2193 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2194 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2195
2196 ++EI;
2197 if (EI == EE)
2198 return false;
2199 auto Last = std::prev(EE);
2200 const auto *UO =
2201 dyn_cast<UnaryOperator>(Last->getAssociatedExpression());
2202 if ((UO && UO->getOpcode() == UO_Deref) ||
2203 isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) ||
2204 isa<ArraySectionExpr>(Last->getAssociatedExpression()) ||
2205 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2206 isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) {
2207 IsVariableAssociatedWithSection = true;
2208 // There is nothing more we need to know about this variable.
2209 return true;
2210 }
2211
2212 // Keep looking for more map info.
2213 return false;
2214 });
2215
2216 if (IsVariableUsedInMapClause) {
2217 // If variable is identified in a map clause it is always captured by
2218 // reference except if it is a pointer that is dereferenced somehow.
2219 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2220 } else {
2221 // By default, all the data that has a scalar type is mapped by copy
2222 // (except for reduction variables).
2223 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2224 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2225 !Ty->isAnyPointerType()) ||
2226 !Ty->isScalarType() ||
2227 DSAStack->isDefaultmapCapturedByRef(
2229 DSAStack->hasExplicitDSA(
2230 D,
2231 [](OpenMPClauseKind K, bool AppliedToPointee) {
2232 return K == OMPC_reduction && !AppliedToPointee;
2233 },
2234 Level);
2235 }
2236 }
2237
2238 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2239 IsByRef =
2240 ((IsVariableUsedInMapClause &&
2241 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2242 OMPD_target) ||
2243 !(DSAStack->hasExplicitDSA(
2244 D,
2245 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2246 return K == OMPC_firstprivate ||
2247 (K == OMPC_reduction && AppliedToPointee);
2248 },
2249 Level, /*NotLastprivate=*/true) ||
2250 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2251 // If the variable is artificial and must be captured by value - try to
2252 // capture by value.
2253 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2254 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2255 // If the variable is implicitly firstprivate and scalar - capture by
2256 // copy
2257 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2258 DSAStack->getDefaultDSA() == DSA_private) &&
2259 !DSAStack->hasExplicitDSA(
2260 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2261 Level) &&
2262 !DSAStack->isLoopControlVariable(D, Level).first);
2263 }
2264
2265 // When passing data by copy, we need to make sure it fits the uintptr size
2266 // and alignment, because the runtime library only deals with uintptr types.
2267 // If it does not fit the uintptr size, we need to pass the data by reference
2268 // instead.
2269 if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) >
2271 Ctx.getAlignOfGlobalVarInChars(Ty, dyn_cast<VarDecl>(D)) >
2272 Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2273 IsByRef = true;
2274 }
2275
2276 return IsByRef;
2277}
2278
2279unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2280 assert(getLangOpts().OpenMP);
2281 return DSAStack->getNestingLevel();
2282}
2283
2285 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2286 DSAStack->isUntiedRegion();
2287}
2288
2290 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2291 !DSAStack->isClauseParsingMode()) ||
2292 DSAStack->hasDirective(
2294 SourceLocation) -> bool {
2296 },
2297 false);
2298}
2299
2301 // Only rebuild for Field.
2302 if (!dyn_cast<FieldDecl>(D))
2303 return false;
2304 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2305 D,
2306 [](OpenMPClauseKind C, bool AppliedToPointee,
2307 DefaultDataSharingAttributes DefaultAttr) {
2308 return isOpenMPPrivate(C) && !AppliedToPointee &&
2309 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2310 },
2311 [](OpenMPDirectiveKind) { return true; },
2312 DSAStack->isClauseParsingMode());
2313 if (DVarPrivate.CKind != OMPC_unknown)
2314 return true;
2315 return false;
2316}
2317
2319 Expr *CaptureExpr, bool WithInit,
2320 DeclContext *CurContext,
2321 bool AsExpression);
2322
2324 unsigned StopAt) {
2325 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2326 D = getCanonicalDecl(D);
2327
2328 auto *VD = dyn_cast<VarDecl>(D);
2329 // Do not capture constexpr variables.
2330 if (VD && VD->isConstexpr())
2331 return nullptr;
2332
2333 // If we want to determine whether the variable should be captured from the
2334 // perspective of the current capturing scope, and we've already left all the
2335 // capturing scopes of the top directive on the stack, check from the
2336 // perspective of its parent directive (if any) instead.
2337 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2338 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2339
2340 // If we are attempting to capture a global variable in a directive with
2341 // 'target' we return true so that this global is also mapped to the device.
2342 //
2343 if (VD && !VD->hasLocalStorage() &&
2345 SemaRef.getCurLambda())) {
2347 DSAStackTy::DSAVarData DVarTop =
2348 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2349 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2350 return VD;
2351 // If the declaration is enclosed in a 'declare target' directive,
2352 // then it should not be captured.
2353 //
2354 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2355 return nullptr;
2356 CapturedRegionScopeInfo *CSI = nullptr;
2357 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2358 llvm::reverse(SemaRef.FunctionScopes),
2359 CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2360 : 0)) {
2361 if (!isa<CapturingScopeInfo>(FSI))
2362 return nullptr;
2363 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2364 if (RSI->CapRegionKind == CR_OpenMP) {
2365 CSI = RSI;
2366 break;
2367 }
2368 }
2369 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2372 DSAStack->getDirective(CSI->OpenMPLevel));
2373 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2374 return VD;
2375 }
2377 // Try to mark variable as declare target if it is used in capturing
2378 // regions.
2379 if (getLangOpts().OpenMP <= 45 &&
2380 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2382 return nullptr;
2383 }
2384 }
2385
2386 if (CheckScopeInfo) {
2387 bool OpenMPFound = false;
2388 for (unsigned I = StopAt + 1; I > 0; --I) {
2390 if (!isa<CapturingScopeInfo>(FSI))
2391 return nullptr;
2392 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2393 if (RSI->CapRegionKind == CR_OpenMP) {
2394 OpenMPFound = true;
2395 break;
2396 }
2397 }
2398 if (!OpenMPFound)
2399 return nullptr;
2400 }
2401
2402 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2403 (!DSAStack->isClauseParsingMode() ||
2404 DSAStack->getParentDirective() != OMPD_unknown)) {
2405 auto &&Info = DSAStack->isLoopControlVariable(D);
2406 if (Info.first ||
2407 (VD && VD->hasLocalStorage() &&
2408 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2409 (VD && DSAStack->isForceVarCapturing()))
2410 return VD ? VD : Info.second;
2411 DSAStackTy::DSAVarData DVarTop =
2412 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2413 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2414 (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee))
2415 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2416 // Threadprivate variables must not be captured.
2417 if (isOpenMPThreadPrivate(DVarTop.CKind))
2418 return nullptr;
2419 // The variable is not private or it is the variable in the directive with
2420 // default(none) clause and not used in any clause.
2421 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2422 D,
2423 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2424 return isOpenMPPrivate(C) && !AppliedToPointee;
2425 },
2426 [](OpenMPDirectiveKind) { return true; },
2427 DSAStack->isClauseParsingMode());
2428 // Global shared must not be captured.
2429 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2430 ((DSAStack->getDefaultDSA() != DSA_none &&
2431 DSAStack->getDefaultDSA() != DSA_private &&
2432 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2433 DVarTop.CKind == OMPC_shared))
2434 return nullptr;
2435 auto *FD = dyn_cast<FieldDecl>(D);
2436 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2437 !DVarPrivate.PrivateCopy) {
2438 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2439 D,
2440 [](OpenMPClauseKind C, bool AppliedToPointee,
2441 DefaultDataSharingAttributes DefaultAttr) {
2442 return isOpenMPPrivate(C) && !AppliedToPointee &&
2443 (DefaultAttr == DSA_firstprivate ||
2444 DefaultAttr == DSA_private);
2445 },
2446 [](OpenMPDirectiveKind) { return true; },
2447 DSAStack->isClauseParsingMode());
2448 if (DVarPrivate.CKind == OMPC_unknown)
2449 return nullptr;
2450
2451 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2452 if (VD)
2453 return VD;
2455 return nullptr;
2458 /*IsImplicit=*/true);
2459 const CXXScopeSpec CS = CXXScopeSpec();
2461 ThisExpr, /*IsArrow=*/true, SourceLocation(),
2464 /*HadMultipleCandidates=*/false, DeclarationNameInfo(), FD->getType(),
2467 SemaRef, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2468 SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2469 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2471 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2472 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2473 return VD;
2474 }
2475 if (DVarPrivate.CKind != OMPC_unknown ||
2476 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2477 DSAStack->getDefaultDSA() == DSA_private ||
2478 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2479 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2480 }
2481 return nullptr;
2482}
2483
2484void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2485 unsigned Level) const {
2486 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2487}
2488
2490 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2491 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2492 DSAStack->loopInit();
2493}
2494
2496 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2497 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2498 DSAStack->resetPossibleLoopCounter();
2499 DSAStack->loopStart();
2500 }
2501}
2502
2504 unsigned CapLevel) const {
2505 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2506 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2507 (!DSAStack->isClauseParsingMode() ||
2508 DSAStack->getParentDirective() != OMPD_unknown)) {
2509 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2510 D,
2511 [](OpenMPClauseKind C, bool AppliedToPointee,
2512 DefaultDataSharingAttributes DefaultAttr) {
2513 return isOpenMPPrivate(C) && !AppliedToPointee &&
2514 DefaultAttr == DSA_private;
2515 },
2516 [](OpenMPDirectiveKind) { return true; },
2517 DSAStack->isClauseParsingMode());
2518 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2519 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2520 !DSAStack->isLoopControlVariable(D).first)
2521 return OMPC_private;
2522 }
2523 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2524 bool IsTriviallyCopyable =
2525 D->getType().getNonReferenceType().isTriviallyCopyableType(
2526 getASTContext()) &&
2527 !D->getType()
2528 .getNonReferenceType()
2529 .getCanonicalType()
2530 ->getAsCXXRecordDecl();
2531 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2533 getOpenMPCaptureRegions(CaptureRegions, DKind);
2534 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2535 (IsTriviallyCopyable ||
2536 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2537 if (DSAStack->hasExplicitDSA(
2538 D,
2539 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2540 Level, /*NotLastprivate=*/true))
2541 return OMPC_firstprivate;
2542 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2543 if (DVar.CKind != OMPC_shared &&
2544 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2545 DSAStack->addImplicitTaskFirstprivate(Level, D);
2546 return OMPC_firstprivate;
2547 }
2548 }
2549 }
2550 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2551 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2552 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2553 DSAStack->resetPossibleLoopCounter(D);
2554 DSAStack->loopStart();
2555 return OMPC_private;
2556 }
2557 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2558 DSAStack->isLoopControlVariable(D).first) &&
2559 !DSAStack->hasExplicitDSA(
2560 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2561 Level) &&
2562 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2563 return OMPC_private;
2564 }
2565 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2566 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2567 DSAStack->isForceVarCapturing() &&
2568 !DSAStack->hasExplicitDSA(
2569 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2570 Level))
2571 return OMPC_private;
2572 }
2573 // User-defined allocators are private since they must be defined in the
2574 // context of target region.
2575 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2576 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2577 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2578 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2579 return OMPC_private;
2580 return (DSAStack->hasExplicitDSA(
2581 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2582 Level) ||
2583 (DSAStack->isClauseParsingMode() &&
2584 DSAStack->getClauseParsingMode() == OMPC_private) ||
2585 // Consider taskgroup reduction descriptor variable a private
2586 // to avoid possible capture in the region.
2587 (DSAStack->hasExplicitDirective(
2588 [](OpenMPDirectiveKind K) {
2589 return K == OMPD_taskgroup ||
2590 ((isOpenMPParallelDirective(K) ||
2591 isOpenMPWorksharingDirective(K)) &&
2592 !isOpenMPSimdDirective(K));
2593 },
2594 Level) &&
2595 DSAStack->isTaskgroupReductionRef(D, Level)))
2596 ? OMPC_private
2597 : OMPC_unknown;
2598}
2599
2601 unsigned Level) {
2602 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2603 D = getCanonicalDecl(D);
2604 OpenMPClauseKind OMPC = OMPC_unknown;
2605 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2606 const unsigned NewLevel = I - 1;
2607 if (DSAStack->hasExplicitDSA(
2608 D,
2609 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2610 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2611 OMPC = K;
2612 return true;
2613 }
2614 return false;
2615 },
2616 NewLevel))
2617 break;
2618 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2619 D, NewLevel,
2621 OpenMPClauseKind) { return true; })) {
2622 OMPC = OMPC_map;
2623 break;
2624 }
2625 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2626 NewLevel)) {
2627 OMPC = OMPC_map;
2628 if (DSAStack->mustBeFirstprivateAtLevel(
2630 OMPC = OMPC_firstprivate;
2631 break;
2632 }
2633 }
2634 if (OMPC != OMPC_unknown)
2635 FD->addAttr(
2636 OMPCaptureKindAttr::CreateImplicit(getASTContext(), unsigned(OMPC)));
2637}
2638
2640 unsigned CaptureLevel) const {
2641 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2642 // Return true if the current level is no longer enclosed in a target region.
2643
2645 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2646 const auto *VD = dyn_cast<VarDecl>(D);
2647 return VD && !VD->hasLocalStorage() &&
2648 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2649 Level) &&
2650 Regions[CaptureLevel] != OMPD_task;
2651}
2652
2654 unsigned CaptureLevel) const {
2655 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2656 // Return true if the current level is no longer enclosed in a target region.
2657
2658 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2659 if (!VD->hasLocalStorage()) {
2661 return true;
2662 DSAStackTy::DSAVarData TopDVar =
2663 DSAStack->getTopDSA(D, /*FromParent=*/false);
2664 unsigned NumLevels =
2665 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2666 if (Level == 0)
2667 // non-file scope static variable with default(firstprivate)
2668 // should be global captured.
2669 return (NumLevels == CaptureLevel + 1 &&
2670 (TopDVar.CKind != OMPC_shared ||
2671 DSAStack->getDefaultDSA() == DSA_firstprivate));
2672 do {
2673 --Level;
2674 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2675 if (DVar.CKind != OMPC_shared)
2676 return true;
2677 } while (Level > 0);
2678 }
2679 }
2680 return true;
2681}
2682
2683void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2684
2686 OMPTraitInfo &TI) {
2687 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2688}
2689
2692 "Not in OpenMP declare variant scope!");
2693
2694 OMPDeclareVariantScopes.pop_back();
2695}
2696
2698 const FunctionDecl *Callee,
2700 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2701 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2702 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2703 // Ignore host functions during device analysis.
2704 if (getLangOpts().OpenMPIsTargetDevice &&
2705 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2706 return;
2707 // Ignore nohost functions during host analysis.
2708 if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2709 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2710 return;
2711 const FunctionDecl *FD = Callee->getMostRecentDecl();
2712 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2713 if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2714 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2715 // Diagnose host function called during device codegen.
2716 StringRef HostDevTy =
2717 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2718 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2719 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2720 diag::note_omp_marked_device_type_here)
2721 << HostDevTy;
2722 return;
2723 }
2724 if (!getLangOpts().OpenMPIsTargetDevice &&
2725 !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2726 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2727 // In OpenMP 5.2 or later, if the function has a host variant then allow
2728 // that to be called instead
2729 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2730 for (OMPDeclareVariantAttr *A :
2731 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2732 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2733 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2734 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2735 OMPDeclareTargetDeclAttr::getDeviceType(
2736 VariantFD->getMostRecentDecl());
2737 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2738 return true;
2739 }
2740 return false;
2741 };
2742 if (getLangOpts().OpenMP >= 52 &&
2743 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2744 return;
2745 // Diagnose nohost function called during host codegen.
2746 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2747 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2748 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2749 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2750 diag::note_omp_marked_device_type_here)
2751 << NoHostDevTy;
2752 }
2753}
2754
2756 const DeclarationNameInfo &DirName,
2757 Scope *CurScope, SourceLocation Loc) {
2758 DSAStack->push(DKind, DirName, CurScope, Loc);
2761}
2762
2764 DSAStack->setClauseParsingMode(K);
2765}
2766
2768 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2770}
2771
2772static std::pair<ValueDecl *, bool>
2773getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2774 SourceRange &ERange, bool AllowArraySection = false,
2775 StringRef DiagType = "");
2776
2777/// Check consistency of the reduction clauses.
2778static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2779 ArrayRef<OMPClause *> Clauses) {
2780 bool InscanFound = false;
2781 SourceLocation InscanLoc;
2782 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2783 // A reduction clause without the inscan reduction-modifier may not appear on
2784 // a construct on which a reduction clause with the inscan reduction-modifier
2785 // appears.
2786 for (OMPClause *C : Clauses) {
2787 if (C->getClauseKind() != OMPC_reduction)
2788 continue;
2789 auto *RC = cast<OMPReductionClause>(C);
2790 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2791 InscanFound = true;
2792 InscanLoc = RC->getModifierLoc();
2793 continue;
2794 }
2795 if (RC->getModifier() == OMPC_REDUCTION_task) {
2796 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2797 // A reduction clause with the task reduction-modifier may only appear on
2798 // a parallel construct, a worksharing construct or a combined or
2799 // composite construct for which any of the aforementioned constructs is a
2800 // constituent construct and simd or loop are not constituent constructs.
2801 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2802 if (!(isOpenMPParallelDirective(CurDir) ||
2804 isOpenMPSimdDirective(CurDir))
2805 S.Diag(RC->getModifierLoc(),
2806 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2807 continue;
2808 }
2809 }
2810 if (InscanFound) {
2811 for (OMPClause *C : Clauses) {
2812 if (C->getClauseKind() != OMPC_reduction)
2813 continue;
2814 auto *RC = cast<OMPReductionClause>(C);
2815 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2816 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2817 ? RC->getBeginLoc()
2818 : RC->getModifierLoc(),
2819 diag::err_omp_inscan_reduction_expected);
2820 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2821 continue;
2822 }
2823 for (Expr *Ref : RC->varlist()) {
2824 assert(Ref && "NULL expr in OpenMP nontemporal clause.");
2825 SourceLocation ELoc;
2826 SourceRange ERange;
2827 Expr *SimpleRefExpr = Ref;
2828 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2829 /*AllowArraySection=*/true);
2830 ValueDecl *D = Res.first;
2831 if (!D)
2832 continue;
2833 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2834 S.Diag(Ref->getExprLoc(),
2835 diag::err_omp_reduction_not_inclusive_exclusive)
2836 << Ref->getSourceRange();
2837 }
2838 }
2839 }
2840 }
2841}
2842
2843static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2844 ArrayRef<OMPClause *> Clauses);
2845static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2846 bool WithInit);
2847
2848static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2849 const ValueDecl *D,
2850 const DSAStackTy::DSAVarData &DVar,
2851 bool IsLoopIterVar = false);
2852
2854 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2855 // A variable of class type (or array thereof) that appears in a lastprivate
2856 // clause requires an accessible, unambiguous default constructor for the
2857 // class type, unless the list item is also specified in a firstprivate
2858 // clause.
2859
2860 auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) {
2861 SmallVector<Expr *, 8> PrivateCopies;
2862 for (Expr *DE : Clause->varlist()) {
2863 if (DE->isValueDependent() || DE->isTypeDependent()) {
2864 PrivateCopies.push_back(nullptr);
2865 continue;
2866 }
2867 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2868 auto *VD = cast<VarDecl>(DRE->getDecl());
2870 const DSAStackTy::DSAVarData DVar =
2871 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2872 if (DVar.CKind != OMPC_lastprivate) {
2873 // The variable is also a firstprivate, so initialization sequence
2874 // for private copy is generated already.
2875 PrivateCopies.push_back(nullptr);
2876 continue;
2877 }
2878 // Generate helper private variable and initialize it with the
2879 // default value. The address of the original variable is replaced
2880 // by the address of the new private variable in CodeGen. This new
2881 // variable is not added to IdResolver, so the code in the OpenMP
2882 // region uses original variable for proper diagnostics.
2883 VarDecl *VDPrivate = buildVarDecl(
2884 SemaRef, DE->getExprLoc(), Type.getUnqualifiedType(), VD->getName(),
2885 VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2887 if (VDPrivate->isInvalidDecl()) {
2888 PrivateCopies.push_back(nullptr);
2889 continue;
2890 }
2891 PrivateCopies.push_back(buildDeclRefExpr(
2892 SemaRef, VDPrivate, DE->getType(), DE->getExprLoc()));
2893 }
2894 Clause->setPrivateCopies(PrivateCopies);
2895 };
2896
2897 auto FinalizeNontemporal = [&](OMPNontemporalClause *Clause) {
2898 // Finalize nontemporal clause by handling private copies, if any.
2899 SmallVector<Expr *, 8> PrivateRefs;
2900 for (Expr *RefExpr : Clause->varlist()) {
2901 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2902 SourceLocation ELoc;
2903 SourceRange ERange;
2904 Expr *SimpleRefExpr = RefExpr;
2905 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
2906 if (Res.second)
2907 // It will be analyzed later.
2908 PrivateRefs.push_back(RefExpr);
2909 ValueDecl *D = Res.first;
2910 if (!D)
2911 continue;
2912
2913 const DSAStackTy::DSAVarData DVar =
2914 DSAStack->getTopDSA(D, /*FromParent=*/false);
2915 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2916 : SimpleRefExpr);
2917 }
2918 Clause->setPrivateRefs(PrivateRefs);
2919 };
2920
2921 auto FinalizeAllocators = [&](OMPUsesAllocatorsClause *Clause) {
2922 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2923 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2924 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
2925 if (!DRE)
2926 continue;
2927 ValueDecl *VD = DRE->getDecl();
2928 if (!VD || !isa<VarDecl>(VD))
2929 continue;
2930 DSAStackTy::DSAVarData DVar =
2931 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2932 // OpenMP [2.12.5, target Construct]
2933 // Memory allocators that appear in a uses_allocators clause cannot
2934 // appear in other data-sharing attribute clauses or data-mapping
2935 // attribute clauses in the same construct.
2936 Expr *MapExpr = nullptr;
2937 if (DVar.RefExpr ||
2938 DSAStack->checkMappableExprComponentListsForDecl(
2939 VD, /*CurrentRegionOnly=*/true,
2940 [VD, &MapExpr](
2942 MapExprComponents,
2944 auto MI = MapExprComponents.rbegin();
2945 auto ME = MapExprComponents.rend();
2946 if (MI != ME &&
2947 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2948 VD->getCanonicalDecl()) {
2949 MapExpr = MI->getAssociatedExpression();
2950 return true;
2951 }
2952 return false;
2953 })) {
2954 Diag(D.Allocator->getExprLoc(), diag::err_omp_allocator_used_in_clauses)
2955 << D.Allocator->getSourceRange();
2956 if (DVar.RefExpr)
2958 else
2959 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2960 << MapExpr->getSourceRange();
2961 }
2962 }
2963 };
2964
2965 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2966 for (OMPClause *C : D->clauses()) {
2967 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
2968 FinalizeLastprivate(Clause);
2969 } else if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
2970 FinalizeNontemporal(Clause);
2971 } else if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
2972 FinalizeAllocators(Clause);
2973 }
2974 }
2975 // Check allocate clauses.
2976 if (!SemaRef.CurContext->isDependentContext())
2977 checkAllocateClauses(SemaRef, DSAStack, D->clauses());
2978 checkReductionClauses(SemaRef, DSAStack, D->clauses());
2979 }
2980
2981 DSAStack->pop();
2984}
2985
2987 Expr *NumIterations, Sema &SemaRef,
2988 Scope *S, DSAStackTy *Stack);
2989
2990static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
2992 DSAStackTy *Stack) {
2993 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
2994 "loop exprs were not built");
2995
2996 if (SemaRef.CurContext->isDependentContext())
2997 return false;
2998
2999 // Finalize the clauses that need pre-built expressions for CodeGen.
3000 for (OMPClause *C : Clauses) {
3001 auto *LC = dyn_cast<OMPLinearClause>(C);
3002 if (!LC)
3003 continue;
3004 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
3005 B.NumIterations, SemaRef,
3006 SemaRef.getCurScope(), Stack))
3007 return true;
3008 }
3009
3010 return false;
3011}
3012
3013namespace {
3014
3015class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3016private:
3017 Sema &SemaRef;
3018
3019public:
3020 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3021 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3022 NamedDecl *ND = Candidate.getCorrectionDecl();
3023 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3024 return VD->hasGlobalStorage() &&
3025 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3026 SemaRef.getCurScope());
3027 }
3028 return false;
3029 }
3030
3031 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3032 return std::make_unique<VarDeclFilterCCC>(*this);
3033 }
3034};
3035
3036class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3037private:
3038 Sema &SemaRef;
3039
3040public:
3041 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3042 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3043 NamedDecl *ND = Candidate.getCorrectionDecl();
3044 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3045 isa<FunctionDecl>(ND))) {
3046 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3047 SemaRef.getCurScope());
3048 }
3049 return false;
3050 }
3051
3052 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3053 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3054 }
3055};
3056
3057} // namespace
3058
3060 CXXScopeSpec &ScopeSpec,
3061 const DeclarationNameInfo &Id,
3062 OpenMPDirectiveKind Kind) {
3063 ASTContext &Context = getASTContext();
3065 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
3066 /*ObjectType=*/QualType(),
3067 /*AllowBuiltinCreation=*/true);
3068
3069 if (Lookup.isAmbiguous())
3070 return ExprError();
3071
3072 VarDecl *VD;
3073 if (!Lookup.isSingleResult()) {
3074 VarDeclFilterCCC CCC(SemaRef);
3075 if (TypoCorrection Corrected =
3076 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
3079 Corrected,
3080 SemaRef.PDiag(Lookup.empty() ? diag::err_undeclared_var_use_suggest
3081 : diag::err_omp_expected_var_arg_suggest)
3082 << Id.getName());
3083 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3084 } else {
3085 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3086 : diag::err_omp_expected_var_arg)
3087 << Id.getName();
3088 return ExprError();
3089 }
3090 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3091 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3092 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3093 return ExprError();
3094 }
3095 Lookup.suppressDiagnostics();
3096
3097 // OpenMP [2.9.2, Syntax, C/C++]
3098 // Variables must be file-scope, namespace-scope, or static block-scope.
3099 if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
3100 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3101 << getOpenMPDirectiveName(Kind) << !VD->isStaticLocal();
3102 bool IsDecl =
3104 Diag(VD->getLocation(),
3105 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3106 << VD;
3107 return ExprError();
3108 }
3109
3110 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3111 NamedDecl *ND = CanonicalVD;
3112 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3113 // A threadprivate directive for file-scope variables must appear outside
3114 // any definition or declaration.
3115 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3117 Diag(Id.getLoc(), diag::err_omp_var_scope)
3118 << getOpenMPDirectiveName(Kind) << VD;
3119 bool IsDecl =
3121 Diag(VD->getLocation(),
3122 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3123 << VD;
3124 return ExprError();
3125 }
3126 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3127 // A threadprivate directive for static class member variables must appear
3128 // in the class definition, in the same scope in which the member
3129 // variables are declared.
3130 if (CanonicalVD->isStaticDataMember() &&
3131 !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) {
3132 Diag(Id.getLoc(), diag::err_omp_var_scope)
3133 << getOpenMPDirectiveName(Kind) << VD;
3134 bool IsDecl =
3136 Diag(VD->getLocation(),
3137 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3138 << VD;
3139 return ExprError();
3140 }
3141 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3142 // A threadprivate directive for namespace-scope variables must appear
3143 // outside any definition or declaration other than the namespace
3144 // definition itself.
3145 if (CanonicalVD->getDeclContext()->isNamespace() &&
3148 CanonicalVD->getDeclContext()))) {
3149 Diag(Id.getLoc(), diag::err_omp_var_scope)
3150 << getOpenMPDirectiveName(Kind) << VD;
3151 bool IsDecl =
3153 Diag(VD->getLocation(),
3154 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3155 << VD;
3156 return ExprError();
3157 }
3158 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3159 // A threadprivate directive for static block-scope variables must appear
3160 // in the scope of the variable and not in a nested scope.
3161 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3163 Diag(Id.getLoc(), diag::err_omp_var_scope)
3164 << getOpenMPDirectiveName(Kind) << VD;
3165 bool IsDecl =
3167 Diag(VD->getLocation(),
3168 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3169 << VD;
3170 return ExprError();
3171 }
3172
3173 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3174 // A threadprivate directive must lexically precede all references to any
3175 // of the variables in its list.
3176 if (Kind == OMPD_threadprivate && VD->isUsed() &&
3177 !DSAStack->isThreadPrivate(VD)) {
3178 Diag(Id.getLoc(), diag::err_omp_var_used)
3179 << getOpenMPDirectiveName(Kind) << VD;
3180 return ExprError();
3181 }
3182
3183 QualType ExprType = VD->getType().getNonReferenceType();
3185 SourceLocation(), VD,
3186 /*RefersToEnclosingVariableOrCapture=*/false,
3187 Id.getLoc(), ExprType, VK_LValue);
3188}
3189
3192 ArrayRef<Expr *> VarList) {
3196 }
3197 return nullptr;
3198}
3199
3200namespace {
3201class LocalVarRefChecker final
3202 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3203 Sema &SemaRef;
3204
3205public:
3206 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3207 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3208 if (VD->hasLocalStorage()) {
3209 SemaRef.Diag(E->getBeginLoc(),
3210 diag::err_omp_local_var_in_threadprivate_init)
3211 << E->getSourceRange();
3212 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3213 << VD << VD->getSourceRange();
3214 return true;
3215 }
3216 }
3217 return false;
3218 }
3219 bool VisitStmt(const Stmt *S) {
3220 for (const Stmt *Child : S->children()) {
3221 if (Child && Visit(Child))
3222 return true;
3223 }
3224 return false;
3225 }
3226 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3227};
3228} // namespace
3229
3232 ArrayRef<Expr *> VarList) {
3233 ASTContext &Context = getASTContext();
3235 for (Expr *RefExpr : VarList) {
3236 auto *DE = cast<DeclRefExpr>(RefExpr);
3237 auto *VD = cast<VarDecl>(DE->getDecl());
3238 SourceLocation ILoc = DE->getExprLoc();
3239
3240 // Mark variable as used.
3241 VD->setReferenced();
3242 VD->markUsed(Context);
3243
3244 QualType QType = VD->getType();
3245 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3246 // It will be analyzed later.
3247 Vars.push_back(DE);
3248 continue;
3249 }
3250
3251 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3252 // A threadprivate variable must not have an incomplete type.
3254 ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) {
3255 continue;
3256 }
3257
3258 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3259 // A threadprivate variable must not have a reference type.
3260 if (VD->getType()->isReferenceType()) {
3261 Diag(ILoc, diag::err_omp_ref_type_arg)
3262 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
3263 bool IsDecl =
3265 Diag(VD->getLocation(),
3266 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3267 << VD;
3268 continue;
3269 }
3270
3271 // Check if this is a TLS variable. If TLS is not being supported, produce
3272 // the corresponding diagnostic.
3273 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3274 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3275 getLangOpts().OpenMPUseTLS &&
3276 getASTContext().getTargetInfo().isTLSSupported())) ||
3277 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3278 !VD->isLocalVarDecl())) {
3279 Diag(ILoc, diag::err_omp_var_thread_local)
3280 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3281 bool IsDecl =
3283 Diag(VD->getLocation(),
3284 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3285 << VD;
3286 continue;
3287 }
3288
3289 // Check if initial value of threadprivate variable reference variable with
3290 // local storage (it is not supported by runtime).
3291 if (const Expr *Init = VD->getAnyInitializer()) {
3292 LocalVarRefChecker Checker(SemaRef);
3293 if (Checker.Visit(Init))
3294 continue;
3295 }
3296
3297 Vars.push_back(RefExpr);
3298 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3299 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3300 Context, SourceRange(Loc, Loc)));
3301 if (ASTMutationListener *ML = Context.getASTMutationListener())
3302 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3303 }
3304 OMPThreadPrivateDecl *D = nullptr;
3305 if (!Vars.empty()) {
3307 Loc, Vars);
3309 }
3310 return D;
3311}
3312
3313static OMPAllocateDeclAttr::AllocatorTypeTy
3314getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3315 if (!Allocator)
3316 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3317 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3318 Allocator->isInstantiationDependent() ||
3319 Allocator->containsUnexpandedParameterPack())
3320 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3321 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3322 llvm::FoldingSetNodeID AEId;
3323 const Expr *AE = Allocator->IgnoreParenImpCasts();
3324 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3325 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3326 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3327 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3328 llvm::FoldingSetNodeID DAEId;
3329 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3330 /*Canonical=*/true);
3331 if (AEId == DAEId) {
3332 AllocatorKindRes = AllocatorKind;
3333 break;
3334 }
3335 }
3336 return AllocatorKindRes;
3337}
3338
3340 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3341 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3342 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3343 return false;
3344 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3345 Expr *PrevAllocator = A->getAllocator();
3346 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3347 getAllocatorKind(S, Stack, PrevAllocator);
3348 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3349 if (AllocatorsMatch &&
3350 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3351 Allocator && PrevAllocator) {
3352 const Expr *AE = Allocator->IgnoreParenImpCasts();
3353 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3354 llvm::FoldingSetNodeID AEId, PAEId;
3355 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3356 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3357 AllocatorsMatch = AEId == PAEId;
3358 }
3359 if (!AllocatorsMatch) {
3360 SmallString<256> AllocatorBuffer;
3361 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3362 if (Allocator)
3363 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3364 SmallString<256> PrevAllocatorBuffer;
3365 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3366 if (PrevAllocator)
3367 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3368 S.getPrintingPolicy());
3369
3370 SourceLocation AllocatorLoc =
3371 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3372 SourceRange AllocatorRange =
3373 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3374 SourceLocation PrevAllocatorLoc =
3375 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3376 SourceRange PrevAllocatorRange =
3377 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3378 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3379 << (Allocator ? 1 : 0) << AllocatorStream.str()
3380 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3381 << AllocatorRange;
3382 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3383 << PrevAllocatorRange;
3384 return true;
3385 }
3386 return false;
3387}
3388
3389static void
3391 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3392 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3393 if (VD->hasAttr<OMPAllocateDeclAttr>())
3394 return;
3395 if (Alignment &&
3396 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3397 Alignment->isInstantiationDependent() ||
3398 Alignment->containsUnexpandedParameterPack()))
3399 // Apply later when we have a usable value.
3400 return;
3401 if (Allocator &&
3402 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3403 Allocator->isInstantiationDependent() ||
3404 Allocator->containsUnexpandedParameterPack()))
3405 return;
3406 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3407 Allocator, Alignment, SR);
3408 VD->addAttr(A);
3410 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3411}
3412
3415 DeclContext *Owner) {
3416 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3417 Expr *Alignment = nullptr;
3418 Expr *Allocator = nullptr;
3419 if (Clauses.empty()) {
3420 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3421 // allocate directives that appear in a target region must specify an
3422 // allocator clause unless a requires directive with the dynamic_allocators
3423 // clause is present in the same compilation unit.
3424 if (getLangOpts().OpenMPIsTargetDevice &&
3425 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3426 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3427 } else {
3428 for (const OMPClause *C : Clauses)
3429 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3430 Allocator = AC->getAllocator();
3431 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3432 Alignment = AC->getAlignment();
3433 else
3434 llvm_unreachable("Unexpected clause on allocate directive");
3435 }
3436 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3437 getAllocatorKind(SemaRef, DSAStack, Allocator);
3439 for (Expr *RefExpr : VarList) {
3440 auto *DE = cast<DeclRefExpr>(RefExpr);
3441 auto *VD = cast<VarDecl>(DE->getDecl());
3442
3443 // Check if this is a TLS variable or global register.
3444 if (VD->getTLSKind() != VarDecl::TLS_None ||
3445 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3446 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3447 !VD->isLocalVarDecl()))
3448 continue;
3449
3450 // If the used several times in the allocate directive, the same allocator
3451 // must be used.
3453 AllocatorKind, Allocator))
3454 continue;
3455
3456 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3457 // If a list item has a static storage type, the allocator expression in the
3458 // allocator clause must be a constant expression that evaluates to one of
3459 // the predefined memory allocator values.
3460 if (Allocator && VD->hasGlobalStorage()) {
3461 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3462 Diag(Allocator->getExprLoc(),
3463 diag::err_omp_expected_predefined_allocator)
3464 << Allocator->getSourceRange();
3465 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3467 Diag(VD->getLocation(),
3468 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3469 << VD;
3470 continue;
3471 }
3472 }
3473
3474 Vars.push_back(RefExpr);
3475 applyOMPAllocateAttribute(SemaRef, VD, AllocatorKind, Allocator, Alignment,
3476 DE->getSourceRange());
3477 }
3478 if (Vars.empty())
3479 return nullptr;
3480 if (!Owner)
3481 Owner = SemaRef.getCurLexicalContext();
3482 auto *D = OMPAllocateDecl::Create(getASTContext(), Owner, Loc, Vars, Clauses);
3484 Owner->addDecl(D);
3486}
3487
3490 ArrayRef<OMPClause *> ClauseList) {
3491 OMPRequiresDecl *D = nullptr;
3493 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3494 } else {
3495 D = CheckOMPRequiresDecl(Loc, ClauseList);
3496 if (D) {
3498 DSAStack->addRequiresDecl(D);
3499 }
3500 }
3502}
3503
3505 OpenMPDirectiveKind DKind,
3506 ArrayRef<std::string> Assumptions,
3507 bool SkippedClauses) {
3508 if (!SkippedClauses && Assumptions.empty())
3509 Diag(Loc, diag::err_omp_no_clause_for_directive)
3510 << llvm::omp::getAllAssumeClauseOptions()
3511 << llvm::omp::getOpenMPDirectiveName(DKind);
3512
3513 auto *AA =
3514 OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc);
3515 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3516 OMPAssumeScoped.push_back(AA);
3517 return;
3518 }
3519
3520 // Global assumes without assumption clauses are ignored.
3521 if (Assumptions.empty())
3522 return;
3523
3524 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3525 "Unexpected omp assumption directive!");
3526 OMPAssumeGlobal.push_back(AA);
3527
3528 // The OMPAssumeGlobal scope above will take care of new declarations but
3529 // we also want to apply the assumption to existing ones, e.g., to
3530 // declarations in included headers. To this end, we traverse all existing
3531 // declaration contexts and annotate function declarations here.
3532 SmallVector<DeclContext *, 8> DeclContexts;
3533 auto *Ctx = SemaRef.CurContext;
3534 while (Ctx->getLexicalParent())
3535 Ctx = Ctx->getLexicalParent();
3536 DeclContexts.push_back(Ctx);
3537 while (!DeclContexts.empty()) {
3538 DeclContext *DC = DeclContexts.pop_back_val();
3539 for (auto *SubDC : DC->decls()) {
3540 if (SubDC->isInvalidDecl())
3541 continue;
3542 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3543 DeclContexts.push_back(CTD->getTemplatedDecl());
3544 llvm::append_range(DeclContexts, CTD->specializations());
3545 continue;
3546 }
3547 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3548 DeclContexts.push_back(DC);
3549 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3550 F->addAttr(AA);
3551 continue;
3552 }
3553 }
3554 }
3555}
3556
3558 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3559 OMPAssumeScoped.pop_back();
3560}
3561
3563 Stmt *AStmt,
3564 SourceLocation StartLoc,
3565 SourceLocation EndLoc) {
3566 if (!AStmt)
3567 return StmtError();
3568
3569 return OMPAssumeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
3570 AStmt);
3571}
3572
3575 ArrayRef<OMPClause *> ClauseList) {
3576 /// For target specific clauses, the requires directive cannot be
3577 /// specified after the handling of any of the target regions in the
3578 /// current compilation unit.
3579 ArrayRef<SourceLocation> TargetLocations =
3580 DSAStack->getEncounteredTargetLocs();
3581 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3582 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3583 for (const OMPClause *CNew : ClauseList) {
3584 // Check if any of the requires clauses affect target regions.
3585 if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3586 isa<OMPUnifiedAddressClause>(CNew) ||
3587 isa<OMPReverseOffloadClause>(CNew) ||
3588 isa<OMPDynamicAllocatorsClause>(CNew)) {
3589 Diag(Loc, diag::err_omp_directive_before_requires)
3590 << "target" << getOpenMPClauseName(CNew->getClauseKind());
3591 for (SourceLocation TargetLoc : TargetLocations) {
3592 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3593 << "target";
3594 }
3595 } else if (!AtomicLoc.isInvalid() &&
3596 isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3597 Diag(Loc, diag::err_omp_directive_before_requires)
3598 << "atomic" << getOpenMPClauseName(CNew->getClauseKind());
3599 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3600 << "atomic";
3601 }
3602 }
3603 }
3604
3605 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3607 getASTContext(), SemaRef.getCurLexicalContext(), Loc, ClauseList);
3608 return nullptr;
3609}
3610
3611static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3612 const ValueDecl *D,
3613 const DSAStackTy::DSAVarData &DVar,
3614 bool IsLoopIterVar) {
3615 if (DVar.RefExpr) {
3616 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3617 << getOpenMPClauseName(DVar.CKind);
3618 return;
3619 }
3620 enum {
3621 PDSA_StaticMemberShared,
3622 PDSA_StaticLocalVarShared,
3623 PDSA_LoopIterVarPrivate,
3624 PDSA_LoopIterVarLinear,
3625 PDSA_LoopIterVarLastprivate,
3626 PDSA_ConstVarShared,
3627 PDSA_GlobalVarShared,
3628 PDSA_TaskVarFirstprivate,
3629 PDSA_LocalVarPrivate,
3630 PDSA_Implicit
3631 } Reason = PDSA_Implicit;
3632 bool ReportHint = false;
3633 auto ReportLoc = D->getLocation();
3634 auto *VD = dyn_cast<VarDecl>(D);
3635 if (IsLoopIterVar) {
3636 if (DVar.CKind == OMPC_private)
3637 Reason = PDSA_LoopIterVarPrivate;
3638 else if (DVar.CKind == OMPC_lastprivate)
3639 Reason = PDSA_LoopIterVarLastprivate;
3640 else
3641 Reason = PDSA_LoopIterVarLinear;
3642 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3643 DVar.CKind == OMPC_firstprivate) {
3644 Reason = PDSA_TaskVarFirstprivate;
3645 ReportLoc = DVar.ImplicitDSALoc;
3646 } else if (VD && VD->isStaticLocal())
3647 Reason = PDSA_StaticLocalVarShared;
3648 else if (VD && VD->isStaticDataMember())
3649 Reason = PDSA_StaticMemberShared;
3650 else if (VD && VD->isFileVarDecl())
3651 Reason = PDSA_GlobalVarShared;
3652 else if (D->getType().isConstant(SemaRef.getASTContext()))
3653 Reason = PDSA_ConstVarShared;
3654 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3655 ReportHint = true;
3656 Reason = PDSA_LocalVarPrivate;
3657 }
3658 if (Reason != PDSA_Implicit) {
3659 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3660 << Reason << ReportHint
3661 << getOpenMPDirectiveName(Stack->getCurrentDirective());
3662 } else if (DVar.ImplicitDSALoc.isValid()) {
3663 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3664 << getOpenMPClauseName(DVar.CKind);
3665 }
3666}
3667
3670 bool IsAggregateOrDeclareTarget) {
3672 switch (M) {
3673 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3674 Kind = OMPC_MAP_alloc;
3675 break;
3676 case OMPC_DEFAULTMAP_MODIFIER_to:
3677 Kind = OMPC_MAP_to;
3678 break;
3679 case OMPC_DEFAULTMAP_MODIFIER_from:
3680 Kind = OMPC_MAP_from;
3681 break;
3682 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3683 Kind = OMPC_MAP_tofrom;
3684 break;
3685 case OMPC_DEFAULTMAP_MODIFIER_present:
3686 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3687 // If implicit-behavior is present, each variable referenced in the
3688 // construct in the category specified by variable-category is treated as if
3689 // it had been listed in a map clause with the map-type of alloc and
3690 // map-type-modifier of present.
3691 Kind = OMPC_MAP_alloc;
3692 break;
3693 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3695 llvm_unreachable("Unexpected defaultmap implicit behavior");
3696 case OMPC_DEFAULTMAP_MODIFIER_none:
3697 case OMPC_DEFAULTMAP_MODIFIER_default:
3699 // IsAggregateOrDeclareTarget could be true if:
3700 // 1. the implicit behavior for aggregate is tofrom
3701 // 2. it's a declare target link
3702 if (IsAggregateOrDeclareTarget) {
3703 Kind = OMPC_MAP_tofrom;
3704 break;
3705 }
3706 llvm_unreachable("Unexpected defaultmap implicit behavior");
3707 }
3708 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3709 return Kind;
3710}
3711
3712namespace {
3713struct VariableImplicitInfo {
3714 static const unsigned MapKindNum = OMPC_MAP_unknown;
3715 static const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3716
3717 llvm::SetVector<Expr *> Privates;
3718 llvm::SetVector<Expr *> Firstprivates;
3719 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3721 MapModifiers[DefaultmapKindNum];
3722};
3723
3724class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3725 DSAStackTy *Stack;
3726 Sema &SemaRef;
3727 OpenMPDirectiveKind DKind = OMPD_unknown;
3728 bool ErrorFound = false;
3729 bool TryCaptureCXXThisMembers = false;
3730 CapturedStmt *CS = nullptr;
3731
3732 VariableImplicitInfo ImpInfo;
3733 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3734 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3735
3736 void VisitSubCaptures(OMPExecutableDirective *S) {
3737 // Check implicitly captured variables.
3738 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3739 return;
3740 if (S->getDirectiveKind() == OMPD_atomic ||
3741 S->getDirectiveKind() == OMPD_critical ||
3742 S->getDirectiveKind() == OMPD_section ||
3743 S->getDirectiveKind() == OMPD_master ||
3744 S->getDirectiveKind() == OMPD_masked ||
3745 S->getDirectiveKind() == OMPD_scope ||
3746 S->getDirectiveKind() == OMPD_assume ||
3747 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3748 Visit(S->getAssociatedStmt());
3749 return;
3750 }
3751 visitSubCaptures(S->getInnermostCapturedStmt());
3752 // Try to capture inner this->member references to generate correct mappings
3753 // and diagnostics.
3754 if (TryCaptureCXXThisMembers ||
3756 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3757 [](const CapturedStmt::Capture &C) {
3758 return C.capturesThis();
3759 }))) {
3760 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3761 TryCaptureCXXThisMembers = true;
3762 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3763 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3764 }
3765 // In tasks firstprivates are not captured anymore, need to analyze them
3766 // explicitly.
3767 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3768 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3769 for (OMPClause *C : S->clauses())
3770 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3771 for (Expr *Ref : FC->varlist())
3772 Visit(Ref);
3773 }
3774 }
3775 }
3776
3777public:
3778 void VisitDeclRefExpr(DeclRefExpr *E) {
3779 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3782 E->isNonOdrUse() == clang::NOUR_Unevaluated)
3783 return;
3784 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3785 // Check the datasharing rules for the expressions in the clauses.
3786 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3787 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3788 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3789 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3790 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3791 Visit(CED->getInit());
3792 return;
3793 }
3794 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3795 // Do not analyze internal variables and do not enclose them into
3796 // implicit clauses.
3797 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3798 return;
3799 VD = VD->getCanonicalDecl();
3800 // Skip internally declared variables.
3801 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3802 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3803 !Stack->isImplicitTaskFirstprivate(VD))
3804 return;
3805 // Skip allocators in uses_allocators clauses.
3806 if (Stack->isUsesAllocatorsDecl(VD))
3807 return;
3808
3809 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3810 // Check if the variable has explicit DSA set and stop analysis if it so.
3811 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3812 return;
3813
3814 // Skip internally declared static variables.
3815 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3816 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3817 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3818 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3819 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3820 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3821 !Stack->isImplicitTaskFirstprivate(VD))
3822 return;
3823
3824 SourceLocation ELoc = E->getExprLoc();
3825 // The default(none) clause requires that each variable that is referenced
3826 // in the construct, and does not have a predetermined data-sharing
3827 // attribute, must have its data-sharing attribute explicitly determined
3828 // by being listed in a data-sharing attribute clause.
3829 if (DVar.CKind == OMPC_unknown &&
3830 (Stack->getDefaultDSA() == DSA_none ||
3831 Stack->getDefaultDSA() == DSA_private ||
3832 Stack->getDefaultDSA() == DSA_firstprivate) &&
3833 isImplicitOrExplicitTaskingRegion(DKind) &&
3834 VarsWithInheritedDSA.count(VD) == 0) {
3835 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3836 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3837 Stack->getDefaultDSA() == DSA_private)) {
3838 DSAStackTy::DSAVarData DVar =
3839 Stack->getImplicitDSA(VD, /*FromParent=*/false);
3840 InheritedDSA = DVar.CKind == OMPC_unknown;
3841 }
3842 if (InheritedDSA)
3843 VarsWithInheritedDSA[VD] = E;
3844 if (Stack->getDefaultDSA() == DSA_none)
3845 return;
3846 }
3847
3848 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3849 // If implicit-behavior is none, each variable referenced in the
3850 // construct that does not have a predetermined data-sharing attribute
3851 // and does not appear in a to or link clause on a declare target
3852 // directive must be listed in a data-mapping attribute clause, a
3853 // data-sharing attribute clause (including a data-sharing attribute
3854 // clause on a combined construct where target. is one of the
3855 // constituent constructs), or an is_device_ptr clause.
3856 OpenMPDefaultmapClauseKind ClauseKind =
3858 if (SemaRef.getLangOpts().OpenMP >= 50) {
3859 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3860 OMPC_DEFAULTMAP_MODIFIER_none;
3861 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3862 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3863 // Only check for data-mapping attribute and is_device_ptr here
3864 // since we have already make sure that the declaration does not
3865 // have a data-sharing attribute above
3866 if (!Stack->checkMappableExprComponentListsForDecl(
3867 VD, /*CurrentRegionOnly=*/true,
3869 MapExprComponents,
3871 auto MI = MapExprComponents.rbegin();
3872 auto ME = MapExprComponents.rend();
3873 return MI != ME && MI->getAssociatedDeclaration() == VD;
3874 })) {
3875 VarsWithInheritedDSA[VD] = E;
3876 return;
3877 }
3878 }
3879 }
3880 if (SemaRef.getLangOpts().OpenMP > 50) {
3881 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3882 OMPC_DEFAULTMAP_MODIFIER_present;
3883 if (IsModifierPresent) {
3884 if (!llvm::is_contained(ImpInfo.MapModifiers[ClauseKind],
3885 OMPC_MAP_MODIFIER_present)) {
3886 ImpInfo.MapModifiers[ClauseKind].push_back(
3887 OMPC_MAP_MODIFIER_present);
3888 }
3889 }
3890 }
3891
3893 !Stack->isLoopControlVariable(VD).first) {
3894 if (!Stack->checkMappableExprComponentListsForDecl(
3895 VD, /*CurrentRegionOnly=*/true,
3897 StackComponents,
3899 if (SemaRef.LangOpts.OpenMP >= 50)
3900 return !StackComponents.empty();
3901 // Variable is used if it has been marked as an array, array
3902 // section, array shaping or the variable itself.
3903 return StackComponents.size() == 1 ||
3904 llvm::all_of(
3905 llvm::drop_begin(llvm::reverse(StackComponents)),
3906 [](const OMPClauseMappableExprCommon::
3907 MappableComponent &MC) {
3908 return MC.getAssociatedDeclaration() ==
3909 nullptr &&
3910 (isa<ArraySectionExpr>(
3911 MC.getAssociatedExpression()) ||
3912 isa<OMPArrayShapingExpr>(
3913 MC.getAssociatedExpression()) ||
3914 isa<ArraySubscriptExpr>(
3915 MC.getAssociatedExpression()));
3916 });
3917 })) {
3918 bool IsFirstprivate = false;
3919 // By default lambdas are captured as firstprivates.
3920 if (const auto *RD =
3922 IsFirstprivate = RD->isLambda();
3923 IsFirstprivate =
3924 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3925 if (IsFirstprivate) {
3926 ImpInfo.Firstprivates.insert(E);
3927 } else {
3929 Stack->getDefaultmapModifier(ClauseKind);
3931 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3932 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
3933 }
3934 return;
3935 }
3936 }
3937
3938 // OpenMP [2.9.3.6, Restrictions, p.2]
3939 // A list item that appears in a reduction clause of the innermost
3940 // enclosing worksharing or parallel construct may not be accessed in an
3941 // explicit task.
3942 DVar = Stack->hasInnermostDSA(
3943 VD,
3944 [](OpenMPClauseKind C, bool AppliedToPointee) {
3945 return C == OMPC_reduction && !AppliedToPointee;
3946 },
3947 [](OpenMPDirectiveKind K) {
3948 return isOpenMPParallelDirective(K) ||
3950 },
3951 /*FromParent=*/true);
3952 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3953 ErrorFound = true;
3954 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3955 reportOriginalDsa(SemaRef, Stack, VD, DVar);
3956 return;
3957 }
3958
3959 // Define implicit data-sharing attributes for task.
3960 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
3961 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
3962 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3963 DVar.CKind == OMPC_firstprivate) ||
3964 (Stack->getDefaultDSA() == DSA_private &&
3965 DVar.CKind == OMPC_private)) &&
3966 !DVar.RefExpr)) &&
3967 !Stack->isLoopControlVariable(VD).first) {
3968 if (Stack->getDefaultDSA() == DSA_private)
3969 ImpInfo.Privates.insert(E);
3970 else
3971 ImpInfo.Firstprivates.insert(E);
3972 return;
3973 }
3974
3975 // Store implicitly used globals with declare target link for parent
3976 // target.
3977 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
3978 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3979 Stack->addToParentTargetRegionLinkGlobals(E);
3980 return;
3981 }
3982 }
3983 }
3984 void VisitMemberExpr(MemberExpr *E) {
3985 if (E->isTypeDependent() || E->isValueDependent() ||
3987 return;
3988 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
3989 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
3990 if (!FD)
3991 return;
3992 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
3993 // Check if the variable has explicit DSA set and stop analysis if it
3994 // so.
3995 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
3996 return;
3997
3999 !Stack->isLoopControlVariable(FD).first &&
4000 !Stack->checkMappableExprComponentListsForDecl(
4001 FD, /*CurrentRegionOnly=*/true,
4003 StackComponents,
4005 return isa<CXXThisExpr>(
4006 cast<MemberExpr>(
4007 StackComponents.back().getAssociatedExpression())
4008 ->getBase()
4009 ->IgnoreParens());
4010 })) {
4011 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
4012 // A bit-field cannot appear in a map clause.
4013 //
4014 if (FD->isBitField())
4015 return;
4016
4017 // Check to see if the member expression is referencing a class that
4018 // has already been explicitly mapped
4019 if (Stack->isClassPreviouslyMapped(TE->getType()))
4020 return;
4021
4023 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4024 OpenMPDefaultmapClauseKind ClauseKind =
4027 Modifier, /*IsAggregateOrDeclareTarget=*/true);
4028 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
4029 return;
4030 }
4031
4032 SourceLocation ELoc = E->getExprLoc();
4033 // OpenMP [2.9.3.6, Restrictions, p.2]
4034 // A list item that appears in a reduction clause of the innermost
4035 // enclosing worksharing or parallel construct may not be accessed in
4036 // an explicit task.
4037 DVar = Stack->hasInnermostDSA(
4038 FD,
4039 [](OpenMPClauseKind C, bool AppliedToPointee) {
4040 return C == OMPC_reduction && !AppliedToPointee;
4041 },
4042 [](OpenMPDirectiveKind K) {
4043 return isOpenMPParallelDirective(K) ||
4045 },
4046 /*FromParent=*/true);
4047 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4048 ErrorFound = true;
4049 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4050 reportOriginalDsa(SemaRef, Stack, FD, DVar);
4051 return;
4052 }
4053
4054 // Define implicit data-sharing attributes for task.
4055 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4056 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4057 !Stack->isLoopControlVariable(FD).first) {
4058 // Check if there is a captured expression for the current field in the
4059 // region. Do not mark it as firstprivate unless there is no captured
4060 // expression.
4061 // TODO: try to make it firstprivate.
4062 if (DVar.CKind != OMPC_unknown)
4063 ImpInfo.Firstprivates.insert(E);
4064 }
4065 return;
4066 }
4069 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4070 DKind, /*NoDiagnose=*/true))
4071 return;
4072 const auto *VD = cast<ValueDecl>(
4073 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4074 if (!Stack->checkMappableExprComponentListsForDecl(
4075 VD, /*CurrentRegionOnly=*/true,
4076 [&CurComponents](
4078 StackComponents,
4080 auto CCI = CurComponents.rbegin();
4081 auto CCE = CurComponents.rend();
4082 for (const auto &SC : llvm::reverse(StackComponents)) {
4083 // Do both expressions have the same kind?
4084 if (CCI->getAssociatedExpression()->getStmtClass() !=
4085 SC.getAssociatedExpression()->getStmtClass())
4086 if (!((isa<ArraySectionExpr>(
4087 SC.getAssociatedExpression()) ||
4088 isa<OMPArrayShapingExpr>(
4089 SC.getAssociatedExpression())) &&
4090 isa<ArraySubscriptExpr>(
4091 CCI->getAssociatedExpression())))
4092 return false;
4093
4094 const Decl *CCD = CCI->getAssociatedDeclaration();
4095 const Decl *SCD = SC.getAssociatedDeclaration();
4096 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4097 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4098 if (SCD != CCD)
4099 return false;
4100 std::advance(CCI, 1);
4101 if (CCI == CCE)
4102 break;
4103 }
4104 return true;
4105 })) {
4106 Visit(E->getBase());
4107 }
4108 } else if (!TryCaptureCXXThisMembers) {
4109 Visit(E->getBase());
4110 }
4111 }
4112 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4113 for (OMPClause *C : S->clauses()) {
4114 // Skip analysis of arguments of private clauses for task|target
4115 // directives.
4116 if (isa_and_nonnull<OMPPrivateClause>(C))
4117 continue;
4118 // Skip analysis of arguments of implicitly defined firstprivate clause
4119 // for task|target directives.
4120 // Skip analysis of arguments of implicitly defined map clause for target
4121 // directives.
4122 if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
4123 C->isImplicit() && !isOpenMPTaskingDirective(DKind))) {
4124 for (Stmt *CC : C->children()) {
4125 if (CC)
4126 Visit(CC);
4127 }
4128 }
4129 }
4130 // Check implicitly captured variables.
4131 VisitSubCaptures(S);
4132 }
4133
4134 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) {
4135 // Loop transformation directives do not introduce data sharing
4136 VisitStmt(S);
4137 }
4138
4139 void VisitCallExpr(CallExpr *S) {
4140 for (Stmt *C : S->arguments()) {
4141 if (C) {
4142 // Check implicitly captured variables in the task-based directives to
4143 // check if they must be firstprivatized.
4144 Visit(C);
4145 }
4146 }
4147 if (Expr *Callee = S->getCallee()) {
4148 auto *CI = Callee->IgnoreParenImpCasts();
4149 if (auto *CE = dyn_cast<MemberExpr>(CI))
4150 Visit(CE->getBase());
4151 else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4152 Visit(CE);
4153 }
4154 }
4155 void VisitStmt(Stmt *S) {
4156 for (Stmt *C : S->children()) {
4157 if (C) {
4158 // Check implicitly captured variables in the task-based directives to
4159 // check if they must be firstprivatized.
4160 Visit(C);
4161 }
4162 }
4163 }
4164
4165 void visitSubCaptures(CapturedStmt *S) {
4166 for (const CapturedStmt::Capture &Cap : S->captures()) {
4167 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4168 continue;
4169 VarDecl *VD = Cap.getCapturedVar();
4170 // Do not try to map the variable if it or its sub-component was mapped
4171 // already.
4173 Stack->checkMappableExprComponentListsForDecl(
4174 VD, /*CurrentRegionOnly=*/true,
4176 OpenMPClauseKind) { return true; }))
4177 continue;
4179 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4180 Cap.getLocation(), /*RefersToCapture=*/true);
4181 Visit(DRE);
4182 }
4183 }
4184 bool isErrorFound() const { return ErrorFound; }
4185 const VariableImplicitInfo &getImplicitInfo() const { return ImpInfo; }
4186 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4187 return VarsWithInheritedDSA;
4188 }
4189
4190 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4191 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4192 DKind = S->getCurrentDirective();
4193 // Process declare target link variables for the target directives.
4195 for (DeclRefExpr *E : Stack->getLinkGlobals())
4196 Visit(E);
4197 }
4198 }
4199};
4200} // namespace
4201
4202static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4203 OpenMPDirectiveKind DKind,
4204 bool ScopeEntry) {
4207 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4208 if (isOpenMPTeamsDirective(DKind))
4209 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4210 if (isOpenMPParallelDirective(DKind))
4211 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4213 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4214 if (isOpenMPSimdDirective(DKind))
4215 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4216 Stack->handleConstructTrait(Traits, ScopeEntry);
4217}
4218
4220getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4221 ASTContext &Context = SemaRef.getASTContext();
4222 QualType KmpInt32Ty =
4223 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4224 QualType KmpInt32PtrTy =
4225 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4227 std::make_pair(".global_tid.", KmpInt32PtrTy),
4228 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4229 };
4230 if (LoopBoundSharing) {
4231 QualType KmpSizeTy = Context.getSizeType().withConst();
4232 Params.push_back(std::make_pair(".previous.lb.", KmpSizeTy));
4233 Params.push_back(std::make_pair(".previous.ub.", KmpSizeTy));
4234 }
4235
4236 // __context with shared vars
4237 Params.push_back(std::make_pair(StringRef(), QualType()));
4238 return Params;
4239}
4240
4243 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4244}
4245
4248 ASTContext &Context = SemaRef.getASTContext();
4249 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4250 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4251 QualType KmpInt32PtrTy =
4252 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4253 QualType Args[] = {VoidPtrTy};
4255 EPI.Variadic = true;
4256 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4258 std::make_pair(".global_tid.", KmpInt32Ty),
4259 std::make_pair(".part_id.", KmpInt32PtrTy),
4260 std::make_pair(".privates.", VoidPtrTy),
4261 std::make_pair(
4262 ".copy_fn.",
4263 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4264 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4265 std::make_pair(StringRef(), QualType()) // __context with shared vars
4266 };
4267 return Params;
4268}
4269
4272 ASTContext &Context = SemaRef.getASTContext();
4274 if (SemaRef.getLangOpts().OpenMPIsTargetDevice) {
4275 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4276 Params.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4277 }
4278 // __context with shared vars
4279 Params.push_back(std::make_pair(StringRef(), QualType()));
4280 return Params;
4281}
4282
4286 std::make_pair(StringRef(), QualType()) // __context with shared vars
4287 };
4288 return Params;
4289}
4290
4293 ASTContext &Context = SemaRef.getASTContext();
4294 QualType KmpInt32Ty =
4295 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4296 QualType KmpUInt64Ty =
4297 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4298 QualType KmpInt64Ty =
4299 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4300 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4301 QualType KmpInt32PtrTy =
4302 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4303 QualType Args[] = {VoidPtrTy};
4305 EPI.Variadic = true;
4306 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4308 std::make_pair(".global_tid.", KmpInt32Ty),
4309 std::make_pair(".part_id.", KmpInt32PtrTy),
4310 std::make_pair(".privates.", VoidPtrTy),
4311 std::make_pair(
4312 ".copy_fn.",
4313 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4314 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4315 std::make_pair(".lb.", KmpUInt64Ty),
4316 std::make_pair(".ub.", KmpUInt64Ty),
4317 std::make_pair(".st.", KmpInt64Ty),
4318 std::make_pair(".liter.", KmpInt32Ty),
4319 std::make_pair(".reductions.", VoidPtrTy),
4320 std::make_pair(StringRef(), QualType()) // __context with shared vars
4321 };
4322 return Params;
4323}
4324
4326 Scope *CurScope, SourceLocation Loc) {
4328 getOpenMPCaptureRegions(Regions, DKind);
4329
4330 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(DKind);
4331
4332 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4333 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4334 SemaRef.getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4335 };
4336
4337 for (auto [Level, RKind] : llvm::enumerate(Regions)) {
4338 switch (RKind) {
4339 // All region kinds that can be returned from `getOpenMPCaptureRegions`
4340 // are listed here.
4341 case OMPD_parallel:
4343 Loc, CurScope, CR_OpenMP,
4344 getParallelRegionParams(SemaRef, LoopBoundSharing), Level);
4345 break;
4346 case OMPD_teams:
4347 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4348 getTeamsRegionParams(SemaRef), Level);
4349 break;
4350 case OMPD_task:
4351 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4352 getTaskRegionParams(SemaRef), Level);
4353 // Mark this captured region as inlined, because we don't use outlined
4354 // function directly.
4355 MarkAsInlined(SemaRef.getCurCapturedRegion());
4356 break;
4357 case OMPD_taskloop:
4358 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4359 getTaskloopRegionParams(SemaRef), Level);
4360 // Mark this captured region as inlined, because we don't use outlined
4361 // function directly.
4362 MarkAsInlined(SemaRef.getCurCapturedRegion());
4363 break;
4364 case OMPD_target:
4365 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4366 getTargetRegionParams(SemaRef), Level);
4367 break;
4368 case OMPD_unknown:
4369 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4370 getUnknownRegionParams(SemaRef));
4371 break;
4372 case OMPD_metadirective:
4373 case OMPD_nothing:
4374 default:
4375 llvm_unreachable("Unexpected capture region");
4376 }
4377 }
4378}
4379
4381 Scope *CurScope) {
4382 switch (DKind) {
4383 case OMPD_atomic:
4384 case OMPD_critical:
4385 case OMPD_masked:
4386 case OMPD_master:
4387 case OMPD_section:
4388 case OMPD_tile:
4389 case OMPD_unroll:
4390 case OMPD_reverse:
4391 case OMPD_interchange:
4392 case OMPD_assume:
4393 break;
4394 default:
4395 processCapturedRegions(SemaRef, DKind, CurScope,
4396 DSAStack->getConstructLoc());
4397 break;
4398 }
4399
4400 DSAStack->setContext(SemaRef.CurContext);
4401 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
4402}
4403
4404int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4405 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4406}
4407
4410 getOpenMPCaptureRegions(CaptureRegions, DKind);
4411 return CaptureRegions.size();
4412}
4413
4415 Expr *CaptureExpr, bool WithInit,
4416 DeclContext *CurContext,
4417 bool AsExpression) {
4418 assert(CaptureExpr);
4419 ASTContext &C = S.getASTContext();
4420 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4421 QualType Ty = Init->getType();
4422 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4423 if (S.getLangOpts().CPlusPlus) {
4424 Ty = C.getLValueReferenceType(Ty);
4425 } else {
4426 Ty = C.getPointerType(Ty);
4427 ExprResult Res =
4428 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4429 if (!Res.isUsable())
4430 return nullptr;
4431 Init = Res.get();
4432 }
4433 WithInit = true;
4434 }
4435 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4436 CaptureExpr->getBeginLoc());
4437 if (!WithInit)
4438 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4439 CurContext->addHiddenDecl(CED);
4441 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4442 return CED;
4443}
4444
4445static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4446 bool WithInit) {
4448 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4449 CD = cast<OMPCapturedExprDecl>(VD);
4450 else
4451 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4452 S.CurContext,
4453 /*AsExpression=*/false);
4454 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4455 CaptureExpr->getExprLoc());
4456}
4457
4458static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4459 StringRef Name) {
4460 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4461 if (!Ref) {
4463 S, &S.getASTContext().Idents.get(Name), CaptureExpr,
4464 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4465 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4466 CaptureExpr->getExprLoc());
4467 }
4468 ExprResult Res = Ref;
4469 if (!S.getLangOpts().CPlusPlus &&
4470 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4471 Ref->getType()->isPointerType()) {
4472 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4473 if (!Res.isUsable())
4474 return ExprError();
4475 }
4476 return S.DefaultLvalueConversion(Res.get());
4477}
4478
4479namespace {
4480// OpenMP directives parsed in this section are represented as a
4481// CapturedStatement with an associated statement. If a syntax error
4482// is detected during the parsing of the associated statement, the
4483// compiler must abort processing and close the CapturedStatement.
4484//
4485// Combined directives such as 'target parallel' have more than one
4486// nested CapturedStatements. This RAII ensures that we unwind out
4487// of all the nested CapturedStatements when an error is found.
4488class CaptureRegionUnwinderRAII {
4489private:
4490 Sema &S;
4491 bool &ErrorFound;
4492 OpenMPDirectiveKind DKind = OMPD_unknown;
4493
4494public:
4495 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4496 OpenMPDirectiveKind DKind)
4497 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4498 ~CaptureRegionUnwinderRAII() {
4499 if (ErrorFound) {
4500 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4501 while (--ThisCaptureLevel >= 0)
4503 }
4504 }
4505};
4506} // namespace
4507
4509 // Capture variables captured by reference in lambdas for target-based
4510 // directives.
4512 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4514 DSAStack->getCurrentDirective()))) {
4515 QualType Type = V->getType();
4516 if (const auto *RD = Type.getCanonicalType()
4517 .getNonReferenceType()
4518 ->getAsCXXRecordDecl()) {
4519 bool SavedForceCaptureByReferenceInTargetExecutable =
4520 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4521 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4522 /*V=*/true);
4523 if (RD->isLambda()) {
4524 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4525 FieldDecl *ThisCapture;
4526 RD->getCaptureFields(Captures, ThisCapture);
4527 for (const LambdaCapture &LC : RD->captures()) {
4528 if (LC.getCaptureKind() == LCK_ByRef) {
4529 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4530 DeclContext *VDC = VD->getDeclContext();
4531 if (!VDC->Encloses(SemaRef.CurContext))
4532 continue;
4533 SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
4534 } else if (LC.getCaptureKind() == LCK_This) {
4536 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4537 ThisTy, ThisCapture->getType()))
4538 SemaRef.CheckCXXThisCapture(LC.getLocation());
4539 }
4540 }
4541 }
4542 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4543 SavedForceCaptureByReferenceInTargetExecutable);
4544 }
4545 }
4546}
4547
4549 const ArrayRef<OMPClause *> Clauses) {
4550 const OMPOrderedClause *Ordered = nullptr;
4551 const OMPOrderClause *Order = nullptr;
4552
4553 for (const OMPClause *Clause : Clauses) {
4554 if (Clause->getClauseKind() == OMPC_ordered)
4555 Ordered = cast<OMPOrderedClause>(Clause);
4556 else if (Clause->getClauseKind() == OMPC_order) {
4557 Order = cast<OMPOrderClause>(Clause);
4558 if (Order->getKind() != OMPC_ORDER_concurrent)
4559 Order = nullptr;
4560 }
4561 if (Ordered && Order)
4562 break;
4563 }
4564
4565 if (Ordered && Order) {
4566 S.Diag(Order->getKindKwLoc(),
4567 diag::err_omp_simple_clause_incompatible_with_ordered)
4568 << getOpenMPClauseName(OMPC_order)
4569 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4570 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4571 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4572 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4573 return true;
4574 }
4575 return false;
4576}
4577
4579 ArrayRef<OMPClause *> Clauses) {
4581 /*ScopeEntry=*/false);
4582 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
4583 return S;
4584
4585 bool ErrorFound = false;
4586 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4587 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4588 if (!S.isUsable()) {
4589 ErrorFound = true;
4590 return StmtError();
4591 }
4592
4594 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4595 OMPOrderedClause *OC = nullptr;
4596 OMPScheduleClause *SC = nullptr;
4599 // This is required for proper codegen.
4600 for (OMPClause *Clause : Clauses) {
4601 if (!getLangOpts().OpenMPSimd &&
4602 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4603 DSAStack->getCurrentDirective() == OMPD_target) &&
4604 Clause->getClauseKind() == OMPC_in_reduction) {
4605 // Capture taskgroup task_reduction descriptors inside the tasking regions
4606 // with the corresponding in_reduction items.
4607 auto *IRC = cast<OMPInReductionClause>(Clause);
4608 for (Expr *E : IRC->taskgroup_descriptors())
4609 if (E)
4611 }
4612 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4613 Clause->getClauseKind() == OMPC_copyprivate ||
4614 (getLangOpts().OpenMPUseTLS &&
4615 getASTContext().getTargetInfo().isTLSSupported() &&
4616 Clause->getClauseKind() == OMPC_copyin)) {
4617 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4618 // Mark all variables in private list clauses as used in inner region.
4619 for (Stmt *VarRef : Clause->children()) {
4620 if (auto *E = cast_or_null<Expr>(VarRef)) {
4622 }
4623 }
4624 DSAStack->setForceVarCapturing(/*V=*/false);
4625 } else if (CaptureRegions.size() > 1 ||
4626 CaptureRegions.back() != OMPD_unknown) {
4627 if (auto *C = OMPClauseWithPreInit::get(Clause))
4628 PICs.push_back(C);
4629 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4630 if (Expr *E = C->getPostUpdateExpr())
4632 }
4633 }
4634 if (Clause->getClauseKind() == OMPC_schedule)
4635 SC = cast<OMPScheduleClause>(Clause);
4636 else if (Clause->getClauseKind() == OMPC_ordered)
4637 OC = cast<OMPOrderedClause>(Clause);
4638 else if (Clause->getClauseKind() == OMPC_linear)
4639 LCs.push_back(cast<OMPLinearClause>(Clause));
4640 }
4641 // Capture allocator expressions if used.
4642 for (Expr *E : DSAStack->getInnerAllocators())
4644 // OpenMP, 2.7.1 Loop Construct, Restrictions
4645 // The nonmonotonic modifier cannot be specified if an ordered clause is
4646 // specified.
4647 if (SC &&
4648 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4650 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4651 OC) {
4652 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4655 diag::err_omp_simple_clause_incompatible_with_ordered)
4656 << getOpenMPClauseName(OMPC_schedule)
4657 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4658 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4659 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4660 ErrorFound = true;
4661 }
4662 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4663 // If an order(concurrent) clause is present, an ordered clause may not appear
4664 // on the same directive.
4665 if (checkOrderedOrderSpecified(SemaRef, Clauses))
4666 ErrorFound = true;
4667 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4668 for (const OMPLinearClause *C : LCs) {
4669 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4670 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4671 }
4672 ErrorFound = true;
4673 }
4674 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4675 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4676 OC->getNumForLoops()) {
4677 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4678 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
4679 ErrorFound = true;
4680 }
4681 if (ErrorFound) {
4682 return StmtError();
4683 }
4684 StmtResult SR = S;
4685 unsigned CompletedRegions = 0;
4686 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4687 // Mark all variables in private list clauses as used in inner region.
4688 // Required for proper codegen of combined directives.
4689 // TODO: add processing for other clauses.
4690 if (ThisCaptureRegion != OMPD_unknown) {
4691 for (const clang::OMPClauseWithPreInit *C : PICs) {
4692 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4693 // Find the particular capture region for the clause if the
4694 // directive is a combined one with multiple capture regions.
4695 // If the directive is not a combined one, the capture region
4696 // associated with the clause is OMPD_unknown and is generated
4697 // only once.
4698 if (CaptureRegion == ThisCaptureRegion ||
4699 CaptureRegion == OMPD_unknown) {
4700 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4701 for (Decl *D : DS->decls())
4703 cast<VarDecl>(D));
4704 }
4705 }
4706 }
4707 }
4708 if (ThisCaptureRegion == OMPD_target) {
4709 // Capture allocator traits in the target region. They are used implicitly
4710 // and, thus, are not captured by default.
4711 for (OMPClause *C : Clauses) {
4712 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4713 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4714 ++I) {
4715 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4716 if (Expr *E = D.AllocatorTraits)
4718 }
4719 continue;
4720 }
4721 }
4722 }
4723 if (ThisCaptureRegion == OMPD_parallel) {
4724 // Capture temp arrays for inscan reductions and locals in aligned
4725 // clauses.
4726 for (OMPClause *C : Clauses) {
4727 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4728 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4729 continue;
4730 for (Expr *E : RC->copy_array_temps())
4731 if (E)
4733 }
4734 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4735 for (Expr *E : AC->varlist())
4737 }
4738 }
4739 }
4740 if (++CompletedRegions == CaptureRegions.size())
4741 DSAStack->setBodyComplete();
4743 }
4744 return SR;
4745}
4746
4747static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4748 OpenMPDirectiveKind CancelRegion,
4749 SourceLocation StartLoc) {
4750 // CancelRegion is only needed for cancel and cancellation_point.
4751 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4752 return false;
4753
4754 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4755 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4756 return false;
4757
4758 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4759 << getOpenMPDirectiveName(CancelRegion);
4760 return true;
4761}
4762
4763static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4764 OpenMPDirectiveKind CurrentRegion,
4765 const DeclarationNameInfo &CurrentName,
4766 OpenMPDirectiveKind CancelRegion,
4767 OpenMPBindClauseKind BindKind,
4768 SourceLocation StartLoc) {
4769 if (!Stack->getCurScope())
4770 return false;
4771
4772 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4773 OpenMPDirectiveKind OffendingRegion = ParentRegion;
4774 bool NestingProhibited = false;
4775 bool CloseNesting = true;
4776 bool OrphanSeen = false;
4777 enum {
4778 NoRecommend,
4779 ShouldBeInParallelRegion,
4780 ShouldBeInOrderedRegion,
4781 ShouldBeInTargetRegion,
4782 ShouldBeInTeamsRegion,
4783 ShouldBeInLoopSimdRegion,
4784 } Recommend = NoRecommend;
4785
4788 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4789 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
4790
4791 if (SemaRef.LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() &&
4792 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop &&
4793 CurrentRegion != OMPD_parallel &&
4794 !isOpenMPCombinedParallelADirective(CurrentRegion)) {
4795 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
4796 << getOpenMPDirectiveName(CurrentRegion);
4797 return true;
4798 }
4799 if (isOpenMPSimdDirective(ParentRegion) &&
4800 ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
4801 (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
4802 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4803 CurrentRegion != OMPD_scan))) {
4804 // OpenMP [2.16, Nesting of Regions]
4805 // OpenMP constructs may not be nested inside a simd region.
4806 // OpenMP [2.8.1,simd Construct, Restrictions]
4807 // An ordered construct with the simd clause is the only OpenMP
4808 // construct that can appear in the simd region.
4809 // Allowing a SIMD construct nested in another SIMD construct is an
4810 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
4811 // message.
4812 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
4813 // The only OpenMP constructs that can be encountered during execution of
4814 // a simd region are the atomic construct, the loop construct, the simd
4815 // construct and the ordered construct with the simd clause.
4816 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
4817 ? diag::err_omp_prohibited_region_simd
4818 : diag::warn_omp_nesting_simd)
4819 << (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0);
4820 return CurrentRegion != OMPD_simd;
4821 }
4822 if (EnclosingConstruct == OMPD_atomic) {
4823 // OpenMP [2.16, Nesting of Regions]
4824 // OpenMP constructs may not be nested inside an atomic region.
4825 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
4826 return true;
4827 }
4828 if (CurrentRegion == OMPD_section) {
4829 // OpenMP [2.7.2, sections Construct, Restrictions]
4830 // Orphaned section directives are prohibited. That is, the section
4831 // directives must appear within the sections construct and must not be
4832 // encountered elsewhere in the sections region.
4833 if (EnclosingConstruct != OMPD_sections) {
4834 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
4835 << (ParentRegion != OMPD_unknown)
4836 << getOpenMPDirectiveName(ParentRegion);
4837 return true;
4838 }
4839 return false;
4840 }
4841 // Allow some constructs (except teams and cancellation constructs) to be
4842 // orphaned (they could be used in functions, called from OpenMP regions
4843 // with the required preconditions).
4844 if (ParentRegion == OMPD_unknown &&
4845 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
4846 CurrentRegion != OMPD_cancellation_point &&
4847 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
4848 return false;
4849 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
4850 // for a detailed explanation
4851 if (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop &&
4852 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
4853 (isOpenMPWorksharingDirective(ParentRegion) ||
4854 EnclosingConstruct == OMPD_loop)) {
4855 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
4856 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
4857 << true << getOpenMPDirectiveName(ParentRegion) << ErrorMsgNumber
4858 << getOpenMPDirectiveName(CurrentRegion);
4859 return true;
4860 }
4861 if (CurrentRegion == OMPD_cancellation_point ||
4862 CurrentRegion == OMPD_cancel) {
4863 // OpenMP [2.16, Nesting of Regions]
4864 // A cancellation point construct for which construct-type-clause is
4865 // taskgroup must be nested inside a task construct. A cancellation
4866 // point construct for which construct-type-clause is not taskgroup must
4867 // be closely nested inside an OpenMP construct that matches the type
4868 // specified in construct-type-clause.
4869 // A cancel construct for which construct-type-clause is taskgroup must be
4870 // nested inside a task construct. A cancel construct for which
4871 // construct-type-clause is not taskgroup must be closely nested inside an
4872 // OpenMP construct that matches the type specified in
4873 // construct-type-clause.
4874 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(ParentRegion);
4875 if (CancelRegion == OMPD_taskgroup) {
4876 NestingProhibited = EnclosingConstruct != OMPD_task &&
4877 (SemaRef.getLangOpts().OpenMP < 50 ||
4878 EnclosingConstruct != OMPD_taskloop);
4879 } else if (CancelRegion == OMPD_sections) {
4880 NestingProhibited = EnclosingConstruct != OMPD_section &&
4881 EnclosingConstruct != OMPD_sections;
4882 } else {
4883 NestingProhibited = CancelRegion != Leafs.back();
4884 }
4885 OrphanSeen = ParentRegion == OMPD_unknown;
4886 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
4887 // OpenMP 5.1 [2.22, Nesting of Regions]
4888 // A masked region may not be closely nested inside a worksharing, loop,
4889 // atomic, task, or taskloop region.
4890 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4891 isOpenMPGenericLoopDirective(ParentRegion) ||
4892 isOpenMPTaskingDirective(ParentRegion);
4893 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
4894 // OpenMP [2.16, Nesting of Regions]
4895 // A critical region may not be nested (closely or otherwise) inside a
4896 // critical region with the same name. Note that this restriction is not
4897 // sufficient to prevent deadlock.
4898 SourceLocation PreviousCriticalLoc;
4899 bool DeadLock = Stack->hasDirective(
4900 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
4901 const DeclarationNameInfo &DNI,
4903 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
4904 PreviousCriticalLoc = Loc;
4905 return true;
4906 }
4907 return false;
4908 },
4909 false /* skip top directive */);
4910 if (DeadLock) {
4911 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
4912 << CurrentName.getName();
4913 if (PreviousCriticalLoc.isValid())
4914 SemaRef.Diag(PreviousCriticalLoc,
4915 diag::note_omp_previous_critical_region);
4916 return true;
4917 }
4918 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
4919 // OpenMP 5.1 [2.22, Nesting of Regions]
4920 // A scope region may not be closely nested inside a worksharing, loop,
4921 // task, taskloop, critical, ordered, atomic, or masked region.
4922 // OpenMP 5.1 [2.22, Nesting of Regions]
4923 // A barrier region may not be closely nested inside a worksharing, loop,
4924 // task, taskloop, critical, ordered, atomic, or masked region.
4925 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4926 isOpenMPGenericLoopDirective(ParentRegion) ||
4927 isOpenMPTaskingDirective(ParentRegion) ||
4928 llvm::is_contained({OMPD_masked, OMPD_master,
4929 OMPD_critical, OMPD_ordered},
4930 EnclosingConstruct);
4931 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
4932 !isOpenMPParallelDirective(CurrentRegion) &&
4933 !isOpenMPTeamsDirective(CurrentRegion)) {
4934 // OpenMP 5.1 [2.22, Nesting of Regions]
4935 // A loop region that binds to a parallel region or a worksharing region
4936 // may not be closely nested inside a worksharing, loop, task, taskloop,
4937 // critical, ordered, atomic, or masked region.
4938 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4939 isOpenMPGenericLoopDirective(ParentRegion) ||
4940 isOpenMPTaskingDirective(ParentRegion) ||
4941 llvm::is_contained({OMPD_masked, OMPD_master,
4942 OMPD_critical, OMPD_ordered},
4943 EnclosingConstruct);
4944 Recommend = ShouldBeInParallelRegion;
4945 } else if (CurrentRegion == OMPD_ordered) {
4946 // OpenMP [2.16, Nesting of Regions]
4947 // An ordered region may not be closely nested inside a critical,
4948 // atomic, or explicit task region.
4949 // An ordered region must be closely nested inside a loop region (or
4950 // parallel loop region) with an ordered clause.
4951 // OpenMP [2.8.1,simd Construct, Restrictions]
4952 // An ordered construct with the simd clause is the only OpenMP construct
4953 // that can appear in the simd region.
4954 NestingProhibited = EnclosingConstruct == OMPD_critical ||
4955 isOpenMPTaskingDirective(ParentRegion) ||
4956 !(isOpenMPSimdDirective(ParentRegion) ||
4957 Stack->isParentOrderedRegion());
4958 Recommend = ShouldBeInOrderedRegion;
4959 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
4960 // OpenMP [2.16, Nesting of Regions]
4961 // If specified, a teams construct must be contained within a target
4962 // construct.
4963 NestingProhibited =
4964 (SemaRef.LangOpts.OpenMP <= 45 && EnclosingConstruct != OMPD_target) ||
4965 (SemaRef.LangOpts.OpenMP >= 50 && EnclosingConstruct != OMPD_unknown &&
4966 EnclosingConstruct != OMPD_target);
4967 OrphanSeen = ParentRegion == OMPD_unknown;
4968 Recommend = ShouldBeInTargetRegion;
4969 } else if (CurrentRegion == OMPD_scan) {
4970 if (SemaRef.LangOpts.OpenMP >= 50) {
4971 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
4972 // simd, or for simd. This has to take into account combined directives.
4973 // In 5.2 this seems to be implied by the fact that the specified
4974 // separated constructs are do, for, and simd.
4975 NestingProhibited = !llvm::is_contained(
4976 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
4977 } else {
4978 NestingProhibited = true;
4979 }
4980 OrphanSeen = ParentRegion == OMPD_unknown;
4981 Recommend = ShouldBeInLoopSimdRegion;
4982 }
4983 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(CurrentRegion) &&
4984 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
4985 EnclosingConstruct == OMPD_teams) {
4986 // OpenMP [5.1, 2.22, Nesting of Regions]
4987 // distribute, distribute simd, distribute parallel worksharing-loop,
4988 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
4989 // including any parallel regions arising from combined constructs,
4990 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
4991 // only OpenMP regions that may be strictly nested inside the teams
4992 // region.
4993 //
4994 // As an extension, we permit atomic within teams as well.
4995 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
4996 !isOpenMPDistributeDirective(CurrentRegion) &&
4997 CurrentRegion != OMPD_loop &&
4998 !(SemaRef.getLangOpts().OpenMPExtensions &&
4999 CurrentRegion == OMPD_atomic);
5000 Recommend = ShouldBeInParallelRegion;
5001 }
5002 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5003 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5004 // If the bind clause is present on the loop construct and binding is
5005 // teams then the corresponding loop region must be strictly nested inside
5006 // a teams region.
5007 NestingProhibited =
5008 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5009 Recommend = ShouldBeInTeamsRegion;
5010 }
5011 if (!NestingProhibited && isOpenMPNestingDistributeDirective(CurrentRegion)) {
5012 // OpenMP 4.5 [2.17 Nesting of Regions]
5013 // The region associated with the distribute construct must be strictly
5014 // nested inside a teams region
5015 NestingProhibited = EnclosingConstruct != OMPD_teams;
5016 Recommend = ShouldBeInTeamsRegion;
5017 }
5018 if (!NestingProhibited &&
5019 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5020 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5021 // OpenMP 4.5 [2.17 Nesting of Regions]
5022 // If a target, target update, target data, target enter data, or
5023 // target exit data construct is encountered during execution of a
5024 // target region, the behavior is unspecified.
5025 NestingProhibited = Stack->hasDirective(
5026 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5029 OffendingRegion = K;
5030 return true;
5031 }
5032 return false;
5033 },
5034 false /* don't skip top directive */);
5035 CloseNesting = false;
5036 }
5037 if (NestingProhibited) {
5038 if (OrphanSeen) {
5039 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5040 << getOpenMPDirectiveName(CurrentRegion) << Recommend;
5041 } else {
5042 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5043 << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
5044 << Recommend << getOpenMPDirectiveName(CurrentRegion);
5045 }
5046 return true;
5047 }
5048 return false;
5049}
5050
5053 unsigned operator()(argument_type DK) { return unsigned(DK); }
5054};
5056 ArrayRef<OMPClause *> Clauses,
5057 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5058 bool ErrorFound = false;
5059 unsigned NamedModifiersNumber = 0;
5060 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5061 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5062 SmallVector<SourceLocation, 4> NameModifierLoc;
5063 for (const OMPClause *C : Clauses) {
5064 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5065 // At most one if clause without a directive-name-modifier can appear on
5066 // the directive.
5067 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5068 if (FoundNameModifiers[CurNM]) {
5069 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5070 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
5071 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
5072 ErrorFound = true;
5073 } else if (CurNM != OMPD_unknown) {
5074 NameModifierLoc.push_back(IC->getNameModifierLoc());
5075 ++NamedModifiersNumber;
5076 }
5077 FoundNameModifiers[CurNM] = IC;
5078 if (CurNM == OMPD_unknown)
5079 continue;
5080 // Check if the specified name modifier is allowed for the current
5081 // directive.
5082 // At most one if clause with the particular directive-name-modifier can
5083 // appear on the directive.
5084 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5085 S.Diag(IC->getNameModifierLoc(),
5086 diag::err_omp_wrong_if_directive_name_modifier)
5087 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
5088 ErrorFound = true;
5089 }
5090 }
5091 }
5092 // If any if clause on the directive includes a directive-name-modifier then
5093 // all if clauses on the directive must include a directive-name-modifier.
5094 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5095 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5096 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5097 diag::err_omp_no_more_if_clause);
5098 } else {
5099 std::string Values;
5100 std::string Sep(", ");
5101 unsigned AllowedCnt = 0;
5102 unsigned TotalAllowedNum =
5103 AllowedNameModifiers.size() - NamedModifiersNumber;
5104 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5105 ++Cnt) {
5106 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5107 if (!FoundNameModifiers[NM]) {
5108 Values += "'";
5109 Values += getOpenMPDirectiveName(NM);
5110 Values += "'";
5111 if (AllowedCnt + 2 == TotalAllowedNum)
5112 Values += " or ";
5113 else if (AllowedCnt + 1 != TotalAllowedNum)
5114 Values += Sep;
5115 ++AllowedCnt;
5116 }
5117 }
5118 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5119 diag::err_omp_unnamed_if_clause)
5120 << (TotalAllowedNum > 1) << Values;
5121 }
5122 for (SourceLocation Loc : NameModifierLoc) {
5123 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5124 }
5125 ErrorFound = true;
5126 }
5127 return ErrorFound;
5128}
5129
5130static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5131 SourceLocation &ELoc,
5132 SourceRange &ERange,
5133 bool AllowArraySection,
5134 StringRef DiagType) {
5135 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5137 return std::make_pair(nullptr, true);
5138
5139 // OpenMP [3.1, C/C++]
5140 // A list item is a variable name.
5141 // OpenMP [2.9.3.3, Restrictions, p.1]
5142 // A variable that is part of another variable (as an array or
5143 // structure element) cannot appear in a private clause.
5144 RefExpr = RefExpr->IgnoreParens();
5145 enum {
5146 NoArrayExpr = -1,
5147 ArraySubscript = 0,
5148 OMPArraySection = 1
5149 } IsArrayExpr = NoArrayExpr;
5150 if (AllowArraySection) {
5151 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5152 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5153 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5154 Base = TempASE->getBase()->IgnoreParenImpCasts();
5155 RefExpr = Base;
5156 IsArrayExpr = ArraySubscript;
5157 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5158 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5159 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Base))
5160 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5161 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5162 Base = TempASE->getBase()->IgnoreParenImpCasts();
5163 RefExpr = Base;
5164 IsArrayExpr = OMPArraySection;
5165 }
5166 }
5167 ELoc = RefExpr->getExprLoc();
5168 ERange = RefExpr->getSourceRange();
5169 RefExpr = RefExpr->IgnoreParenImpCasts();
5170 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5171 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5172 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5173 (S.getCurrentThisType().isNull() || !ME ||
5174 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5175 !isa<FieldDecl>(ME->getMemberDecl()))) {
5176 if (IsArrayExpr != NoArrayExpr) {
5177 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5178 << IsArrayExpr << ERange;
5179 } else if (!DiagType.empty()) {
5180 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5181 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5182 : 0;
5183 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5184 << DiagSelect << DiagType << ERange;
5185 } else {
5186 S.Diag(ELoc,
5187 AllowArraySection
5188 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5189 : diag::err_omp_expected_var_name_member_expr)
5190 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5191 }
5192 return std::make_pair(nullptr, false);
5193 }
5194 return std::make_pair(
5195 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5196}
5197
5198namespace {
5199/// Checks if the allocator is used in uses_allocators clause to be allowed in
5200/// target regions.
5201class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5202 DSAStackTy *S = nullptr;
5203
5204public:
5205 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5206 return S->isUsesAllocatorsDecl(E->getDecl())
5207 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5208 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5209 }
5210 bool VisitStmt(const Stmt *S) {
5211 for (const Stmt *Child : S->children()) {
5212 if (Child && Visit(Child))
5213 return true;
5214 }
5215 return false;
5216 }
5217 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5218};
5219} // namespace
5220
5221static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5222 ArrayRef<OMPClause *> Clauses) {
5223 assert(!S.CurContext->isDependentContext() &&
5224 "Expected non-dependent context.");
5225 auto AllocateRange =
5226 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5227 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5228 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5229 return isOpenMPPrivate(C->getClauseKind());
5230 });
5231 for (OMPClause *Cl : PrivateRange) {
5233 if (Cl->getClauseKind() == OMPC_private) {
5234 auto *PC = cast<OMPPrivateClause>(Cl);
5235 I = PC->private_copies().begin();
5236 It = PC->varlist_begin();
5237 Et = PC->varlist_end();
5238 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5239 auto *PC = cast<OMPFirstprivateClause>(Cl);
5240 I = PC->private_copies().begin();
5241 It = PC->varlist_begin();
5242 Et = PC->varlist_end();
5243 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5244 auto *PC = cast<OMPLastprivateClause>(Cl);
5245 I = PC->private_copies().begin();
5246 It = PC->varlist_begin();
5247 Et = PC->varlist_end();
5248 } else if (Cl->getClauseKind() == OMPC_linear) {
5249 auto *PC = cast<OMPLinearClause>(Cl);
5250 I = PC->privates().begin();
5251 It = PC->varlist_begin();
5252 Et = PC->varlist_end();
5253 } else if (Cl->getClauseKind() == OMPC_reduction) {
5254 auto *PC = cast<OMPReductionClause>(Cl);
5255 I = PC->privates().begin();
5256 It = PC->varlist_begin();
5257 Et = PC->varlist_end();
5258 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5259 auto *PC = cast<OMPTaskReductionClause>(Cl);
5260 I = PC->privates().begin();
5261 It = PC->varlist_begin();
5262 Et = PC->varlist_end();
5263 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5264 auto *PC = cast<OMPInReductionClause>(Cl);
5265 I = PC->privates().begin();
5266 It = PC->varlist_begin();
5267 Et = PC->varlist_end();
5268 } else {
5269 llvm_unreachable("Expected private clause.");
5270 }
5271 for (Expr *E : llvm::make_range(It, Et)) {
5272 if (!*I) {
5273 ++I;
5274 continue;
5275 }
5276 SourceLocation ELoc;
5277 SourceRange ERange;
5278 Expr *SimpleRefExpr = E;
5279 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5280 /*AllowArraySection=*/true);
5281 DeclToCopy.try_emplace(Res.first,
5282 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5283 ++I;
5284 }
5285 }
5286 for (OMPClause *C : AllocateRange) {
5287 auto *AC = cast<OMPAllocateClause>(C);
5288 if (S.getLangOpts().OpenMP >= 50 &&
5289 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5290 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5291 AC->getAllocator()) {
5292 Expr *Allocator = AC->getAllocator();
5293 // OpenMP, 2.12.5 target Construct
5294 // Memory allocators that do not appear in a uses_allocators clause cannot
5295 // appear as an allocator in an allocate clause or be used in the target
5296 // region unless a requires directive with the dynamic_allocators clause
5297 // is present in the same compilation unit.
5298 AllocatorChecker Checker(Stack);
5299 if (Checker.Visit(Allocator))
5300 S.Diag(Allocator->getExprLoc(),
5301 diag::err_omp_allocator_not_in_uses_allocators)
5302 << Allocator->getSourceRange();
5303 }
5304 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5305 getAllocatorKind(S, Stack, AC->getAllocator());
5306 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5307 // For task, taskloop or target directives, allocation requests to memory
5308 // allocators with the trait access set to thread result in unspecified
5309 // behavior.
5310 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5311 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5312 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5313 S.Diag(AC->getAllocator()->getExprLoc(),
5314 diag::warn_omp_allocate_thread_on_task_target_directive)
5315 << getOpenMPDirectiveName(Stack->getCurrentDirective());
5316 }
5317 for (Expr *E : AC->varlist()) {
5318 SourceLocation ELoc;
5319 SourceRange ERange;
5320 Expr *SimpleRefExpr = E;
5321 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5322 ValueDecl *VD = Res.first;
5323 if (!VD)
5324 continue;
5325 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5326 if (!isOpenMPPrivate(Data.CKind)) {
5327 S.Diag(E->getExprLoc(),
5328 diag::err_omp_expected_private_copy_for_allocate);
5329 continue;
5330 }
5331 VarDecl *PrivateVD = DeclToCopy[VD];
5332 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5333 AllocatorKind, AC->getAllocator()))
5334 continue;
5335 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5336 AC->getAlignment(), E->getSourceRange());
5337 }
5338 }
5339}
5340
5341namespace {
5342/// Rewrite statements and expressions for Sema \p Actions CurContext.
5343///
5344/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5345/// context. DeclRefExpr used inside the new context are changed to refer to the
5346/// captured variable instead.
5347class CaptureVars : public TreeTransform<CaptureVars> {
5348 using BaseTransform = TreeTransform<CaptureVars>;
5349
5350public:
5351 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5352
5353 bool AlwaysRebuild() { return true; }
5354};
5355} // namespace
5356
5357static VarDecl *precomputeExpr(Sema &Actions,
5358 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5359 StringRef Name) {
5360 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5361 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5362 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5363 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5364 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5365 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5366 BodyStmts.push_back(NewDeclStmt);
5367 return NewVar;
5368}
5369
5370/// Create a closure that computes the number of iterations of a loop.
5371///
5372/// \param Actions The Sema object.
5373/// \param LogicalTy Type for the logical iteration number.
5374/// \param Rel Comparison operator of the loop condition.
5375/// \param StartExpr Value of the loop counter at the first iteration.
5376/// \param StopExpr Expression the loop counter is compared against in the loop
5377/// condition. \param StepExpr Amount of increment after each iteration.
5378///
5379/// \return Closure (CapturedStmt) of the distance calculation.
5380static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5382 Expr *StartExpr, Expr *StopExpr,
5383 Expr *StepExpr) {
5384 ASTContext &Ctx = Actions.getASTContext();
5385 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5386
5387 // Captured regions currently don't support return values, we use an
5388 // out-parameter instead. All inputs are implicit captures.
5389 // TODO: Instead of capturing each DeclRefExpr occurring in
5390 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5391 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5392 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5393 {StringRef(), QualType()}};
5394 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5395
5396 Stmt *Body;
5397 {
5398 Sema::CompoundScopeRAII CompoundScope(Actions);
5399 CapturedDecl *CS = cast<CapturedDecl>(Actions.CurContext);
5400
5401 // Get the LValue expression for the result.
5402 ImplicitParamDecl *DistParam = CS->getParam(0);
5403 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5404 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5405
5406 SmallVector<Stmt *, 4> BodyStmts;
5407
5408 // Capture all referenced variable references.
5409 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5410 // CapturedStmt, we could compute them before and capture the result, to be
5411 // used jointly with the LoopVar function.
5412 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5413 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5414 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5415 auto BuildVarRef = [&](VarDecl *VD) {
5416 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5417 };
5418
5420 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5422 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5423 Expr *Dist;
5424 if (Rel == BO_NE) {
5425 // When using a != comparison, the increment can be +1 or -1. This can be
5426 // dynamic at runtime, so we need to check for the direction.
5427 Expr *IsNegStep = AssertSuccess(
5428 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5429
5430 // Positive increment.
5431 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5432 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5433 ForwardRange = AssertSuccess(
5434 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5435 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5436 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5437
5438 // Negative increment.
5439 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5440 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5441 BackwardRange = AssertSuccess(
5442 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5443 Expr *NegIncAmount = AssertSuccess(
5444 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5445 Expr *BackwardDist = AssertSuccess(
5446 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5447
5448 // Use the appropriate case.
5449 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5450 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5451 } else {
5452 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5453 "Expected one of these relational operators");
5454
5455 // We can derive the direction from any other comparison operator. It is
5456 // non well-formed OpenMP if Step increments/decrements in the other
5457 // directions. Whether at least the first iteration passes the loop
5458 // condition.
5459 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5460 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5461
5462 // Compute the range between first and last counter value.
5463 Expr *Range;
5464 if (Rel == BO_GE || Rel == BO_GT)
5465 Range = AssertSuccess(Actions.BuildBinOp(
5466 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5467 else
5468 Range = AssertSuccess(Actions.BuildBinOp(
5469 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5470
5471 // Ensure unsigned range space.
5472 Range =
5473 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5474
5475 if (Rel == BO_LE || Rel == BO_GE) {
5476 // Add one to the range if the relational operator is inclusive.
5477 Range =
5478 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5479 }
5480
5481 // Divide by the absolute step amount. If the range is not a multiple of
5482 // the step size, rounding-up the effective upper bound ensures that the
5483 // last iteration is included.
5484 // Note that the rounding-up may cause an overflow in a temporary that
5485 // could be avoided, but would have occurred in a C-style for-loop as
5486 // well.
5487 Expr *Divisor = BuildVarRef(NewStep);
5488 if (Rel == BO_GE || Rel == BO_GT)
5489 Divisor =
5490 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5491 Expr *DivisorMinusOne =
5492 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5493 Expr *RangeRoundUp = AssertSuccess(
5494 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5495 Dist = AssertSuccess(
5496 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5497
5498 // If there is not at least one iteration, the range contains garbage. Fix
5499 // to zero in this case.
5500 Dist = AssertSuccess(
5501 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5502 }
5503
5504 // Assign the result to the out-parameter.
5505 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5506 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5507 BodyStmts.push_back(ResultAssign);
5508
5509 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5510 }
5511
5512 return cast<CapturedStmt>(
5513 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5514}
5515
5516/// Create a closure that computes the loop variable from the logical iteration
5517/// number.
5518///
5519/// \param Actions The Sema object.
5520/// \param LoopVarTy Type for the loop variable used for result value.
5521/// \param LogicalTy Type for the logical iteration number.
5522/// \param StartExpr Value of the loop counter at the first iteration.
5523/// \param Step Amount of increment after each iteration.
5524/// \param Deref Whether the loop variable is a dereference of the loop
5525/// counter variable.
5526///
5527/// \return Closure (CapturedStmt) of the loop value calculation.
5528static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5529 QualType LogicalTy,
5530 DeclRefExpr *StartExpr, Expr *Step,
5531 bool Deref) {
5532 ASTContext &Ctx = Actions.getASTContext();
5533
5534 // Pass the result as an out-parameter. Passing as return value would require
5535 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5536 // invoke a copy constructor.
5537 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5538 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5539 {"Logical", LogicalTy},
5540 {StringRef(), QualType()}};
5541 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5542
5543 // Capture the initial iterator which represents the LoopVar value at the
5544 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5545 // it in every iteration, capture it by value before it is modified.
5546 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5547 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5549 (void)Invalid;
5550 assert(!Invalid && "Expecting capture-by-value to work.");
5551
5552 Expr *Body;
5553 {
5554 Sema::CompoundScopeRAII CompoundScope(Actions);
5555 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5556
5557 ImplicitParamDecl *TargetParam = CS->getParam(0);
5558 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5559 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5560 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5561 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5562 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5563
5564 // Capture the Start expression.
5565 CaptureVars Recap(Actions);
5566 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5567 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5568
5570 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5571 // TODO: Explicitly cast to the iterator's difference_type instead of
5572 // relying on implicit conversion.
5573 Expr *Advanced =
5574 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5575
5576 if (Deref) {
5577 // For range-based for-loops convert the loop counter value to a concrete
5578 // loop variable value by dereferencing the iterator.
5579 Advanced =
5580 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5581 }
5582
5583 // Assign the result to the output parameter.
5584 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5585 BO_Assign, TargetRef, Advanced));
5586 }
5587 return cast<CapturedStmt>(
5588 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5589}
5590
5592 ASTContext &Ctx = getASTContext();
5593
5594 // Extract the common elements of ForStmt and CXXForRangeStmt:
5595 // Loop variable, repeat condition, increment
5596 Expr *Cond, *Inc;
5597 VarDecl *LIVDecl, *LUVDecl;
5598 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5599 Stmt *Init = For->getInit();
5600 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5601 // For statement declares loop variable.
5602 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5603 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5604 // For statement reuses variable.
5605 assert(LCAssign->getOpcode() == BO_Assign &&
5606 "init part must be a loop variable assignment");
5607 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5608 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5609 } else
5610 llvm_unreachable("Cannot determine loop variable");
5611 LUVDecl = LIVDecl;
5612
5613 Cond = For->getCond();
5614 Inc = For->getInc();
5615 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5616 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5617 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5618 LUVDecl = RangeFor->getLoopVariable();
5619
5620 Cond = RangeFor->getCond();
5621 Inc = RangeFor->getInc();
5622 } else
5623 llvm_unreachable("unhandled kind of loop");
5624
5625 QualType CounterTy = LIVDecl->getType();
5626 QualType LVTy = LUVDecl->getType();
5627
5628 // Analyze the loop condition.
5629 Expr *LHS, *RHS;
5630 BinaryOperator::Opcode CondRel;
5631 Cond = Cond->IgnoreImplicit();
5632 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5633 LHS = CondBinExpr->getLHS();
5634 RHS = CondBinExpr->getRHS();
5635 CondRel = CondBinExpr->getOpcode();
5636 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5637 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5638 LHS = CondCXXOp->getArg(0);
5639 RHS = CondCXXOp->getArg(1);
5640 switch (CondCXXOp->getOperator()) {
5641 case OO_ExclaimEqual:
5642 CondRel = BO_NE;
5643 break;
5644 case OO_Less:
5645 CondRel = BO_LT;
5646 break;
5647 case OO_LessEqual:
5648 CondRel = BO_LE;
5649 break;
5650 case OO_Greater:
5651 CondRel = BO_GT;
5652 break;
5653 case OO_GreaterEqual:
5654 CondRel = BO_GE;
5655 break;
5656 default:
5657 llvm_unreachable("unexpected iterator operator");
5658 }
5659 } else
5660 llvm_unreachable("unexpected loop condition");
5661
5662 // Normalize such that the loop counter is on the LHS.
5663 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5664 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5665 std::swap(LHS, RHS);
5666 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5667 }
5668 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5669
5670 // Decide the bit width for the logical iteration counter. By default use the
5671 // unsigned ptrdiff_t integer size (for iterators and pointers).
5672 // TODO: For iterators, use iterator::difference_type,
5673 // std::iterator_traits<>::difference_type or decltype(it - end).
5674 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5675 if (CounterTy->isIntegerType()) {
5676 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5677 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5678 }
5679
5680 // Analyze the loop increment.
5681 Expr *Step;
5682 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5683 int Direction;
5684 switch (IncUn->getOpcode()) {
5685 case UO_PreInc:
5686 case UO_PostInc:
5687 Direction = 1;
5688 break;
5689 case UO_PreDec:
5690 case UO_PostDec:
5691 Direction = -1;
5692 break;
5693 default:
5694 llvm_unreachable("unhandled unary increment operator");
5695 }
5697 Ctx,
5698 llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction, /*isSigned=*/true),
5699 LogicalTy, {});
5700 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5701 if (IncBin->getOpcode() == BO_AddAssign) {
5702 Step = IncBin->getRHS();
5703 } else if (IncBin->getOpcode() == BO_SubAssign) {
5704 Step = AssertSuccess(
5705 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5706 } else
5707 llvm_unreachable("unhandled binary increment operator");
5708 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5709 switch (CondCXXOp->getOperator()) {
5710 case OO_PlusPlus:
5712 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5713 break;
5714 case OO_MinusMinus:
5716 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5717 break;
5718 case OO_PlusEqual:
5719 Step = CondCXXOp->getArg(1);
5720 break;
5721 case OO_MinusEqual:
5722 Step = AssertSuccess(
5723 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5724 break;
5725 default:
5726 llvm_unreachable("unhandled overloaded increment operator");
5727 }
5728 } else
5729 llvm_unreachable("unknown increment expression");
5730
5731 CapturedStmt *DistanceFunc =
5732 buildDistanceFunc(SemaRef, LogicalTy, CondRel, LHS, RHS, Step);
5733 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5734 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5735 DeclRefExpr *LVRef =
5736 SemaRef.BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue, {},
5737 nullptr, nullptr, {}, nullptr);
5738 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
5739 LoopVarFunc, LVRef);
5740}
5741
5743 // Handle a literal loop.
5744 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5745 return ActOnOpenMPCanonicalLoop(AStmt);
5746
5747 // If not a literal loop, it must be the result of a loop transformation.
5748 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(AStmt);
5749 assert(
5751 "Loop transformation directive expected");
5752 return LoopTransform;
5753}
5754
5756 CXXScopeSpec &MapperIdScopeSpec,
5757 const DeclarationNameInfo &MapperId,
5758 QualType Type,
5759 Expr *UnresolvedMapper);
5760
5761/// Perform DFS through the structure/class data members trying to find
5762/// member(s) with user-defined 'default' mapper and generate implicit map
5763/// clauses for such members with the found 'default' mapper.
5764static void
5767 // Check for the default mapper for data members.
5768 if (S.getLangOpts().OpenMP < 50)
5769 return;
5770 SmallVector<OMPClause *, 4> ImplicitMaps;
5771 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5772 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5773 if (!C)
5774 continue;
5775 SmallVector<Expr *, 4> SubExprs;
5776 auto *MI = C->mapperlist_begin();
5777 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
5778 ++I, ++MI) {
5779 // Expression is mapped using mapper - skip it.
5780 if (*MI)
5781 continue;
5782 Expr *E = *I;
5783 // Expression is dependent - skip it, build the mapper when it gets
5784 // instantiated.
5785 if (E->isTypeDependent() || E->isValueDependent() ||
5787 continue;
5788 // Array section - need to check for the mapping of the array section
5789 // element.
5790 QualType CanonType = E->getType().getCanonicalType();
5791 if (CanonType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
5792 const auto *OASE = cast<ArraySectionExpr>(E->IgnoreParenImpCasts());
5793 QualType BaseType =
5795 QualType ElemType;
5796 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
5797 ElemType = ATy->getElementType();
5798 else
5799 ElemType = BaseType->getPointeeType();
5800 CanonType = ElemType;
5801 }
5802
5803 // DFS over data members in structures/classes.
5805 1, {CanonType, nullptr});
5806 llvm::DenseMap<const Type *, Expr *> Visited;
5808 1, {nullptr, 1});
5809 while (!Types.empty()) {
5810 QualType BaseType;
5811 FieldDecl *CurFD;
5812 std::tie(BaseType, CurFD) = Types.pop_back_val();
5813 while (ParentChain.back().second == 0)
5814 ParentChain.pop_back();
5815 --ParentChain.back().second;
5816 if (BaseType.isNull())
5817 continue;
5818 // Only structs/classes are allowed to have mappers.
5819 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
5820 if (!RD)
5821 continue;
5822 auto It = Visited.find(BaseType.getTypePtr());
5823 if (It == Visited.end()) {
5824 // Try to find the associated user-defined mapper.
5825 CXXScopeSpec MapperIdScopeSpec;
5826 DeclarationNameInfo DefaultMapperId;
5828 &S.Context.Idents.get("default")));
5829 DefaultMapperId.setLoc(E->getExprLoc());
5831 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
5832 BaseType, /*UnresolvedMapper=*/nullptr);
5833 if (ER.isInvalid())
5834 continue;
5835 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
5836 }
5837 // Found default mapper.
5838 if (It->second) {
5839 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
5841 OE->setIsUnique(/*V=*/true);
5842 Expr *BaseExpr = OE;
5843 for (const auto &P : ParentChain) {
5844 if (P.first) {
5845 BaseExpr = S.BuildMemberExpr(
5846 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
5848 DeclAccessPair::make(P.first, P.first->getAccess()),
5849 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
5850 P.first->getType(), VK_LValue, OK_Ordinary);
5851 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
5852 }
5853 }
5854 if (CurFD)
5855 BaseExpr = S.BuildMemberExpr(
5856 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
5858 DeclAccessPair::make(CurFD, CurFD->getAccess()),
5859 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
5860 CurFD->getType(), VK_LValue, OK_Ordinary);
5861 SubExprs.push_back(BaseExpr);
5862 continue;
5863 }
5864 // Check for the "default" mapper for data members.
5865 bool FirstIter = true;
5866 for (FieldDecl *FD : RD->fields()) {
5867 if (!FD)
5868 continue;
5869 QualType FieldTy = FD->getType();
5870 if (FieldTy.isNull() ||
5871 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
5872 continue;
5873 if (FirstIter) {
5874 FirstIter = false;
5875 ParentChain.emplace_back(CurFD, 1);
5876 } else {
5877 ++ParentChain.back().second;
5878 }
5879 Types.emplace_back(FieldTy, FD);
5880 }
5881 }
5882 }
5883 if (SubExprs.empty())
5884 continue;
5885 CXXScopeSpec MapperIdScopeSpec;
5886 DeclarationNameInfo MapperId;
5887 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
5888 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
5889 MapperIdScopeSpec, MapperId, C->getMapType(),
5890 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
5891 SubExprs, OMPVarListLocTy()))
5892 Clauses.push_back(NewClause);
5893 }
5894}
5895
5896namespace {
5897/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
5898/// call in the associated loop-nest cannot be a 'parallel for'.
5899class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
5900 Sema &SemaRef;
5901
5902public:
5903 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
5904
5905 // Is there a nested OpenMP loop bind(parallel)
5906 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
5907 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
5908 if (const auto *C = D->getSingleClause<OMPBindClause>())
5909 if (C->getBindKind() == OMPC_BIND_parallel) {
5910 TeamsLoopCanBeParallelFor = false;
5911 // No need to continue visiting any more
5912 return;
5913 }
5914 }
5915 for (const Stmt *Child : D->children())
5916 if (Child)
5917 Visit(Child);
5918 }
5919
5920 void VisitCallExpr(const CallExpr *C) {
5921 // Function calls inhibit parallel loop translation of 'target teams loop'
5922 // unless the assume-no-nested-parallelism flag has been specified.
5923 // OpenMP API runtime library calls do not inhibit parallel loop
5924 // translation, regardless of the assume-no-nested-parallelism.
5925 bool IsOpenMPAPI = false;
5926 auto *FD = dyn_cast_or_null<FunctionDecl>(C->getCalleeDecl());
5927 if (FD) {
5928 std::string Name = FD->getNameInfo().getAsString();
5929 IsOpenMPAPI = Name.find("omp_") == 0;
5930 }
5931 TeamsLoopCanBeParallelFor =
5932 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
5933 if (!TeamsLoopCanBeParallelFor)
5934 return;
5935
5936 for (const Stmt *Child : C->children())
5937 if (Child)
5938 Visit(Child);
5939 }
5940
5941 void VisitCapturedStmt(const CapturedStmt *S) {
5942 if (!S)
5943 return;
5944 Visit(S->getCapturedDecl()->getBody());
5945 }
5946
5947 void VisitStmt(const Stmt *S) {
5948 if (!S)
5949 return;
5950 for (const Stmt *Child : S->children())
5951 if (Child)
5952 Visit(Child);
5953 }
5954 explicit TeamsLoopChecker(Sema &SemaRef)
5955 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
5956
5957private:
5958 bool TeamsLoopCanBeParallelFor;
5959};
5960} // namespace
5961
5962static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
5963 TeamsLoopChecker Checker(SemaRef);
5964 Checker.Visit(AStmt);
5965 return Checker.teamsLoopCanBeParallelFor();
5966}
5967
5969 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
5970 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
5971 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
5972 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
5973
5974 StmtResult Res = StmtError();
5976 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
5977
5978 if (const OMPBindClause *BC =
5979 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
5980 BindKind = BC->getBindKind();
5981
5982 if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
5983 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
5984
5985 // Setting the enclosing teams or parallel construct for the loop
5986 // directive without bind clause.
5987 // [5.0:129:25-28] If the bind clause is not present on the construct and
5988 // the loop construct is closely nested inside a teams or parallel
5989 // construct, the binding region is the corresponding teams or parallel
5990 // region. If none of those conditions hold, the binding region is not
5991 // defined.
5992 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
5993 ArrayRef<OpenMPDirectiveKind> ParentLeafs =
5994 getLeafConstructsOrSelf(ParentDirective);
5995
5996 if (ParentDirective == OMPD_unknown) {
5997 Diag(DSAStack->getDefaultDSALocation(),
5998 diag::err_omp_bind_required_on_loop);
5999 } else if (ParentLeafs.back() == OMPD_parallel) {
6000 BindKind = OMPC_BIND_parallel;
6001 } else if (ParentLeafs.back() == OMPD_teams) {
6002 BindKind = OMPC_BIND_teams;
6003 }
6004
6005 assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind");
6006
6007 OMPClause *C =
6010 ClausesWithImplicit.push_back(C);
6011 }
6012
6013 // Diagnose "loop bind(teams)" with "reduction".
6014 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6015 for (OMPClause *C : Clauses) {
6016 if (C->getClauseKind() == OMPC_reduction)
6017 Diag(DSAStack->getDefaultDSALocation(),
6018 diag::err_omp_loop_reduction_clause);
6019 }
6020 }
6021
6022 // First check CancelRegion which is then used in checkNestingOfRegions.
6023 if (checkCancelRegion(SemaRef, Kind, CancelRegion, StartLoc) ||
6024 checkNestingOfRegions(SemaRef, DSAStack, Kind, DirName, CancelRegion,
6025 BindKind, StartLoc)) {
6026 return StmtError();
6027 }
6028
6029 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6032 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6033
6034 VarsWithInheritedDSAType VarsWithInheritedDSA;
6035 bool ErrorFound = false;
6036 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6037
6038 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6040 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6041
6042 // Check default data sharing attributes for referenced variables.
6043 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(AStmt));
6044 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6045 Stmt *S = AStmt;
6046 while (--ThisCaptureLevel >= 0)
6047 S = cast<CapturedStmt>(S)->getCapturedStmt();
6048 DSAChecker.Visit(S);
6050 !isOpenMPTaskingDirective(Kind)) {
6051 // Visit subcaptures to generate implicit clauses for captured vars.
6052 auto *CS = cast<CapturedStmt>(AStmt);
6054 getOpenMPCaptureRegions(CaptureRegions, Kind);
6055 // Ignore outer tasking regions for target directives.
6056 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6057 CS = cast<CapturedStmt>(CS->getCapturedStmt());
6058 DSAChecker.visitSubCaptures(CS);
6059 }
6060 if (DSAChecker.isErrorFound())
6061 return StmtError();
6062 // Generate list of implicitly defined firstprivate variables.
6063 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6064 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6065
6067 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6068 // Get the original location of present modifier from Defaultmap clause.
6069 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6070 for (OMPClause *C : Clauses) {
6071 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6072 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6073 PresentModifierLocs[DMC->getDefaultmapKind()] =
6074 DMC->getDefaultmapModifierLoc();
6075 }
6076
6078 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6080 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[K]),
6081 ImpInfo.MapModifiers[K].size(), PresentModifierLocs[K]);
6082 }
6083 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6084 for (OMPClause *C : Clauses) {
6085 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6086 for (Expr *E : IRC->taskgroup_descriptors())
6087 if (E)
6088 ImpInfo.Firstprivates.insert(E);
6089 }
6090 // OpenMP 5.0, 2.10.1 task Construct
6091 // [detach clause]... The event-handle will be considered as if it was
6092 // specified on a firstprivate clause.
6093 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6094 ImpInfo.Firstprivates.insert(DC->getEventHandler());
6095 }
6096 if (!ImpInfo.Firstprivates.empty()) {
6098 ImpInfo.Firstprivates.getArrayRef(), SourceLocation(),
6100 ClausesWithImplicit.push_back(Implicit);
6101 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6102 ImpInfo.Firstprivates.size();
6103 } else {
6104 ErrorFound = true;
6105 }
6106 }
6107 if (!ImpInfo.Privates.empty()) {
6109 ImpInfo.Privates.getArrayRef(), SourceLocation(),
6111 ClausesWithImplicit.push_back(Implicit);
6112 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6113 ImpInfo.Privates.size();
6114 } else {
6115 ErrorFound = true;
6116 }
6117 }
6118 // OpenMP 5.0 [2.19.7]
6119 // If a list item appears in a reduction, lastprivate or linear
6120 // clause on a combined target construct then it is treated as
6121 // if it also appears in a map clause with a map-type of tofrom
6122 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6124 SmallVector<Expr *, 4> ImplicitExprs;
6125 for (OMPClause *C : Clauses) {
6126 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6127 for (Expr *E : RC->varlist())
6128 if (!isa<DeclRefExpr>(E->IgnoreParenImpCasts()))
6129 ImplicitExprs.emplace_back(E);
6130 }
6131 if (!ImplicitExprs.empty()) {
6132 ArrayRef<Expr *> Exprs = ImplicitExprs;
6133 CXXScopeSpec MapperIdScopeSpec;
6134 DeclarationNameInfo MapperId;
6137 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6138 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6139 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6140 ClausesWithImplicit.emplace_back(Implicit);
6141 }
6142 }
6143 for (unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6144 int ClauseKindCnt = -1;
6145 for (unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6146 ArrayRef<Expr *> ImplicitMap = ImpInfo.Mappings[I][J].getArrayRef();
6147 ++ClauseKindCnt;
6148 if (ImplicitMap.empty())
6149 continue;
6150 CXXScopeSpec MapperIdScopeSpec;
6151 DeclarationNameInfo MapperId;
6152 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6154 nullptr, ImpInfo.MapModifiers[I], ImplicitMapModifiersLoc[I],
6155 MapperIdScopeSpec, MapperId, K, /*IsMapTypeImplicit=*/true,
6156 SourceLocation(), SourceLocation(), ImplicitMap,
6157 OMPVarListLocTy())) {
6158 ClausesWithImplicit.emplace_back(Implicit);
6159 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6160 ImplicitMap.size();
6161 } else {
6162 ErrorFound = true;
6163 }
6164 }
6165 }
6166 // Build expressions for implicit maps of data members with 'default'
6167 // mappers.
6168 if (getLangOpts().OpenMP >= 50)
6170 ClausesWithImplicit);
6171 }
6172
6173 switch (Kind) {
6174 case OMPD_parallel:
6175 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6176 EndLoc);
6177 break;
6178 case OMPD_simd:
6179 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6180 VarsWithInheritedDSA);
6181 break;
6182 case OMPD_tile:
6183 Res =
6184 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6185 break;
6186 case OMPD_unroll:
6187 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6188 EndLoc);
6189 break;
6190 case OMPD_reverse:
6191 assert(ClausesWithImplicit.empty() &&
6192 "reverse directive does not support any clauses");
6193 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6194 break;
6195 case OMPD_interchange:
6196 Res = ActOnOpenMPInterchangeDirective(ClausesWithImplicit, AStmt, StartLoc,
6197 EndLoc);
6198 break;
6199 case OMPD_for:
6200 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6201 VarsWithInheritedDSA);
6202 break;
6203 case OMPD_for_simd:
6204 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6205 EndLoc, VarsWithInheritedDSA);
6206 break;
6207 case OMPD_sections:
6208 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6209 EndLoc);
6210 break;
6211 case OMPD_section:
6212 assert(ClausesWithImplicit.empty() &&
6213 "No clauses are allowed for 'omp section' directive");
6214 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6215 break;
6216 case OMPD_single:
6217 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6218 EndLoc);
6219 break;
6220 case OMPD_master:
6221 assert(ClausesWithImplicit.empty() &&
6222 "No clauses are allowed for 'omp master' directive");
6223 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6224 break;
6225 case OMPD_masked:
6226 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6227 EndLoc);
6228 break;
6229 case OMPD_critical:
6230 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6231 StartLoc, EndLoc);
6232 break;
6233 case OMPD_parallel_for:
6234 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6235 EndLoc, VarsWithInheritedDSA);
6236 break;
6237 case OMPD_parallel_for_simd:
6239 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6240 break;
6241 case OMPD_scope:
6242 Res =
6243 ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6244 break;
6245 case OMPD_parallel_master:
6246 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6247 StartLoc, EndLoc);
6248 break;
6249 case OMPD_parallel_masked:
6250 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6251 StartLoc, EndLoc);
6252 break;
6253 case OMPD_parallel_sections:
6254 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6255 StartLoc, EndLoc);
6256 break;
6257 case OMPD_task:
6258 Res =
6259 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6260 break;
6261 case OMPD_taskyield:
6262 assert(ClausesWithImplicit.empty() &&
6263 "No clauses are allowed for 'omp taskyield' directive");
6264 assert(AStmt == nullptr &&
6265 "No associated statement allowed for 'omp taskyield' directive");
6266 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6267 break;
6268 case OMPD_error:
6269 assert(AStmt == nullptr &&
6270 "No associated statement allowed for 'omp error' directive");
6271 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6272 break;
6273 case OMPD_barrier:
6274 assert(ClausesWithImplicit.empty() &&
6275 "No clauses are allowed for 'omp barrier' directive");
6276 assert(AStmt == nullptr &&
6277 "No associated statement allowed for 'omp barrier' directive");
6278 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6279 break;
6280 case OMPD_taskwait:
6281 assert(AStmt == nullptr &&
6282 "No associated statement allowed for 'omp taskwait' directive");
6283 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6284 break;
6285 case OMPD_taskgroup:
6286 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6287 EndLoc);
6288 break;
6289 case OMPD_flush:
6290 assert(AStmt == nullptr &&
6291 "No associated statement allowed for 'omp flush' directive");
6292 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6293 break;
6294 case OMPD_depobj:
6295 assert(AStmt == nullptr &&
6296 "No associated statement allowed for 'omp depobj' directive");
6297 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6298 break;
6299 case OMPD_scan:
6300 assert(AStmt == nullptr &&
6301 "No associated statement allowed for 'omp scan' directive");
6302 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6303 break;
6304 case OMPD_ordered:
6305 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6306 EndLoc);
6307 break;
6308 case OMPD_atomic:
6309 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6310 EndLoc);
6311 break;
6312 case OMPD_teams:
6313 Res =
6314 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6315 break;
6316 case OMPD_target:
6317 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6318 EndLoc);
6319 break;
6320 case OMPD_target_parallel:
6321 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6322 StartLoc, EndLoc);
6323 break;
6324 case OMPD_target_parallel_for:
6326 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6327 break;
6328 case OMPD_cancellation_point:
6329 assert(ClausesWithImplicit.empty() &&
6330 "No clauses are allowed for 'omp cancellation point' directive");
6331 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6332 "cancellation point' directive");
6333 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6334 break;
6335 case OMPD_cancel:
6336 assert(AStmt == nullptr &&
6337 "No associated statement allowed for 'omp cancel' directive");
6338 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6339 CancelRegion);
6340 break;
6341 case OMPD_target_data:
6342 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6343 EndLoc);
6344 break;
6345 case OMPD_target_enter_data:
6346 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6347 EndLoc, AStmt);
6348 break;
6349 case OMPD_target_exit_data:
6350 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6351 EndLoc, AStmt);
6352 break;
6353 case OMPD_taskloop:
6354 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6355 EndLoc, VarsWithInheritedDSA);
6356 break;
6357 case OMPD_taskloop_simd:
6358 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6359 EndLoc, VarsWithInheritedDSA);
6360 break;
6361 case OMPD_master_taskloop:
6363 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6364 break;
6365 case OMPD_masked_taskloop:
6367 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6368 break;
6369 case OMPD_master_taskloop_simd:
6371 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6372 break;
6373 case OMPD_masked_taskloop_simd:
6375 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6376 break;
6377 case OMPD_parallel_master_taskloop:
6379 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6380 break;
6381 case OMPD_parallel_masked_taskloop:
6383 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6384 break;
6385 case OMPD_parallel_master_taskloop_simd:
6387 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6388 break;
6389 case OMPD_parallel_masked_taskloop_simd:
6391 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6392 break;
6393 case OMPD_distribute:
6394 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6395 EndLoc, VarsWithInheritedDSA);
6396 break;
6397 case OMPD_target_update:
6398 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6399 EndLoc, AStmt);
6400 break;
6401 case OMPD_distribute_parallel_for:
6403 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6404 break;
6405 case OMPD_distribute_parallel_for_simd:
6407 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6408 break;
6409 case OMPD_distribute_simd:
6411 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6412 break;
6413 case OMPD_target_parallel_for_simd:
6415 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6416 break;
6417 case OMPD_target_simd:
6418 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6419 EndLoc, VarsWithInheritedDSA);
6420 break;
6421 case OMPD_teams_distribute:
6423 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6424 break;
6425 case OMPD_teams_distribute_simd:
6427 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6428 break;
6429 case OMPD_teams_distribute_parallel_for_simd:
6431 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6432 break;
6433 case OMPD_teams_distribute_parallel_for:
6435 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6436 break;
6437 case OMPD_target_teams:
6438 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6439 EndLoc);
6440 break;
6441 case OMPD_target_teams_distribute:
6443 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6444 break;
6445 case OMPD_target_teams_distribute_parallel_for:
6447 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6448 break;
6449 case OMPD_target_teams_distribute_parallel_for_simd:
6451 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6452 break;
6453 case OMPD_target_teams_distribute_simd:
6455 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6456 break;
6457 case OMPD_interop:
6458 assert(AStmt == nullptr &&
6459 "No associated statement allowed for 'omp interop' directive");
6460 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6461 break;
6462 case OMPD_dispatch:
6463 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6464 EndLoc);
6465 break;
6466 case OMPD_loop:
6467 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6468 EndLoc, VarsWithInheritedDSA);
6469 break;
6470 case OMPD_teams_loop:
6472 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6473 break;
6474 case OMPD_target_teams_loop:
6476 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6477 break;
6478 case OMPD_parallel_loop:
6480 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6481 break;
6482 case OMPD_target_parallel_loop:
6484 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6485 break;
6486 case OMPD_declare_target:
6487 case OMPD_end_declare_target:
6488 case OMPD_threadprivate:
6489 case OMPD_allocate:
6490 case OMPD_declare_reduction:
6491 case OMPD_declare_mapper:
6492 case OMPD_declare_simd:
6493 case OMPD_requires:
6494 case OMPD_declare_variant:
6495 case OMPD_begin_declare_variant:
6496 case OMPD_end_declare_variant:
6497 llvm_unreachable("OpenMP Directive is not allowed");
6498 case OMPD_unknown:
6499 default:
6500 llvm_unreachable("Unknown OpenMP directive");
6501 }
6502
6503 ErrorFound = Res.isInvalid() || ErrorFound;
6504
6505 // Check variables in the clauses if default(none) or
6506 // default(firstprivate) was specified.
6507 if (DSAStack->getDefaultDSA() == DSA_none ||
6508 DSAStack->getDefaultDSA() == DSA_private ||
6509 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6510 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6511 for (OMPClause *C : Clauses) {
6512 switch (C->getClauseKind()) {
6513 case OMPC_num_threads:
6514 case OMPC_dist_schedule:
6515 // Do not analyze if no parent teams directive.
6516 if (isOpenMPTeamsDirective(Kind))
6517 break;
6518 continue;
6519 case OMPC_if:
6520 if (isOpenMPTeamsDirective(Kind) &&
6521 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6522 break;
6523 if (isOpenMPParallelDirective(Kind) &&
6525 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6526 break;
6527 continue;
6528 case OMPC_schedule:
6529 case OMPC_detach:
6530 break;
6531 case OMPC_grainsize:
6532 case OMPC_num_tasks:
6533 case OMPC_final:
6534 case OMPC_priority:
6535 case OMPC_novariants:
6536 case OMPC_nocontext:
6537 // Do not analyze if no parent parallel directive.
6538 if (isOpenMPParallelDirective(Kind))
6539 break;
6540 continue;
6541 case OMPC_ordered:
6542 case OMPC_device:
6543 case OMPC_num_teams:
6544 case OMPC_thread_limit:
6545 case OMPC_hint:
6546 case OMPC_collapse:
6547 case OMPC_safelen:
6548 case OMPC_simdlen:
6549 case OMPC_sizes:
6550 case OMPC_default:
6551 case OMPC_proc_bind:
6552 case OMPC_private:
6553 case OMPC_firstprivate:
6554 case OMPC_lastprivate:
6555 case OMPC_shared:
6556 case OMPC_reduction:
6557 case OMPC_task_reduction:
6558 case OMPC_in_reduction:
6559 case OMPC_linear:
6560 case OMPC_aligned:
6561 case OMPC_copyin:
6562 case OMPC_copyprivate:
6563 case OMPC_nowait:
6564 case OMPC_untied:
6565 case OMPC_mergeable:
6566 case OMPC_allocate:
6567 case OMPC_read:
6568 case OMPC_write:
6569 case OMPC_update:
6570 case OMPC_capture:
6571 case OMPC_compare:
6572 case OMPC_seq_cst:
6573 case OMPC_acq_rel:
6574 case OMPC_acquire:
6575 case OMPC_release:
6576 case OMPC_relaxed:
6577 case OMPC_depend:
6578 case OMPC_threads:
6579 case OMPC_simd:
6580 case OMPC_map:
6581 case OMPC_nogroup:
6582 case OMPC_defaultmap:
6583 case OMPC_to:
6584 case OMPC_from:
6585 case OMPC_use_device_ptr:
6586 case OMPC_use_device_addr:
6587 case OMPC_is_device_ptr:
6588 case OMPC_has_device_addr:
6589 case OMPC_nontemporal:
6590 case OMPC_order:
6591 case OMPC_destroy:
6592 case OMPC_inclusive:
6593 case OMPC_exclusive:
6594 case OMPC_uses_allocators:
6595 case OMPC_affinity:
6596 case OMPC_bind:
6597 case OMPC_filter:
6598 continue;
6599 case OMPC_allocator:
6600 case OMPC_flush:
6601 case OMPC_depobj:
6602 case OMPC_threadprivate:
6603 case OMPC_uniform:
6604 case OMPC_unknown:
6605 case OMPC_unified_address:
6606 case OMPC_unified_shared_memory:
6607 case OMPC_reverse_offload:
6608 case OMPC_dynamic_allocators:
6609 case OMPC_atomic_default_mem_order:
6610 case OMPC_device_type:
6611 case OMPC_match:
6612 case OMPC_when:
6613 case OMPC_at:
6614 case OMPC_severity:
6615 case OMPC_message:
6616 default:
6617 llvm_unreachable("Unexpected clause");
6618 }
6619 for (Stmt *CC : C->children()) {
6620 if (CC)
6621 DSAChecker.Visit(CC);
6622 }
6623 }
6624 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6625 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6626 }
6627 for (const auto &P : VarsWithInheritedDSA) {
6628 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6629 continue;
6630 ErrorFound = true;
6631 if (DSAStack->getDefaultDSA() == DSA_none ||
6632 DSAStack->getDefaultDSA() == DSA_private ||
6633 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6634 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6635 << P.first << P.second->getSourceRange();
6636 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6637 } else if (getLangOpts().OpenMP >= 50) {
6638 Diag(P.second->getExprLoc(),
6639 diag::err_omp_defaultmap_no_attr_for_variable)
6640 << P.first << P.second->getSourceRange();
6641 Diag(DSAStack->getDefaultDSALocation(),
6642 diag::note_omp_defaultmap_attr_none);
6643 }
6644 }
6645
6646 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6647 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(Kind)) {
6648 if (isAllowedClauseForDirective(D, OMPC_if, getLangOpts().OpenMP))
6649 AllowedNameModifiers.push_back(D);
6650 }
6651 if (!AllowedNameModifiers.empty())
6652 ErrorFound = checkIfClauses(SemaRef, Kind, Clauses, AllowedNameModifiers) ||
6653 ErrorFound;
6654
6655 if (ErrorFound)
6656 return StmtError();
6657
6660 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6661 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6662 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6663 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6664 // Register target to DSA Stack.
6665 DSAStack->addTargetDirLocation(StartLoc);
6666 }
6667
6668 return Res;
6669}
6670
6672 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6673 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6674 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6675 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6676 assert(Aligneds.size() == Alignments.size());
6677 assert(Linears.size() == LinModifiers.size());
6678 assert(Linears.size() == Steps.size());
6679 if (!DG || DG.get().isNull())
6680 return DeclGroupPtrTy();
6681
6682 const int SimdId = 0;
6683 if (!DG.get().isSingleDecl()) {
6684 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6685 << SimdId;
6686 return DG;
6687 }
6688 Decl *ADecl = DG.get().getSingleDecl();
6689 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6690 ADecl = FTD->getTemplatedDecl();
6691
6692 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6693 if (!FD) {
6694 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6695 return DeclGroupPtrTy();
6696 }
6697
6698 // OpenMP [2.8.2, declare simd construct, Description]
6699 // The parameter of the simdlen clause must be a constant positive integer
6700 // expression.
6701 ExprResult SL;
6702 if (Simdlen)
6703 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6704 // OpenMP [2.8.2, declare simd construct, Description]
6705 // The special this pointer can be used as if was one of the arguments to the
6706 // function in any of the linear, aligned, or uniform clauses.
6707 // The uniform clause declares one or more arguments to have an invariant
6708 // value for all concurrent invocations of the function in the execution of a
6709 // single SIMD loop.
6710 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6711 const Expr *UniformedLinearThis = nullptr;
6712 for (const Expr *E : Uniforms) {
6713 E = E->IgnoreParenImpCasts();
6714 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6715 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6716 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6717 FD->getParamDecl(PVD->getFunctionScopeIndex())
6718 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
6719 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6720 continue;
6721 }
6722 if (isa<CXXThisExpr>(E)) {
6723 UniformedLinearThis = E;
6724 continue;
6725 }
6726 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6727 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6728 }
6729 // OpenMP [2.8.2, declare simd construct, Description]
6730 // The aligned clause declares that the object to which each list item points
6731 // is aligned to the number of bytes expressed in the optional parameter of
6732 // the aligned clause.
6733 // The special this pointer can be used as if was one of the arguments to the
6734 // function in any of the linear, aligned, or uniform clauses.
6735 // The type of list items appearing in the aligned clause must be array,
6736 // pointer, reference to array, or reference to pointer.
6737 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6738 const Expr *AlignedThis = nullptr;
6739 for (const Expr *E : Aligneds) {
6740 E = E->IgnoreParenImpCasts();
6741 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6742 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6743 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6744 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6745 FD->getParamDecl(PVD->getFunctionScopeIndex())
6746 ->getCanonicalDecl() == CanonPVD) {
6747 // OpenMP [2.8.1, simd construct, Restrictions]
6748 // A list-item cannot appear in more than one aligned clause.
6749 if (AlignedArgs.count(CanonPVD) > 0) {
6750 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6751 << 1 << getOpenMPClauseName(OMPC_aligned)
6752 << E->getSourceRange();
6753 Diag(AlignedArgs[CanonPVD]->getExprLoc(),
6754 diag::note_omp_explicit_dsa)
6755 << getOpenMPClauseName(OMPC_aligned);
6756 continue;
6757 }
6758 AlignedArgs[CanonPVD] = E;
6759 QualType QTy = PVD->getType()
6760 .getNonReferenceType()
6761 .getUnqualifiedType()
6762 .getCanonicalType();
6763 const Type *Ty = QTy.getTypePtrOrNull();
6764 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
6765 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
6766 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
6767 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6768 }
6769 continue;
6770 }
6771 }
6772 if (isa<CXXThisExpr>(E)) {
6773 if (AlignedThis) {
6774 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6775 << 2 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange();
6776 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
6777 << getOpenMPClauseName(OMPC_aligned);
6778 }
6779 AlignedThis = E;
6780 continue;
6781 }
6782 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6783 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6784 }
6785 // The optional parameter of the aligned clause, alignment, must be a constant
6786 // positive integer expression. If no optional parameter is specified,
6787 // implementation-defined default alignments for SIMD instructions on the
6788 // target platforms are assumed.
6790 for (Expr *E : Alignments) {
6791 ExprResult Align;
6792 if (E)
6793 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
6794 NewAligns.push_back(Align.get());
6795 }
6796 // OpenMP [2.8.2, declare simd construct, Description]
6797 // The linear clause declares one or more list items to be private to a SIMD
6798 // lane and to have a linear relationship with respect to the iteration space
6799 // of a loop.
6800 // The special this pointer can be used as if was one of the arguments to the
6801 // function in any of the linear, aligned, or uniform clauses.
6802 // When a linear-step expression is specified in a linear clause it must be
6803 // either a constant integer expression or an integer-typed parameter that is
6804 // specified in a uniform clause on the directive.
6805 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
6806 const bool IsUniformedThis = UniformedLinearThis != nullptr;
6807 auto MI = LinModifiers.begin();
6808 for (const Expr *E : Linears) {
6809 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
6810 ++MI;
6811 E = E->IgnoreParenImpCasts();
6812 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6813 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6814 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6815 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6816 FD->getParamDecl(PVD->getFunctionScopeIndex())
6817 ->getCanonicalDecl() == CanonPVD) {
6818 // OpenMP [2.15.3.7, linear Clause, Restrictions]
6819 // A list-item cannot appear in more than one linear clause.
6820 if (LinearArgs.count(CanonPVD) > 0) {
6821 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6822 << getOpenMPClauseName(OMPC_linear)
6823 << getOpenMPClauseName(OMPC_linear) << E->getSourceRange();
6824 Diag(LinearArgs[CanonPVD]->getExprLoc(),
6825 diag::note_omp_explicit_dsa)
6826 << getOpenMPClauseName(OMPC_linear);
6827 continue;
6828 }
6829 // Each argument can appear in at most one uniform or linear clause.
6830 if (UniformedArgs.count(CanonPVD) > 0) {
6831 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6832 << getOpenMPClauseName(OMPC_linear)
6833 << getOpenMPClauseName(OMPC_uniform) << E->getSourceRange();
6834 Diag(UniformedArgs[CanonPVD]->getExprLoc(),
6835 diag::note_omp_explicit_dsa)
6836 << getOpenMPClauseName(OMPC_uniform);
6837 continue;
6838 }
6839 LinearArgs[CanonPVD] = E;
6840 if (E->isValueDependent() || E->isTypeDependent() ||
6843 continue;
6844 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
6845 PVD->getOriginalType(),
6846 /*IsDeclareSimd=*/true);
6847 continue;
6848 }
6849 }
6850 if (isa<CXXThisExpr>(E)) {
6851 if (UniformedLinearThis) {
6852 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6853 << getOpenMPClauseName(OMPC_linear)
6854 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear)
6855 << E->getSourceRange();
6856 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
6857 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform
6858 : OMPC_linear);
6859 continue;
6860 }
6861 UniformedLinearThis = E;
6862 if (E->isValueDependent() || E->isTypeDependent() ||
6864 continue;
6865 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
6866 E->getType(), /*IsDeclareSimd=*/true);
6867 continue;
6868 }
6869 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6870 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6871 }
6872 Expr *Step = nullptr;
6873 Expr *NewStep = nullptr;
6874 SmallVector<Expr *, 4> NewSteps;
6875 for (Expr *E : Steps) {
6876 // Skip the same step expression, it was checked already.
6877 if (Step == E || !E) {
6878 NewSteps.push_back(E ? NewStep : nullptr);
6879 continue;
6880 }
6881 Step = E;
6882 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
6883 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6884 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6885 if (UniformedArgs.count(CanonPVD) == 0) {
6886 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
6887 << Step->getSourceRange();
6888 } else if (E->isValueDependent() || E->isTypeDependent() ||
6891 CanonPVD->getType()->hasIntegerRepresentation()) {
6892 NewSteps.push_back(Step);
6893 } else {
6894 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
6895 << Step->getSourceRange();
6896 }
6897 continue;
6898 }
6899 NewStep = Step;
6900 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
6901 !Step->isInstantiationDependent() &&
6903 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
6904 .get();
6905 if (NewStep)
6906 NewStep = SemaRef
6908 NewStep, /*FIXME*/ Sema::AllowFold)
6909 .get();
6910 }
6911 NewSteps.push_back(NewStep);
6912 }
6913 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
6914 getASTContext(), BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
6915 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
6916 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
6917 const_cast<Expr **>(Linears.data()), Linears.size(),
6918 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
6919 NewSteps.data(), NewSteps.size(), SR);
6920 ADecl->addAttr(NewAttr);
6921 return DG;
6922}
6923
6925 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6926 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
6927 SourceLocation EndLoc) {
6928 assert(isOpenMPInformationalDirective(Kind) &&
6929 "Unexpected directive category");
6930
6931 StmtResult Res = StmtError();
6932
6933 switch (Kind) {
6934 case OMPD_assume:
6935 Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc);
6936 break;
6937 default:
6938 llvm_unreachable("Unknown OpenMP directive");
6939 }
6940
6941 return Res;
6942}
6943
6944static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
6945 QualType NewType) {
6946 assert(NewType->isFunctionProtoType() &&
6947 "Expected function type with prototype.");
6948 assert(FD->getType()->isFunctionNoProtoType() &&
6949 "Expected function with type with no prototype.");
6950 assert(FDWithProto->getType()->isFunctionProtoType() &&
6951 "Expected function with prototype.");
6952 // Synthesize parameters with the same types.
6953 FD->setType(NewType);
6955 for (const ParmVarDecl *P : FDWithProto->parameters()) {
6956 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
6957 SourceLocation(), nullptr, P->getType(),
6958 /*TInfo=*/nullptr, SC_None, nullptr);
6959 Param->setScopeInfo(0, Params.size());
6960 Param->setImplicit();
6961 Params.push_back(Param);
6962 }
6963
6964 FD->setParams(Params);
6965}
6966
6968 if (D->isInvalidDecl())
6969 return;
6970 FunctionDecl *FD = nullptr;
6971 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
6972 FD = UTemplDecl->getTemplatedDecl();
6973 else
6974 FD = cast<FunctionDecl>(D);
6975 assert(FD && "Expected a function declaration!");
6976
6977 // If we are instantiating templates we do *not* apply scoped assumptions but
6978 // only global ones. We apply scoped assumption to the template definition
6979 // though.
6981 for (OMPAssumeAttr *AA : OMPAssumeScoped)
6982 FD->addAttr(AA);
6983 }
6984 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
6985 FD->addAttr(AA);
6986}
6987
6988SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
6989 : TI(&TI), NameSuffix(TI.getMangledName()) {}
6990
6992 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
6994 if (!D.getIdentifier())
6995 return;
6996
6997 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
6998
6999 // Template specialization is an extension, check if we do it.
7000 bool IsTemplated = !TemplateParamLists.empty();
7001 if (IsTemplated &&
7002 !DVScope.TI->isExtensionActive(
7003 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7004 return;
7005
7006 const IdentifierInfo *BaseII = D.getIdentifier();
7007 LookupResult Lookup(SemaRef, DeclarationName(BaseII), D.getIdentifierLoc(),
7009 SemaRef.LookupParsedName(Lookup, S, &D.getCXXScopeSpec(),
7010 /*ObjectType=*/QualType());
7011
7013 QualType FType = TInfo->getType();
7014
7015 bool IsConstexpr =
7016 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr;
7017 bool IsConsteval =
7018 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval;
7019
7020 for (auto *Candidate : Lookup) {
7021 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7022 FunctionDecl *UDecl = nullptr;
7023 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7024 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7025 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7026 UDecl = FTD->getTemplatedDecl();
7027 } else if (!IsTemplated)
7028 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7029 if (!UDecl)
7030 continue;
7031
7032 // Don't specialize constexpr/consteval functions with
7033 // non-constexpr/consteval functions.
7034 if (UDecl->isConstexpr() && !IsConstexpr)
7035 continue;
7036 if (UDecl->isConsteval() && !IsConsteval)
7037 continue;
7038
7039 QualType UDeclTy = UDecl->getType();
7040 if (!UDeclTy->isDependentType()) {
7042 FType, UDeclTy, /*OfBlockPointer=*/false,
7043 /*Unqualified=*/false, /*AllowCXX=*/true);
7044 if (NewType.isNull())
7045 continue;
7046 }
7047
7048 // Found a base!
7049 Bases.push_back(UDecl);
7050 }
7051
7052 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7053 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7054 // If no base was found we create a declaration that we use as base.
7055 if (Bases.empty() && UseImplicitBase) {
7056 D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
7057 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7058 BaseD->setImplicit(true);
7059 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7060 Bases.push_back(BaseTemplD->getTemplatedDecl());
7061 else
7062 Bases.push_back(cast<FunctionDecl>(BaseD));
7063 }
7064
7065 std::string MangledName;
7066 MangledName += D.getIdentifier()->getName();
7067 MangledName += getOpenMPVariantManglingSeparatorStr();
7068 MangledName += DVScope.NameSuffix;
7069 IdentifierInfo &VariantII = getASTContext().Idents.get(MangledName);
7070
7071 VariantII.setMangledOpenMPVariantName(true);
7072 D.SetIdentifier(&VariantII, D.getBeginLoc());
7073}
7074
7077 // Do not mark function as is used to prevent its emission if this is the
7078 // only place where it is used.
7081
7082 FunctionDecl *FD = nullptr;
7083 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7084 FD = UTemplDecl->getTemplatedDecl();
7085 else
7086 FD = cast<FunctionDecl>(D);
7087 auto *VariantFuncRef = DeclRefExpr::Create(
7089 /*RefersToEnclosingVariableOrCapture=*/false,
7090 /*NameLoc=*/FD->getLocation(), FD->getType(), ExprValueKind::VK_PRValue);
7091
7092 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7093 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7094 getASTContext(), VariantFuncRef, DVScope.TI,
7095 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7096 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7097 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7098 for (FunctionDecl *BaseFD : Bases)
7099 BaseFD->addAttr(OMPDeclareVariantA);
7100}
7101
7103 SourceLocation LParenLoc,
7104 MultiExprArg ArgExprs,
7105 SourceLocation RParenLoc,
7106 Expr *ExecConfig) {
7107 // The common case is a regular call we do not want to specialize at all. Try
7108 // to make that case fast by bailing early.
7109 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7110 if (!CE)
7111 return Call;
7112
7113 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7114 if (!CalleeFnDecl)
7115 return Call;
7116
7117 if (getLangOpts().OpenMP >= 51 && CalleeFnDecl->getIdentifier() &&
7118 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7119 // checking for any calls inside an Order region
7121 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7122 }
7123
7124 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7125 return Call;
7126
7127 ASTContext &Context = getASTContext();
7128 std::function<void(StringRef)> DiagUnknownTrait = [this,
7129 CE](StringRef ISATrait) {
7130 // TODO Track the selector locations in a way that is accessible here to
7131 // improve the diagnostic location.
7132 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7133 << ISATrait;
7134 };
7135 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7137 DSAStack->getConstructTraits());
7138
7139 QualType CalleeFnType = CalleeFnDecl->getType();
7140
7143 while (CalleeFnDecl) {
7144 for (OMPDeclareVariantAttr *A :
7145 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7146 Expr *VariantRef = A->getVariantFuncRef();
7147
7148 VariantMatchInfo VMI;
7149 OMPTraitInfo &TI = A->getTraitInfo();
7150 TI.getAsVariantMatchInfo(Context, VMI);
7151 if (!isVariantApplicableInContext(VMI, OMPCtx,
7152 /*DeviceSetOnly=*/false))
7153 continue;
7154
7155 VMIs.push_back(VMI);
7156 Exprs.push_back(VariantRef);
7157 }
7158
7159 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7160 }
7161
7162 ExprResult NewCall;
7163 do {
7164 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7165 if (BestIdx < 0)
7166 return Call;
7167 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7168 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7169
7170 {
7171 // Try to build a (member) call expression for the current best applicable
7172 // variant expression. We allow this to fail in which case we continue
7173 // with the next best variant expression. The fail case is part of the
7174 // implementation defined behavior in the OpenMP standard when it talks
7175 // about what differences in the function prototypes: "Any differences
7176 // that the specific OpenMP context requires in the prototype of the
7177 // variant from the base function prototype are implementation defined."
7178 // This wording is there to allow the specialized variant to have a
7179 // different type than the base function. This is intended and OK but if
7180 // we cannot create a call the difference is not in the "implementation
7181 // defined range" we allow.
7183
7184 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7185 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7186 BestExpr = MemberExpr::CreateImplicit(
7187 Context, MemberCall->getImplicitObjectArgument(),
7188 /*IsArrow=*/false, SpecializedMethod, Context.BoundMemberTy,
7189 MemberCall->getValueKind(), MemberCall->getObjectKind());
7190 }
7191 NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs,
7192 RParenLoc, ExecConfig);
7193 if (NewCall.isUsable()) {
7194 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7195 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7197 CalleeFnType, NewCalleeFnDecl->getType(),
7198 /*OfBlockPointer=*/false,
7199 /*Unqualified=*/false, /*AllowCXX=*/true);
7200 if (!NewType.isNull())
7201 break;
7202 // Don't use the call if the function type was not compatible.
7203 NewCall = nullptr;
7204 }
7205 }
7206 }
7207
7208 VMIs.erase(VMIs.begin() + BestIdx);
7209 Exprs.erase(Exprs.begin() + BestIdx);
7210 } while (!VMIs.empty());
7211
7212 if (!NewCall.isUsable())
7213 return Call;
7214 return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
7215}
7216
7217std::optional<std::pair<FunctionDecl *, Expr *>>
7219 Expr *VariantRef,
7220 OMPTraitInfo &TI,
7221 unsigned NumAppendArgs,
7222 SourceRange SR) {
7223 ASTContext &Context = getASTContext();
7224 if (!DG || DG.get().isNull())
7225 return std::nullopt;
7226
7227 const int VariantId = 1;
7228 // Must be applied only to single decl.
7229 if (!DG.get().isSingleDecl()) {
7230 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7231 << VariantId << SR;
7232 return std::nullopt;
7233 }
7234 Decl *ADecl = DG.get().getSingleDecl();
7235 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7236 ADecl = FTD->getTemplatedDecl();
7237
7238 // Decl must be a function.
7239 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7240 if (!FD) {
7241 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7242 << VariantId << SR;
7243 return std::nullopt;
7244 }
7245
7246 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7247 // The 'target' attribute needs to be separately checked because it does
7248 // not always signify a multiversion function declaration.
7249 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7250 };
7251 // OpenMP is not compatible with multiversion function attributes.
7252 if (HasMultiVersionAttributes(FD)) {
7253 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7254 << SR;
7255 return std::nullopt;
7256 }
7257
7258 // Allow #pragma omp declare variant only if the function is not used.
7259 if (FD->isUsed(false))
7260 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7261 << FD->getLocation();
7262
7263 // Check if the function was emitted already.
7264 const FunctionDecl *Definition;
7265 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7266 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7267 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7268 << FD->getLocation();
7269
7270 // The VariantRef must point to function.
7271 if (!VariantRef) {
7272 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7273 return std::nullopt;
7274 }
7275
7276 auto ShouldDelayChecks = [](Expr *&E, bool) {
7277 return E && (E->isTypeDependent() || E->isValueDependent() ||
7280 };
7281 // Do not check templates, wait until instantiation.
7282 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7283 TI.anyScoreOrCondition(ShouldDelayChecks))
7284 return std::make_pair(FD, VariantRef);
7285
7286 // Deal with non-constant score and user condition expressions.
7287 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7288 bool IsScore) -> bool {
7290 return false;
7291
7292 if (IsScore) {
7293 // We warn on non-constant scores and pretend they were not present.
7294 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7295 << E;
7296 E = nullptr;
7297 } else {
7298 // We could replace a non-constant user condition with "false" but we
7299 // will soon need to handle these anyway for the dynamic version of
7300 // OpenMP context selectors.
7301 Diag(E->getExprLoc(),
7302 diag::err_omp_declare_variant_user_condition_not_constant)
7303 << E;
7304 }
7305 return true;
7306 };
7307 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7308 return std::nullopt;
7309
7310 QualType AdjustedFnType = FD->getType();
7311 if (NumAppendArgs) {
7312 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7313 if (!PTy) {
7314 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7315 << SR;
7316 return std::nullopt;
7317 }
7318 // Adjust the function type to account for an extra omp_interop_t for each
7319 // specified in the append_args clause.
7320 const TypeDecl *TD = nullptr;
7321 LookupResult Result(SemaRef, &Context.Idents.get("omp_interop_t"),
7324 NamedDecl *ND = Result.getFoundDecl();
7325 TD = dyn_cast_or_null<TypeDecl>(ND);
7326 }
7327 if (!TD) {
7328 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7329 return std::nullopt;
7330 }
7331 QualType InteropType = Context.getTypeDeclType(TD);
7332 if (PTy->isVariadic()) {
7333 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7334 return std::nullopt;
7335 }
7337 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7338 Params.insert(Params.end(), NumAppendArgs, InteropType);
7339 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7340 PTy->getExtProtoInfo());
7341 }
7342
7343 // Convert VariantRef expression to the type of the original function to
7344 // resolve possible conflicts.
7345 ExprResult VariantRefCast = VariantRef;
7346 if (getLangOpts().CPlusPlus) {
7347 QualType FnPtrType;
7348 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7349 if (Method && !Method->isStatic()) {
7350 const Type *ClassType =
7351 Context.getTypeDeclType(Method->getParent()).getTypePtr();
7352 FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType);
7353 ExprResult ER;
7354 {
7355 // Build addr_of unary op to correctly handle type checks for member
7356 // functions.
7358 ER = SemaRef.CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7359 VariantRef);
7360 }
7361 if (!ER.isUsable()) {
7362 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7363 << VariantId << VariantRef->getSourceRange();
7364 return std::nullopt;
7365 }
7366 VariantRef = ER.get();
7367 } else {
7368 FnPtrType = Context.getPointerType(AdjustedFnType);
7369 }
7370 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7371 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7373 VariantRef, FnPtrType.getUnqualifiedType(),
7374 /*SuppressUserConversions=*/false, Sema::AllowedExplicit::None,
7375 /*InOverloadResolution=*/false,
7376 /*CStyle=*/false,
7377 /*AllowObjCWritebackConversion=*/false);
7378 if (ICS.isFailure()) {
7379 Diag(VariantRef->getExprLoc(),
7380 diag::err_omp_declare_variant_incompat_types)
7381 << VariantRef->getType()
7382 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7383 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7384 return std::nullopt;
7385 }
7386 VariantRefCast = SemaRef.PerformImplicitConversion(
7387 VariantRef, FnPtrType.getUnqualifiedType(),
7389 if (!VariantRefCast.isUsable())
7390 return std::nullopt;
7391 }
7392 // Drop previously built artificial addr_of unary op for member functions.
7393 if (Method && !Method->isStatic()) {
7394 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7395 if (auto *UO = dyn_cast<UnaryOperator>(
7396 PossibleAddrOfVariantRef->IgnoreImplicit()))
7397 VariantRefCast = UO->getSubExpr();
7398 }
7399 }
7400
7401 ExprResult ER = SemaRef.CheckPlaceholderExpr(VariantRefCast.get());
7402 if (!ER.isUsable() ||
7404 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7405 << VariantId << VariantRef->getSourceRange();
7406 return std::nullopt;
7407 }
7408
7409 // The VariantRef must point to function.
7410 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7411 if (!DRE) {
7412 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7413 << VariantId << VariantRef->getSourceRange();
7414 return std::nullopt;
7415 }
7416 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7417 if (!NewFD) {
7418 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7419 << VariantId << VariantRef->getSourceRange();
7420 return std::nullopt;
7421 }
7422
7423 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7424 Diag(VariantRef->getExprLoc(),
7425 diag::err_omp_declare_variant_same_base_function)
7426 << VariantRef->getSourceRange();
7427 return std::nullopt;
7428 }
7429
7430 // Check if function types are compatible in C.
7431 if (!getLangOpts().CPlusPlus) {
7432 QualType NewType =
7433 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7434 if (NewType.isNull()) {
7435 Diag(VariantRef->getExprLoc(),
7436 diag::err_omp_declare_variant_incompat_types)
7437 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7438 << VariantRef->getSourceRange();
7439 return std::nullopt;
7440 }
7441 if (NewType->isFunctionProtoType()) {
7442 if (FD->getType()->isFunctionNoProtoType())
7443 setPrototype(SemaRef, FD, NewFD, NewType);
7444 else if (NewFD->getType()->isFunctionNoProtoType())
7445 setPrototype(SemaRef, NewFD, FD, NewType);
7446 }
7447 }
7448
7449 // Check if variant function is not marked with declare variant directive.
7450 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7451 Diag(VariantRef->getExprLoc(),
7452 diag::warn_omp_declare_variant_marked_as_declare_variant)
7453 << VariantRef->getSourceRange();
7454 SourceRange SR =
7455 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7456 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7457 return std::nullopt;
7458 }
7459
7460 enum DoesntSupport {
7461 VirtFuncs = 1,
7462 Constructors = 3,
7463 Destructors = 4,
7464 DeletedFuncs = 5,
7465 DefaultedFuncs = 6,
7466 ConstexprFuncs = 7,
7467 ConstevalFuncs = 8,
7468 };
7469 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7470 if (CXXFD->isVirtual()) {
7471 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7472 << VirtFuncs;
7473 return std::nullopt;
7474 }
7475
7476 if (isa<CXXConstructorDecl>(FD)) {
7477 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7478 << Constructors;
7479 return std::nullopt;
7480 }
7481
7482 if (isa<CXXDestructorDecl>(FD)) {
7483 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7484 << Destructors;
7485 return std::nullopt;
7486 }
7487 }
7488
7489 if (FD->isDeleted()) {
7490 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7491 << DeletedFuncs;
7492 return std::nullopt;
7493 }
7494
7495 if (FD->isDefaulted()) {
7496 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7497 << DefaultedFuncs;
7498 return std::nullopt;
7499 }
7500
7501 if (FD->isConstexpr()) {
7502 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7503 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7504 return std::nullopt;
7505 }
7506
7507 // Check general compatibility.
7513 VariantRef->getExprLoc(),
7514 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7515 PartialDiagnosticAt(VariantRef->getExprLoc(),
7516 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7517 << FD->getLocation()),
7518 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7519 /*CLinkageMayDiffer=*/true))
7520 return std::nullopt;
7521 return std::make_pair(FD, cast<Expr>(DRE));
7522}
7523
7525 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7526 ArrayRef<Expr *> AdjustArgsNothing,
7527 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7528 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7529 SourceLocation AppendArgsLoc, SourceRange SR) {
7530
7531 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7532 // An adjust_args clause or append_args clause can only be specified if the
7533 // dispatch selector of the construct selector set appears in the match
7534 // clause.
7535
7536 SmallVector<Expr *, 8> AllAdjustArgs;
7537 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7538 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7539
7540 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7541 VariantMatchInfo VMI;
7543 if (!llvm::is_contained(
7544 VMI.ConstructTraits,
7545 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7546 if (!AllAdjustArgs.empty())
7547 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7548 << getOpenMPClauseName(OMPC_adjust_args);
7549 if (!AppendArgs.empty())
7550 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7551 << getOpenMPClauseName(OMPC_append_args);
7552 return;
7553 }
7554 }
7555
7556 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7557 // Each argument can only appear in a single adjust_args clause for each
7558 // declare variant directive.
7560
7561 for (Expr *E : AllAdjustArgs) {
7562 E = E->IgnoreParenImpCasts();
7563 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7564 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7565 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7566 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7567 FD->getParamDecl(PVD->getFunctionScopeIndex())
7568 ->getCanonicalDecl() == CanonPVD) {
7569 // It's a parameter of the function, check duplicates.
7570 if (!AdjustVars.insert(CanonPVD).second) {
7571 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7572 << PVD;
7573 return;
7574 }
7575 continue;
7576 }
7577 }
7578 }
7579 // Anything that is not a function parameter is an error.
7580 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7581 return;
7582 }
7583
7584 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7585 getASTContext(), VariantRef, &TI,
7586 const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7587 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7588 AdjustArgsNeedDevicePtr.size(),
7589 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7590 FD->addAttr(NewAttr);
7591}
7592
7593static CapturedStmt *
7595 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7596 assert(CS && "Captured statement expected");
7597 // 1.2.2 OpenMP Language Terminology
7598 // Structured block - An executable statement with a single entry at the
7599 // top and a single exit at the bottom.
7600 // The point of exit cannot be a branch out of the structured block.
7601 // longjmp() and throw() must not violate the entry/exit criteria.
7602 CS->getCapturedDecl()->setNothrow();
7603
7604 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
7605 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7606 CS = cast<CapturedStmt>(CS->getCapturedStmt());
7607 // 1.2.2 OpenMP Language Terminology
7608 // Structured block - An executable statement with a single entry at the
7609 // top and a single exit at the bottom.
7610 // The point of exit cannot be a branch out of the structured block.
7611 // longjmp() and throw() must not violate the entry/exit criteria.
7612 CS->getCapturedDecl()->setNothrow();
7613 }
7615 return CS;
7616}
7617
7620 Stmt *AStmt, SourceLocation StartLoc,
7621 SourceLocation EndLoc) {
7622 if (!AStmt)
7623 return StmtError();
7624
7625 setBranchProtectedScope(SemaRef, OMPD_parallel, AStmt);
7626
7628 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
7629 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
7630}
7631
7632namespace {
7633/// Iteration space of a single for loop.
7634struct LoopIterationSpace final {
7635 /// True if the condition operator is the strict compare operator (<, > or
7636 /// !=).
7637 bool IsStrictCompare = false;
7638 /// Condition of the loop.
7639 Expr *PreCond = nullptr;
7640 /// This expression calculates the number of iterations in the loop.
7641 /// It is always possible to calculate it before starting the loop.
7642 Expr *NumIterations = nullptr;
7643 /// The loop counter variable.
7644 Expr *CounterVar = nullptr;
7645 /// Private loop counter variable.
7646 Expr *PrivateCounterVar = nullptr;
7647 /// This is initializer for the initial value of #CounterVar.
7648 Expr *CounterInit = nullptr;
7649 /// This is step for the #CounterVar used to generate its update:
7650 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7651 Expr *CounterStep = nullptr;
7652 /// Should step be subtracted?
7653 bool Subtract = false;
7654 /// Source range of the loop init.
7655 SourceRange InitSrcRange;
7656 /// Source range of the loop condition.
7657 SourceRange CondSrcRange;
7658 /// Source range of the loop increment.
7659 SourceRange IncSrcRange;
7660 /// Minimum value that can have the loop control variable. Used to support
7661 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7662 /// since only such variables can be used in non-loop invariant expressions.
7663 Expr *MinValue = nullptr;
7664 /// Maximum value that can have the loop control variable. Used to support
7665 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7666 /// since only such variables can be used in non-loop invariant expressions.
7667 Expr *MaxValue = nullptr;
7668 /// true, if the lower bound depends on the outer loop control var.
7669 bool IsNonRectangularLB = false;
7670 /// true, if the upper bound depends on the outer loop control var.
7671 bool IsNonRectangularUB = false;
7672 /// Index of the loop this loop depends on and forms non-rectangular loop
7673 /// nest.
7674 unsigned LoopDependentIdx = 0;
7675 /// Final condition for the non-rectangular loop nest support. It is used to
7676 /// check that the number of iterations for this particular counter must be
7677 /// finished.
7678 Expr *FinalCondition = nullptr;
7679};
7680
7681/// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls
7682/// set are referenced. Used for verifying loop nest structure before
7683/// performing a loop collapse operation.
7684class ForSubExprChecker : public DynamicRecursiveASTVisitor {
7685 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7686 VarDecl *ForbiddenVar = nullptr;
7687 SourceRange ErrLoc;
7688
7689public:
7690 explicit ForSubExprChecker(
7691 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7692 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
7693 // We want to visit implicit code, i.e. synthetic initialisation statements
7694 // created during range-for lowering.
7695 ShouldVisitImplicitCode = true;
7696 }
7697
7698 bool VisitDeclRefExpr(DeclRefExpr *E) override {
7699 ValueDecl *VD = E->getDecl();
7700 if (!isa<VarDecl, BindingDecl>(VD))
7701 return true;
7703 if (V->getType()->isReferenceType()) {
7704 VarDecl *VD = V->getDefinition();
7705 if (VD->hasInit()) {
7706 Expr *I = VD->getInit();
7707 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
7708 if (!DRE)
7709 return true;
7711 }
7712 }
7713 Decl *Canon = V->getCanonicalDecl();
7714 if (CollapsedLoopVarDecls.contains(Canon)) {
7715 ForbiddenVar = V;
7716 ErrLoc = E->getSourceRange();
7717 return false;
7718 }
7719
7720 return true;
7721 }
7722
7723 VarDecl *getForbiddenVar() const { return ForbiddenVar; }
7724 SourceRange getErrRange() const { return ErrLoc; }
7725};
7726
7727/// Helper class for checking canonical form of the OpenMP loops and
7728/// extracting iteration space of each loop in the loop nest, that will be used
7729/// for IR generation.
7730class OpenMPIterationSpaceChecker {
7731 /// Reference to Sema.
7732 Sema &SemaRef;
7733 /// Does the loop associated directive support non-rectangular loops?
7734 bool SupportsNonRectangular;
7735 /// Data-sharing stack.
7736 DSAStackTy &Stack;
7737 /// A location for diagnostics (when there is no some better location).
7738 SourceLocation DefaultLoc;
7739 /// A location for diagnostics (when increment is not compatible).
7740 SourceLocation ConditionLoc;
7741 /// The set of variables declared within the (to be collapsed) loop nest.
7742 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7743 /// A source location for referring to loop init later.
7744 SourceRange InitSrcRange;
7745 /// A source location for referring to condition later.
7746 SourceRange ConditionSrcRange;
7747 /// A source location for referring to increment later.
7748 SourceRange IncrementSrcRange;
7749 /// Loop variable.
7750 ValueDecl *LCDecl = nullptr;
7751 /// Reference to loop variable.
7752 Expr *LCRef = nullptr;
7753 /// Lower bound (initializer for the var).
7754 Expr *LB = nullptr;
7755 /// Upper bound.
7756 Expr *UB = nullptr;
7757 /// Loop step (increment).
7758 Expr *Step = nullptr;
7759 /// This flag is true when condition is one of:
7760 /// Var < UB
7761 /// Var <= UB
7762 /// UB > Var
7763 /// UB >= Var
7764 /// This will have no value when the condition is !=
7765 std::optional<bool> TestIsLessOp;
7766 /// This flag is true when condition is strict ( < or > ).
7767 bool TestIsStrictOp = false;
7768 /// This flag is true when step is subtracted on each iteration.
7769 bool SubtractStep = false;
7770 /// The outer loop counter this loop depends on (if any).
7771 const ValueDecl *DepDecl = nullptr;
7772 /// Contains number of loop (starts from 1) on which loop counter init
7773 /// expression of this loop depends on.
7774 std::optional<unsigned> InitDependOnLC;
7775 /// Contains number of loop (starts from 1) on which loop counter condition
7776 /// expression of this loop depends on.
7777 std::optional<unsigned> CondDependOnLC;
7778 /// Checks if the provide statement depends on the loop counter.
7779 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
7780 bool IsInitializer);
7781 /// Original condition required for checking of the exit condition for
7782 /// non-rectangular loop.
7783 Expr *Condition = nullptr;
7784
7785public:
7786 OpenMPIterationSpaceChecker(
7787 Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack,
7788 SourceLocation DefaultLoc,
7789 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
7790 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7791 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
7792 CollapsedLoopVarDecls(CollapsedLoopDecls) {}
7793 /// Check init-expr for canonical loop form and save loop counter
7794 /// variable - #Var and its initialization value - #LB.
7795 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
7796 /// Check test-expr for canonical form, save upper-bound (#UB), flags
7797 /// for less/greater and for strict/non-strict comparison.
7798 bool checkAndSetCond(Expr *S);
7799 /// Check incr-expr for canonical loop form and return true if it
7800 /// does not conform, otherwise save loop step (#Step).
7801 bool checkAndSetInc(Expr *S);
7802 /// Return the loop counter variable.
7803 ValueDecl *getLoopDecl() const { return LCDecl; }
7804 /// Return the reference expression to loop counter variable.
7805 Expr *getLoopDeclRefExpr() const { return LCRef; }
7806 /// Source range of the loop init.
7807 SourceRange getInitSrcRange() const { return InitSrcRange; }
7808 /// Source range of the loop condition.
7809 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
7810 /// Source range of the loop increment.
7811 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
7812 /// True if the step should be subtracted.
7813 bool shouldSubtractStep() const { return SubtractStep; }
7814 /// True, if the compare operator is strict (<, > or !=).
7815 bool isStrictTestOp() const { return TestIsStrictOp; }
7816 /// Build the expression to calculate the number of iterations.
7817 Expr *buildNumIterations(
7818 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
7819 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7820 /// Build the precondition expression for the loops.
7821 Expr *
7822 buildPreCond(Scope *S, Expr *Cond,
7823 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7824 /// Build reference expression to the counter be used for codegen.
7825 DeclRefExpr *
7826 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7827 DSAStackTy &DSA) const;
7828 /// Build reference expression to the private counter be used for
7829 /// codegen.
7830 Expr *buildPrivateCounterVar() const;
7831 /// Build initialization of the counter be used for codegen.
7832 Expr *buildCounterInit() const;
7833 /// Build step of the counter be used for codegen.
7834 Expr *buildCounterStep() const;
7835 /// Build loop data with counter value for depend clauses in ordered
7836 /// directives.
7837 Expr *
7838 buildOrderedLoopData(Scope *S, Expr *Counter,
7839 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7840 SourceLocation Loc, Expr *Inc = nullptr,
7841 OverloadedOperatorKind OOK = OO_Amp);
7842 /// Builds the minimum value for the loop counter.
7843 std::pair<Expr *, Expr *> buildMinMaxValues(
7844 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7845 /// Builds final condition for the non-rectangular loops.
7846 Expr *buildFinalCondition(Scope *S) const;
7847 /// Return true if any expression is dependent.
7848 bool dependent() const;
7849 /// Returns true if the initializer forms non-rectangular loop.
7850 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
7851 /// Returns true if the condition forms non-rectangular loop.
7852 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
7853 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
7854 unsigned getLoopDependentIdx() const {
7855 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
7856 }
7857
7858private:
7859 /// Check the right-hand side of an assignment in the increment
7860 /// expression.
7861 bool checkAndSetIncRHS(Expr *RHS);
7862 /// Helper to set loop counter variable and its initializer.
7863 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
7864 bool EmitDiags);
7865 /// Helper to set upper bound.
7866 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
7868 /// Helper to set loop increment.
7869 bool setStep(Expr *NewStep, bool Subtract);
7870};
7871
7872bool OpenMPIterationSpaceChecker::dependent() const {
7873 if (!LCDecl) {
7874 assert(!LB && !UB && !Step);
7875 return false;
7876 }
7877 return LCDecl->getType()->isDependentType() ||
7878 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
7879 (Step && Step->isValueDependent());
7880}
7881
7882bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
7883 Expr *NewLCRefExpr,
7884 Expr *NewLB, bool EmitDiags) {
7885 // State consistency checking to ensure correct usage.
7886 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
7887 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7888 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
7889 return true;
7890 LCDecl = getCanonicalDecl(NewLCDecl);
7891 LCRef = NewLCRefExpr;
7892 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
7893 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
7894 if ((Ctor->isCopyOrMoveConstructor() ||
7895 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
7896 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
7897 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
7898 LB = NewLB;
7899 if (EmitDiags)
7900 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
7901 return false;
7902}
7903
7904bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
7905 bool StrictOp, SourceRange SR,
7906 SourceLocation SL) {
7907 // State consistency checking to ensure correct usage.
7908 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
7909 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7910 if (!NewUB || NewUB->containsErrors())
7911 return true;
7912 UB = NewUB;
7913 if (LessOp)
7914 TestIsLessOp = LessOp;
7915 TestIsStrictOp = StrictOp;
7916 ConditionSrcRange = SR;
7917 ConditionLoc = SL;
7918 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
7919 return false;
7920}
7921
7922bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
7923 // State consistency checking to ensure correct usage.
7924 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
7925 if (!NewStep || NewStep->containsErrors())
7926 return true;
7927 if (!NewStep->isValueDependent()) {
7928 // Check that the step is integer expression.
7929 SourceLocation StepLoc = NewStep->getBeginLoc();
7931 StepLoc, getExprAsWritten(NewStep));
7932 if (Val.isInvalid())
7933 return true;
7934 NewStep = Val.get();
7935
7936 // OpenMP [2.6, Canonical Loop Form, Restrictions]
7937 // If test-expr is of form var relational-op b and relational-op is < or
7938 // <= then incr-expr must cause var to increase on each iteration of the
7939 // loop. If test-expr is of form var relational-op b and relational-op is
7940 // > or >= then incr-expr must cause var to decrease on each iteration of
7941 // the loop.
7942 // If test-expr is of form b relational-op var and relational-op is < or
7943 // <= then incr-expr must cause var to decrease on each iteration of the
7944 // loop. If test-expr is of form b relational-op var and relational-op is
7945 // > or >= then incr-expr must cause var to increase on each iteration of
7946 // the loop.
7947 std::optional<llvm::APSInt> Result =
7948 NewStep->getIntegerConstantExpr(SemaRef.Context);
7949 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
7950 bool IsConstNeg =
7951 Result && Result->isSigned() && (Subtract != Result->isNegative());
7952 bool IsConstPos =
7953 Result && Result->isSigned() && (Subtract == Result->isNegative());
7954 bool IsConstZero = Result && !Result->getBoolValue();
7955
7956 // != with increment is treated as <; != with decrement is treated as >
7957 if (!TestIsLessOp)
7958 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
7959 if (UB && (IsConstZero ||
7960 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
7961 : (IsConstPos || (IsUnsigned && !Subtract))))) {
7962 SemaRef.Diag(NewStep->getExprLoc(),
7963 diag::err_omp_loop_incr_not_compatible)
7964 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
7965 SemaRef.Diag(ConditionLoc,
7966 diag::note_omp_loop_cond_requires_compatible_incr)
7967 << *TestIsLessOp << ConditionSrcRange;
7968 return true;
7969 }
7970 if (*TestIsLessOp == Subtract) {
7971 NewStep =
7972 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
7973 .get();
7974 Subtract = !Subtract;
7975 }
7976 }
7977
7978 Step = NewStep;
7979 SubtractStep = Subtract;
7980 return false;
7981}
7982
7983namespace {
7984/// Checker for the non-rectangular loops. Checks if the initializer or
7985/// condition expression references loop counter variable.
7986class LoopCounterRefChecker final
7987 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
7988 Sema &SemaRef;
7989 DSAStackTy &Stack;
7990 const ValueDecl *CurLCDecl = nullptr;
7991 const ValueDecl *DepDecl = nullptr;
7992 const ValueDecl *PrevDepDecl = nullptr;
7993 bool IsInitializer = true;
7994 bool SupportsNonRectangular;
7995 unsigned BaseLoopId = 0;
7996 bool checkDecl(const Expr *E, const ValueDecl *VD) {
7997 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
7998 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
7999 << (IsInitializer ? 0 : 1);
8000 return false;
8001 }
8002 const auto &&Data = Stack.isLoopControlVariable(VD);
8003 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8004 // The type of the loop iterator on which we depend may not have a random
8005 // access iterator type.
8006 if (Data.first && VD->getType()->isRecordType()) {
8007 SmallString<128> Name;
8008 llvm::raw_svector_ostream OS(Name);
8009 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8010 /*Qualified=*/true);
8011 SemaRef.Diag(E->getExprLoc(),
8012 diag::err_omp_wrong_dependency_iterator_type)
8013 << OS.str();
8014 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8015 return false;
8016 }
8017 if (Data.first && !SupportsNonRectangular) {
8018 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8019 return false;
8020 }
8021 if (Data.first &&
8022 (DepDecl || (PrevDepDecl &&
8023 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8024 if (!DepDecl && PrevDepDecl)
8025 DepDecl = PrevDepDecl;
8026 SmallString<128> Name;
8027 llvm::raw_svector_ostream OS(Name);
8028 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8029 /*Qualified=*/true);
8030 SemaRef.Diag(E->getExprLoc(),
8031 diag::err_omp_invariant_or_linear_dependency)
8032 << OS.str();
8033 return false;
8034 }
8035 if (Data.first) {
8036 DepDecl = VD;
8037 BaseLoopId = Data.first;
8038 }
8039 return Data.first;
8040 }
8041
8042public:
8043 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8044 const ValueDecl *VD = E->getDecl();
8045 if (isa<VarDecl>(VD))
8046 return checkDecl(E, VD);
8047 return false;
8048 }
8049 bool VisitMemberExpr(const MemberExpr *E) {
8050 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8051 const ValueDecl *VD = E->getMemberDecl();
8052 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8053 return checkDecl(E, VD);
8054 }
8055 return false;
8056 }
8057 bool VisitStmt(const Stmt *S) {
8058 bool Res = false;
8059 for (const Stmt *Child : S->children())
8060 Res = (Child && Visit(Child)) || Res;
8061 return Res;
8062 }
8063 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8064 const ValueDecl *CurLCDecl, bool IsInitializer,
8065 const ValueDecl *PrevDepDecl = nullptr,
8066 bool SupportsNonRectangular = true)
8067 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8068 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8069 SupportsNonRectangular(SupportsNonRectangular) {}
8070 unsigned getBaseLoopId() const {
8071 assert(CurLCDecl && "Expected loop dependency.");
8072 return BaseLoopId;
8073 }
8074 const ValueDecl *getDepDecl() const {
8075 assert(CurLCDecl && "Expected loop dependency.");
8076 return DepDecl;
8077 }
8078};
8079} // namespace
8080
8081std::optional<unsigned>
8082OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8083 bool IsInitializer) {
8084 // Check for the non-rectangular loops.
8085 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8086 DepDecl, SupportsNonRectangular);
8087 if (LoopStmtChecker.Visit(S)) {
8088 DepDecl = LoopStmtChecker.getDepDecl();
8089 return LoopStmtChecker.getBaseLoopId();
8090 }
8091 return std::nullopt;
8092}
8093
8094bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8095 // Check init-expr for canonical loop form and save loop counter
8096 // variable - #Var and its initialization value - #LB.
8097 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8098 // var = lb
8099 // integer-type var = lb
8100 // random-access-iterator-type var = lb
8101 // pointer-type var = lb
8102 //
8103 if (!S) {
8104 if (EmitDiags) {
8105 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8106 }
8107 return true;
8108 }
8109 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8110 if (!ExprTemp->cleanupsHaveSideEffects())
8111 S = ExprTemp->getSubExpr();
8112
8113 if (!CollapsedLoopVarDecls.empty()) {
8114 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8115 if (!FSEC.TraverseStmt(S)) {
8116 SourceRange Range = FSEC.getErrRange();
8117 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8118 << Range.getEnd() << 0 << FSEC.getForbiddenVar();
8119 return true;
8120 }
8121 }
8122
8123 InitSrcRange = S->getSourceRange();
8124 if (Expr *E = dyn_cast<Expr>(S))
8125 S = E->IgnoreParens();
8126 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8127 if (BO->getOpcode() == BO_Assign) {
8128 Expr *LHS = BO->getLHS()->IgnoreParens();
8129 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8130 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8131 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8132 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8133 EmitDiags);
8134 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8135 }
8136 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8137 if (ME->isArrow() &&
8138 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8139 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8140 EmitDiags);
8141 }
8142 }
8143 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8144 if (DS->isSingleDecl()) {
8145 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8146 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8147 // Accept non-canonical init form here but emit ext. warning.
8148 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8149 SemaRef.Diag(S->getBeginLoc(),
8150 diag::ext_omp_loop_not_canonical_init)
8151 << S->getSourceRange();
8152 return setLCDeclAndLB(
8153 Var,
8154 buildDeclRefExpr(SemaRef, Var,
8155 Var->getType().getNonReferenceType(),
8156 DS->getBeginLoc()),
8157 Var->getInit(), EmitDiags);
8158 }
8159 }
8160 }
8161 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8162 if (CE->getOperator() == OO_Equal) {
8163 Expr *LHS = CE->getArg(0);
8164 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8165 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8166 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8167 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8168 EmitDiags);
8169 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8170 }
8171 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8172 if (ME->isArrow() &&
8173 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8174 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8175 EmitDiags);
8176 }
8177 }
8178 }
8179
8180 if (dependent() || SemaRef.CurContext->isDependentContext())
8181 return false;
8182 if (EmitDiags) {
8183 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8184 << S->getSourceRange();
8185 }
8186 return true;
8187}
8188
8189/// Ignore parenthesizes, implicit casts, copy constructor and return the
8190/// variable (which may be the loop variable) if possible.
8191static const ValueDecl *getInitLCDecl(const Expr *E) {
8192 if (!E)
8193 return nullptr;
8194 E = getExprAsWritten(E);
8195 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8196 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8197 if ((Ctor->isCopyOrMoveConstructor() ||
8198 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8199 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8200 E = CE->getArg(0)->IgnoreParenImpCasts();
8201 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8202 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8203 return getCanonicalDecl(VD);
8204 }
8205 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8206 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8207 return getCanonicalDecl(ME->getMemberDecl());
8208 return nullptr;
8209}
8210
8211bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8212 // Check test-expr for canonical form, save upper-bound UB, flags for
8213 // less/greater and for strict/non-strict comparison.
8214 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8215 // var relational-op b
8216 // b relational-op var
8217 //
8218 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8219 if (!S) {
8220 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8221 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8222 return true;
8223 }
8224 Condition = S;
8225 S = getExprAsWritten(S);
8226
8227 if (!CollapsedLoopVarDecls.empty()) {
8228 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8229 if (!FSEC.TraverseStmt(S)) {
8230 SourceRange Range = FSEC.getErrRange();
8231 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8232 << Range.getEnd() << 1 << FSEC.getForbiddenVar();
8233 return true;
8234 }
8235 }
8236
8237 SourceLocation CondLoc = S->getBeginLoc();
8238 auto &&CheckAndSetCond =
8239 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8240 const Expr *RHS, SourceRange SR,
8241 SourceLocation OpLoc) -> std::optional<bool> {
8242 if (BinaryOperator::isRelationalOp(Opcode)) {
8243 if (getInitLCDecl(LHS) == LCDecl)
8244 return setUB(const_cast<Expr *>(RHS),
8245 (Opcode == BO_LT || Opcode == BO_LE),
8246 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8247 if (getInitLCDecl(RHS) == LCDecl)
8248 return setUB(const_cast<Expr *>(LHS),
8249 (Opcode == BO_GT || Opcode == BO_GE),
8250 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8251 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8252 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8253 /*LessOp=*/std::nullopt,
8254 /*StrictOp=*/true, SR, OpLoc);
8255 }
8256 return std::nullopt;
8257 };
8258 std::optional<bool> Res;
8259 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8260 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8261 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8262 RBO->getOperatorLoc());
8263 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8264 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8265 BO->getSourceRange(), BO->getOperatorLoc());
8266 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8267 if (CE->getNumArgs() == 2) {
8268 Res = CheckAndSetCond(
8269 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8270 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8271 }
8272 }
8273 if (Res)
8274 return *Res;
8275 if (dependent() || SemaRef.CurContext->isDependentContext())
8276 return false;
8277 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8278 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8279 return true;
8280}
8281
8282bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8283 // RHS of canonical loop form increment can be:
8284 // var + incr
8285 // incr + var
8286 // var - incr
8287 //
8288 RHS = RHS->IgnoreParenImpCasts();
8289 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8290 if (BO->isAdditiveOp()) {
8291 bool IsAdd = BO->getOpcode() == BO_Add;
8292 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8293 return setStep(BO->getRHS(), !IsAdd);
8294 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8295 return setStep(BO->getLHS(), /*Subtract=*/false);
8296 }
8297 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8298 bool IsAdd = CE->getOperator() == OO_Plus;
8299 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8300 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8301 return setStep(CE->getArg(1), !IsAdd);
8302 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8303 return setStep(CE->getArg(0), /*Subtract=*/false);
8304 }
8305 }
8306 if (dependent() || SemaRef.CurContext->isDependentContext())
8307 return false;
8308 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8309 << RHS->getSourceRange() << LCDecl;
8310 return true;
8311}
8312
8313bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8314 // Check incr-expr for canonical loop form and return true if it
8315 // does not conform.
8316 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8317 // ++var
8318 // var++
8319 // --var
8320 // var--
8321 // var += incr
8322 // var -= incr
8323 // var = var + incr
8324 // var = incr + var
8325 // var = var - incr
8326 //
8327 if (!S) {
8328 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8329 return true;
8330 }
8331 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8332 if (!ExprTemp->cleanupsHaveSideEffects())
8333 S = ExprTemp->getSubExpr();
8334
8335 if (!CollapsedLoopVarDecls.empty()) {
8336 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8337 if (!FSEC.TraverseStmt(S)) {
8338 SourceRange Range = FSEC.getErrRange();
8339 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8340 << Range.getEnd() << 2 << FSEC.getForbiddenVar();
8341 return true;
8342 }
8343 }
8344
8345 IncrementSrcRange = S->getSourceRange();
8346 S = S->IgnoreParens();
8347 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8348 if (UO->isIncrementDecrementOp() &&
8349 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8350 return setStep(SemaRef
8351 .ActOnIntegerConstant(UO->getBeginLoc(),
8352 (UO->isDecrementOp() ? -1 : 1))
8353 .get(),
8354 /*Subtract=*/false);
8355 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8356 switch (BO->getOpcode()) {
8357 case BO_AddAssign:
8358 case BO_SubAssign:
8359 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8360 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8361 break;
8362 case BO_Assign:
8363 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8364 return checkAndSetIncRHS(BO->getRHS());
8365 break;
8366 default:
8367 break;
8368 }
8369 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8370 switch (CE->getOperator()) {
8371 case OO_PlusPlus:
8372 case OO_MinusMinus:
8373 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8374 return setStep(SemaRef
8375 .ActOnIntegerConstant(
8376 CE->getBeginLoc(),
8377 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8378 .get(),
8379 /*Subtract=*/false);
8380 break;
8381 case OO_PlusEqual:
8382 case OO_MinusEqual:
8383 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8384 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8385 break;
8386 case OO_Equal:
8387 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8388 return checkAndSetIncRHS(CE->getArg(1));
8389 break;
8390 default:
8391 break;
8392 }
8393 }
8394 if (dependent() || SemaRef.CurContext->isDependentContext())
8395 return false;
8396 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8397 << S->getSourceRange() << LCDecl;
8398 return true;
8399}
8400
8401static ExprResult
8402tryBuildCapture(Sema &SemaRef, Expr *Capture,
8403 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8404 StringRef Name = ".capture_expr.") {
8405 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8406 return Capture;
8407 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8408 return SemaRef.PerformImplicitConversion(Capture->IgnoreImpCasts(),
8409 Capture->getType(),
8411 /*AllowExplicit=*/true);
8412 auto I = Captures.find(Capture);
8413 if (I != Captures.end())
8414 return buildCapture(SemaRef, Capture, I->second, Name);
8415 DeclRefExpr *Ref = nullptr;
8416 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8417 Captures[Capture] = Ref;
8418 return Res;
8419}
8420
8421/// Calculate number of iterations, transforming to unsigned, if number of
8422/// iterations may be larger than the original type.
8423static Expr *
8424calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8425 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8426 bool TestIsStrictOp, bool RoundToStep,
8427 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8428 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8429 if (!NewStep.isUsable())
8430 return nullptr;
8431 llvm::APSInt LRes, SRes;
8432 bool IsLowerConst = false, IsStepConst = false;
8433 if (std::optional<llvm::APSInt> Res =
8434 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8435 LRes = *Res;
8436 IsLowerConst = true;
8437 }
8438 if (std::optional<llvm::APSInt> Res =
8439 Step->getIntegerConstantExpr(SemaRef.Context)) {
8440 SRes = *Res;
8441 IsStepConst = true;
8442 }
8443 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8444 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8445 (TestIsStrictOp && LRes.isStrictlyPositive()));
8446 bool NeedToReorganize = false;
8447 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8448 if (!NoNeedToConvert && IsLowerConst &&
8449 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8450 NoNeedToConvert = true;
8451 if (RoundToStep) {
8452 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8453 ? LRes.getBitWidth()
8454 : SRes.getBitWidth();
8455 LRes = LRes.extend(BW + 1);
8456 LRes.setIsSigned(true);
8457 SRes = SRes.extend(BW + 1);
8458 SRes.setIsSigned(true);
8459 LRes -= SRes;
8460 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8461 LRes = LRes.trunc(BW);
8462 }
8463 if (TestIsStrictOp) {
8464 unsigned BW = LRes.getBitWidth();
8465 LRes = LRes.extend(BW + 1);
8466 LRes.setIsSigned(true);
8467 ++LRes;
8468 NoNeedToConvert =
8469 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8470 // truncate to the original bitwidth.
8471 LRes = LRes.trunc(BW);
8472 }
8473 NeedToReorganize = NoNeedToConvert;
8474 }
8475 llvm::APSInt URes;
8476 bool IsUpperConst = false;
8477 if (std::optional<llvm::APSInt> Res =
8478 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8479 URes = *Res;
8480 IsUpperConst = true;
8481 }
8482 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8483 (!RoundToStep || IsStepConst)) {
8484 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8485 : URes.getBitWidth();
8486 LRes = LRes.extend(BW + 1);
8487 LRes.setIsSigned(true);
8488 URes = URes.extend(BW + 1);
8489 URes.setIsSigned(true);
8490 URes -= LRes;
8491 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8492 NeedToReorganize = NoNeedToConvert;
8493 }
8494 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8495 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8496 // unsigned.
8497 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8498 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8499 QualType LowerTy = Lower->getType();
8500 QualType UpperTy = Upper->getType();
8501 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8502 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8503 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8504 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8506 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8507 Upper =
8508 SemaRef
8510 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8512 .get();
8513 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8514 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8515 }
8516 }
8517 if (!Lower || !Upper || NewStep.isInvalid())
8518 return nullptr;
8519
8520 ExprResult Diff;
8521 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8522 // 1]).
8523 if (NeedToReorganize) {
8524 Diff = Lower;
8525
8526 if (RoundToStep) {
8527 // Lower - Step
8528 Diff =
8529 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8530 if (!Diff.isUsable())
8531 return nullptr;
8532 }
8533
8534 // Lower - Step [+ 1]
8535 if (TestIsStrictOp)
8536 Diff = SemaRef.BuildBinOp(
8537 S, DefaultLoc, BO_Add, Diff.get(),
8538 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8539 if (!Diff.isUsable())
8540 return nullptr;
8541
8542 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8543 if (!Diff.isUsable())
8544 return nullptr;
8545
8546 // Upper - (Lower - Step [+ 1]).
8547 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8548 if (!Diff.isUsable())
8549 return nullptr;
8550 } else {
8551 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8552
8553 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8554 // BuildBinOp already emitted error, this one is to point user to upper
8555 // and lower bound, and to tell what is passed to 'operator-'.
8556 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8557 << Upper->getSourceRange() << Lower->getSourceRange();
8558 return nullptr;
8559 }
8560
8561 if (!Diff.isUsable())
8562 return nullptr;
8563
8564 // Upper - Lower [- 1]
8565 if (TestIsStrictOp)
8566 Diff = SemaRef.BuildBinOp(
8567 S, DefaultLoc, BO_Sub, Diff.get(),
8568 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8569 if (!Diff.isUsable())
8570 return nullptr;
8571
8572 if (RoundToStep) {
8573 // Upper - Lower [- 1] + Step
8574 Diff =
8575 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8576 if (!Diff.isUsable())
8577 return nullptr;
8578 }
8579 }
8580
8581 // Parentheses (for dumping/debugging purposes only).
8582 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8583 if (!Diff.isUsable())
8584 return nullptr;
8585
8586 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8587 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8588 if (!Diff.isUsable())
8589 return nullptr;
8590
8591 return Diff.get();
8592}
8593
8594/// Build the expression to calculate the number of iterations.
8595Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8596 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8597 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8598 QualType VarType = LCDecl->getType().getNonReferenceType();
8599 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8600 !SemaRef.getLangOpts().CPlusPlus)
8601 return nullptr;
8602 Expr *LBVal = LB;
8603 Expr *UBVal = UB;
8604 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8605 // max(LB(MinVal), LB(MaxVal)))
8606 if (InitDependOnLC) {
8607 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8608 if (!IS.MinValue || !IS.MaxValue)
8609 return nullptr;
8610 // OuterVar = Min
8611 ExprResult MinValue =
8612 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8613 if (!MinValue.isUsable())
8614 return nullptr;
8615
8616 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8617 IS.CounterVar, MinValue.get());
8618 if (!LBMinVal.isUsable())
8619 return nullptr;
8620 // OuterVar = Min, LBVal
8621 LBMinVal =
8622 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8623 if (!LBMinVal.isUsable())
8624 return nullptr;
8625 // (OuterVar = Min, LBVal)
8626 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8627 if (!LBMinVal.isUsable())
8628 return nullptr;
8629
8630 // OuterVar = Max
8631 ExprResult MaxValue =
8632 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8633 if (!MaxValue.isUsable())
8634 return nullptr;
8635
8636 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8637 IS.CounterVar, MaxValue.get());
8638 if (!LBMaxVal.isUsable())
8639 return nullptr;
8640 // OuterVar = Max, LBVal
8641 LBMaxVal =
8642 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8643 if (!LBMaxVal.isUsable())
8644 return nullptr;
8645 // (OuterVar = Max, LBVal)
8646 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8647 if (!LBMaxVal.isUsable())
8648 return nullptr;
8649
8650 Expr *LBMin =
8651 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
8652 Expr *LBMax =
8653 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
8654 if (!LBMin || !LBMax)
8655 return nullptr;
8656 // LB(MinVal) < LB(MaxVal)
8657 ExprResult MinLessMaxRes =
8658 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8659 if (!MinLessMaxRes.isUsable())
8660 return nullptr;
8661 Expr *MinLessMax =
8662 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
8663 .get();
8664 if (!MinLessMax)
8665 return nullptr;
8666 if (*TestIsLessOp) {
8667 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8668 // LB(MaxVal))
8669 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8670 MinLessMax, LBMin, LBMax);
8671 if (!MinLB.isUsable())
8672 return nullptr;
8673 LBVal = MinLB.get();
8674 } else {
8675 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8676 // LB(MaxVal))
8677 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8678 MinLessMax, LBMax, LBMin);
8679 if (!MaxLB.isUsable())
8680 return nullptr;
8681 LBVal = MaxLB.get();
8682 }
8683 // OuterVar = LB
8684 LBMinVal =
8685 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8686 if (!LBMinVal.isUsable())
8687 return nullptr;
8688 LBVal = LBMinVal.get();
8689 }
8690 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8691 // min(UB(MinVal), UB(MaxVal))
8692 if (CondDependOnLC) {
8693 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8694 if (!IS.MinValue || !IS.MaxValue)
8695 return nullptr;
8696 // OuterVar = Min
8697 ExprResult MinValue =
8698 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8699 if (!MinValue.isUsable())
8700 return nullptr;
8701
8702 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8703 IS.CounterVar, MinValue.get());
8704 if (!UBMinVal.isUsable())
8705 return nullptr;
8706 // OuterVar = Min, UBVal
8707 UBMinVal =
8708 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
8709 if (!UBMinVal.isUsable())
8710 return nullptr;
8711 // (OuterVar = Min, UBVal)
8712 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
8713 if (!UBMinVal.isUsable())
8714 return nullptr;
8715
8716 // OuterVar = Max
8717 ExprResult MaxValue =
8718 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8719 if (!MaxValue.isUsable())
8720 return nullptr;
8721
8722 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8723 IS.CounterVar, MaxValue.get());
8724 if (!UBMaxVal.isUsable())
8725 return nullptr;
8726 // OuterVar = Max, UBVal
8727 UBMaxVal =
8728 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
8729 if (!UBMaxVal.isUsable())
8730 return nullptr;
8731 // (OuterVar = Max, UBVal)
8732 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
8733 if (!UBMaxVal.isUsable())
8734 return nullptr;
8735
8736 Expr *UBMin =
8737 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
8738 Expr *UBMax =
8739 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
8740 if (!UBMin || !UBMax)
8741 return nullptr;
8742 // UB(MinVal) > UB(MaxVal)
8743 ExprResult MinGreaterMaxRes =
8744 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8745 if (!MinGreaterMaxRes.isUsable())
8746 return nullptr;
8747 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
8748 Captures, ".min_greater_max")
8749 .get();
8750 if (!MinGreaterMax)
8751 return nullptr;
8752 if (*TestIsLessOp) {
8753 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8754 // UB(MaxVal))
8755 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
8756 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8757 if (!MaxUB.isUsable())
8758 return nullptr;
8759 UBVal = MaxUB.get();
8760 } else {
8761 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
8762 // UB(MaxVal))
8763 ExprResult MinUB = SemaRef.ActOnConditionalOp(
8764 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
8765 if (!MinUB.isUsable())
8766 return nullptr;
8767 UBVal = MinUB.get();
8768 }
8769 }
8770 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
8771 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
8772 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
8773 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
8774 if (!Upper || !Lower)
8775 return nullptr;
8776
8777 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8778 Step, VarType, TestIsStrictOp,
8779 /*RoundToStep=*/true, Captures);
8780 if (!Diff.isUsable())
8781 return nullptr;
8782
8783 // OpenMP runtime requires 32-bit or 64-bit loop variables.
8784 QualType Type = Diff.get()->getType();
8785 ASTContext &C = SemaRef.Context;
8786 bool UseVarType = VarType->hasIntegerRepresentation() &&
8787 C.getTypeSize(Type) > C.getTypeSize(VarType);
8788 if (!Type->isIntegerType() || UseVarType) {
8789 unsigned NewSize =
8790 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
8791 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
8793 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
8794 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
8795 Diff = SemaRef.PerformImplicitConversion(Diff.get(), Type,
8797 /*AllowExplicit=*/true);
8798 if (!Diff.isUsable())
8799 return nullptr;
8800 }
8801 }
8802 if (LimitedType) {
8803 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
8804 if (NewSize != C.getTypeSize(Type)) {
8805 if (NewSize < C.getTypeSize(Type)) {
8806 assert(NewSize == 64 && "incorrect loop var size");
8807 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8808 << InitSrcRange << ConditionSrcRange;
8809 }
8810 QualType NewType = C.getIntTypeForBitwidth(
8812 C.getTypeSize(Type) < NewSize);
8813 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
8814 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
8816 /*AllowExplicit=*/true);
8817 if (!Diff.isUsable())
8818 return nullptr;
8819 }
8820 }
8821 }
8822
8823 return Diff.get();
8824}
8825
8826std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
8827 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8828 // Do not build for iterators, they cannot be used in non-rectangular loop
8829 // nests.
8830 if (LCDecl->getType()->isRecordType())
8831 return std::make_pair(nullptr, nullptr);
8832 // If we subtract, the min is in the condition, otherwise the min is in the
8833 // init value.
8834 Expr *MinExpr = nullptr;
8835 Expr *MaxExpr = nullptr;
8836 Expr *LBExpr = *TestIsLessOp ? LB : UB;
8837 Expr *UBExpr = *TestIsLessOp ? UB : LB;
8838 bool LBNonRect =
8839 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
8840 bool UBNonRect =
8841 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
8842 Expr *Lower =
8843 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
8844 Expr *Upper =
8845 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
8846 if (!Upper || !Lower)
8847 return std::make_pair(nullptr, nullptr);
8848
8849 if (*TestIsLessOp)
8850 MinExpr = Lower;
8851 else
8852 MaxExpr = Upper;
8853
8854 // Build minimum/maximum value based on number of iterations.
8855 QualType VarType = LCDecl->getType().getNonReferenceType();
8856
8857 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8858 Step, VarType, TestIsStrictOp,
8859 /*RoundToStep=*/false, Captures);
8860 if (!Diff.isUsable())
8861 return std::make_pair(nullptr, nullptr);
8862
8863 // ((Upper - Lower [- 1]) / Step) * Step
8864 // Parentheses (for dumping/debugging purposes only).
8865 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8866 if (!Diff.isUsable())
8867 return std::make_pair(nullptr, nullptr);
8868
8869 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8870 if (!NewStep.isUsable())
8871 return std::make_pair(nullptr, nullptr);
8872 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
8873 if (!Diff.isUsable())
8874 return std::make_pair(nullptr, nullptr);
8875
8876 // Parentheses (for dumping/debugging purposes only).
8877 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8878 if (!Diff.isUsable())
8879 return std::make_pair(nullptr, nullptr);
8880
8881 // Convert to the ptrdiff_t, if original type is pointer.
8882 if (VarType->isAnyPointerType() &&
8883 !SemaRef.Context.hasSameType(
8884 Diff.get()->getType(),
8886 Diff = SemaRef.PerformImplicitConversion(
8887 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
8888 AssignmentAction::Converting, /*AllowExplicit=*/true);
8889 }
8890 if (!Diff.isUsable())
8891 return std::make_pair(nullptr, nullptr);
8892
8893 if (*TestIsLessOp) {
8894 // MinExpr = Lower;
8895 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
8896 Diff = SemaRef.BuildBinOp(
8897 S, DefaultLoc, BO_Add,
8898 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
8899 Diff.get());
8900 if (!Diff.isUsable())
8901 return std::make_pair(nullptr, nullptr);
8902 } else {
8903 // MaxExpr = Upper;
8904 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
8905 Diff = SemaRef.BuildBinOp(
8906 S, DefaultLoc, BO_Sub,
8907 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8908 Diff.get());
8909 if (!Diff.isUsable())
8910 return std::make_pair(nullptr, nullptr);
8911 }
8912
8913 // Convert to the original type.
8914 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
8915 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
8917 /*AllowExplicit=*/true);
8918 if (!Diff.isUsable())
8919 return std::make_pair(nullptr, nullptr);
8920
8921 Sema::TentativeAnalysisScope Trap(SemaRef);
8922 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
8923 if (!Diff.isUsable())
8924 return std::make_pair(nullptr, nullptr);
8925
8926 if (*TestIsLessOp)
8927 MaxExpr = Diff.get();
8928 else
8929 MinExpr = Diff.get();
8930
8931 return std::make_pair(MinExpr, MaxExpr);
8932}
8933
8934Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
8935 if (InitDependOnLC || CondDependOnLC)
8936 return Condition;
8937 return nullptr;
8938}
8939
8940Expr *OpenMPIterationSpaceChecker::buildPreCond(
8941 Scope *S, Expr *Cond,
8942 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8943 // Do not build a precondition when the condition/initialization is dependent
8944 // to prevent pessimistic early loop exit.
8945 // TODO: this can be improved by calculating min/max values but not sure that
8946 // it will be very effective.
8947 if (CondDependOnLC || InitDependOnLC)
8948 return SemaRef
8950 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
8951 SemaRef.Context.BoolTy, /*Action=*/AssignmentAction::Casting,
8952 /*AllowExplicit=*/true)
8953 .get();
8954
8955 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
8956 Sema::TentativeAnalysisScope Trap(SemaRef);
8957
8958 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
8959 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
8960 if (!NewLB.isUsable() || !NewUB.isUsable())
8961 return nullptr;
8962
8963 ExprResult CondExpr =
8964 SemaRef.BuildBinOp(S, DefaultLoc,
8965 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
8966 : (TestIsStrictOp ? BO_GT : BO_GE),
8967 NewLB.get(), NewUB.get());
8968 if (CondExpr.isUsable()) {
8969 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
8970 SemaRef.Context.BoolTy))
8971 CondExpr = SemaRef.PerformImplicitConversion(
8972 CondExpr.get(), SemaRef.Context.BoolTy,
8973 /*Action=*/AssignmentAction::Casting,
8974 /*AllowExplicit=*/true);
8975 }
8976
8977 // Otherwise use original loop condition and evaluate it in runtime.
8978 return CondExpr.isUsable() ? CondExpr.get() : Cond;
8979}
8980
8981/// Build reference expression to the counter be used for codegen.
8982DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
8983 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8984 DSAStackTy &DSA) const {
8985 auto *VD = dyn_cast<VarDecl>(LCDecl);
8986 if (!VD) {
8987 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(LCDecl);
8989 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
8990 const DSAStackTy::DSAVarData Data =
8991 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
8992 // If the loop control decl is explicitly marked as private, do not mark it
8993 // as captured again.
8994 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
8995 Captures.insert(std::make_pair(LCRef, Ref));
8996 return Ref;
8997 }
8998 return cast<DeclRefExpr>(LCRef);
8999}
9000
9001Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9002 if (LCDecl && !LCDecl->isInvalidDecl()) {
9004 VarDecl *PrivateVar = buildVarDecl(
9005 SemaRef, DefaultLoc, Type, LCDecl->getName(),
9006 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9007 isa<VarDecl>(LCDecl)
9008 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
9009 : nullptr);
9010 if (PrivateVar->isInvalidDecl())
9011 return nullptr;
9012 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
9013 }
9014 return nullptr;
9015}
9016
9017/// Build initialization of the counter to be used for codegen.
9018Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9019
9020/// Build step of the counter be used for codegen.
9021Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9022
9023Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9024 Scope *S, Expr *Counter,
9025 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9026 Expr *Inc, OverloadedOperatorKind OOK) {
9027 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
9028 if (!Cnt)
9029 return nullptr;
9030 if (Inc) {
9031 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9032 "Expected only + or - operations for depend clauses.");
9033 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9034 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
9035 if (!Cnt)
9036 return nullptr;
9037 }
9038 QualType VarType = LCDecl->getType().getNonReferenceType();
9039 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9040 !SemaRef.getLangOpts().CPlusPlus)
9041 return nullptr;
9042 // Upper - Lower
9043 Expr *Upper =
9044 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9045 Expr *Lower =
9046 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9047 if (!Upper || !Lower)
9048 return nullptr;
9049
9050 ExprResult Diff = calculateNumIters(
9051 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9052 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9053 if (!Diff.isUsable())
9054 return nullptr;
9055
9056 return Diff.get();
9057}
9058} // namespace
9059
9061 Stmt *Init) {
9062 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9063 assert(Init && "Expected loop in canonical form.");
9064 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9065 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9066 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
9067 return;
9068
9069 DSAStack->loopStart();
9071 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9072 *DSAStack, ForLoc, EmptyDeclSet);
9073 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9074 if (ValueDecl *D = ISC.getLoopDecl()) {
9075 auto *VD = dyn_cast<VarDecl>(D);
9076 DeclRefExpr *PrivateRef = nullptr;
9077 if (!VD) {
9079 VD = Private;
9080 } else {
9081 PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(),
9082 /*WithInit=*/false);
9083 VD = cast<VarDecl>(PrivateRef->getDecl());
9084 }
9085 }
9086 DSAStack->addLoopControlVariable(D, VD);
9087 const Decl *LD = DSAStack->getPossiblyLoopCounter();
9088 if (LD != D->getCanonicalDecl()) {
9089 DSAStack->resetPossibleLoopCounter();
9090 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9092 SemaRef, const_cast<VarDecl *>(Var),
9093 Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
9094 /*RefersToCapture=*/true));
9095 }
9096 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9097 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9098 // associated for-loop of a simd construct with just one associated
9099 // for-loop may be listed in a linear clause with a constant-linear-step
9100 // that is the increment of the associated for-loop. The loop iteration
9101 // variable(s) in the associated for-loop(s) of a for or parallel for
9102 // construct may be listed in a private or lastprivate clause.
9103 DSAStackTy::DSAVarData DVar =
9104 DSAStack->getTopDSA(D, /*FromParent=*/false);
9105 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9106 // is declared in the loop and it is predetermined as a private.
9107 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9108 OpenMPClauseKind PredeterminedCKind =
9110 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9111 : OMPC_private;
9112 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
9113 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9114 };
9115 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9116 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9117 (getLangOpts().OpenMP <= 45 ||
9118 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9120 IsOpenMPTaskloopDirective(DKind) ||
9122 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9123 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9124 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9125 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9126 << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind)
9127 << getOpenMPClauseName(PredeterminedCKind);
9128 if (DVar.RefExpr == nullptr)
9129 DVar.CKind = PredeterminedCKind;
9130 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
9131 } else if (LoopDeclRefExpr) {
9132 // Make the loop iteration variable private (for worksharing
9133 // constructs), linear (for simd directives with the only one
9134 // associated loop) or lastprivate (for simd directives with several
9135 // collapsed or ordered loops).
9136 if (DVar.CKind == OMPC_unknown)
9137 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9138 }
9139 }
9140 }
9141 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9142}
9143
9144namespace {
9145// Utility for OpenMP doacross clause kind
9146class OMPDoacrossKind {
9147public:
9148 bool isSource(const OMPDoacrossClause *C) {
9149 return C->getDependenceType() == OMPC_DOACROSS_source ||
9150 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9151 }
9152 bool isSink(const OMPDoacrossClause *C) {
9153 return C->getDependenceType() == OMPC_DOACROSS_sink;
9154 }
9155 bool isSinkIter(const OMPDoacrossClause *C) {
9156 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9157 }
9158};
9159} // namespace
9160/// Called on a for stmt to check and extract its iteration space
9161/// for further processing (such as collapsing).
9163 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9164 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9165 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9166 Expr *OrderedLoopCountExpr,
9167 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9169 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9170 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9171 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9172 // OpenMP [2.9.1, Canonical Loop Form]
9173 // for (init-expr; test-expr; incr-expr) structured-block
9174 // for (range-decl: range-expr) structured-block
9175 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9176 S = CanonLoop->getLoopStmt();
9177 auto *For = dyn_cast_or_null<ForStmt>(S);
9178 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9179 // Ranged for is supported only in OpenMP 5.0.
9180 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9181 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9182 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9183 << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount
9184 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9185 if (TotalNestedLoopCount > 1) {
9186 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9187 SemaRef.Diag(DSA.getConstructLoc(),
9188 diag::note_omp_collapse_ordered_expr)
9189 << 2 << CollapseLoopCountExpr->getSourceRange()
9190 << OrderedLoopCountExpr->getSourceRange();
9191 else if (CollapseLoopCountExpr)
9192 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9193 diag::note_omp_collapse_ordered_expr)
9194 << 0 << CollapseLoopCountExpr->getSourceRange();
9195 else if (OrderedLoopCountExpr)
9196 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9197 diag::note_omp_collapse_ordered_expr)
9198 << 1 << OrderedLoopCountExpr->getSourceRange();
9199 }
9200 return true;
9201 }
9202 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9203 "No loop body.");
9204 // Postpone analysis in dependent contexts for ranged for loops.
9205 if (CXXFor && SemaRef.CurContext->isDependentContext())
9206 return false;
9207
9208 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9209 For ? For->getForLoc() : CXXFor->getForLoc(),
9210 CollapsedLoopVarDecls);
9211
9212 // Check init.
9213 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9214 if (ISC.checkAndSetInit(Init))
9215 return true;
9216
9217 bool HasErrors = false;
9218
9219 // Check loop variable's type.
9220 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9221 // OpenMP [2.6, Canonical Loop Form]
9222 // Var is one of the following:
9223 // A variable of signed or unsigned integer type.
9224 // For C++, a variable of a random access iterator type.
9225 // For C, a variable of a pointer type.
9226 QualType VarType = LCDecl->getType().getNonReferenceType();
9227 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9228 !VarType->isPointerType() &&
9229 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9230 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9231 << SemaRef.getLangOpts().CPlusPlus;
9232 HasErrors = true;
9233 }
9234
9235 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9236 // a Construct
9237 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9238 // parallel for construct is (are) private.
9239 // The loop iteration variable in the associated for-loop of a simd
9240 // construct with just one associated for-loop is linear with a
9241 // constant-linear-step that is the increment of the associated for-loop.
9242 // Exclude loop var from the list of variables with implicitly defined data
9243 // sharing attributes.
9244 VarsWithImplicitDSA.erase(LCDecl);
9245
9246 assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
9247
9248 // Check test-expr.
9249 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9250
9251 // Check incr-expr.
9252 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9253 }
9254
9255 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9256 return HasErrors;
9257
9258 // Build the loop's iteration space representation.
9259 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9260 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9261 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9262 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9268 Captures);
9269 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9270 ISC.buildCounterVar(Captures, DSA);
9271 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9272 ISC.buildPrivateCounterVar();
9273 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9274 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9275 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9276 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9277 ISC.getConditionSrcRange();
9278 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9279 ISC.getIncrementSrcRange();
9280 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9281 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9282 ISC.isStrictTestOp();
9283 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9284 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9285 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9286 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9287 ISC.buildFinalCondition(DSA.getCurScope());
9288 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9289 ISC.doesInitDependOnLC();
9290 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9291 ISC.doesCondDependOnLC();
9292 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9293 ISC.getLoopDependentIdx();
9294
9295 HasErrors |=
9296 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9297 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9298 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9299 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9300 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9301 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9302 if (!HasErrors && DSA.isOrderedRegion()) {
9303 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9304 if (CurrentNestedLoopCount <
9305 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9306 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9307 CurrentNestedLoopCount,
9308 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9309 DSA.getOrderedRegionParam().second->setLoopCounter(
9310 CurrentNestedLoopCount,
9311 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9312 }
9313 }
9314 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9315 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9316 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9317 unsigned NumLoops =
9318 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9319 if (CurrentNestedLoopCount >= NumLoops) {
9320 // Erroneous case - clause has some problems.
9321 continue;
9322 }
9323 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9324 Pair.second.size() <= CurrentNestedLoopCount) {
9325 // Erroneous case - clause has some problems.
9326 DependC->setLoopData(CurrentNestedLoopCount, nullptr);
9327 continue;
9328 }
9329 OMPDoacrossKind ODK;
9330 if (DoacrossC && ODK.isSink(DoacrossC) &&
9331 Pair.second.size() <= CurrentNestedLoopCount) {
9332 // Erroneous case - clause has some problems.
9333 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
9334 continue;
9335 }
9336 Expr *CntValue;
9337 SourceLocation DepLoc =
9338 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9339 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9340 (DoacrossC && ODK.isSource(DoacrossC)))
9341 CntValue = ISC.buildOrderedLoopData(
9342 DSA.getCurScope(),
9343 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9344 DepLoc);
9345 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9346 Expr *Cnt = SemaRef
9348 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9349 .get();
9350 if (!Cnt)
9351 continue;
9352 // build CounterVar - 1
9353 Expr *Inc =
9354 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
9355 .get();
9356 CntValue = ISC.buildOrderedLoopData(
9357 DSA.getCurScope(),
9358 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9359 DepLoc, Inc, clang::OO_Minus);
9360 } else
9361 CntValue = ISC.buildOrderedLoopData(
9362 DSA.getCurScope(),
9363 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9364 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9365 Pair.second[CurrentNestedLoopCount].second);
9366 if (DependC)
9367 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9368 else
9369 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9370 }
9371 }
9372
9373 return HasErrors;
9374}
9375
9376/// Build 'VarRef = Start.
9377static ExprResult
9379 ExprResult Start, bool IsNonRectangularLB,
9380 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9381 // Build 'VarRef = Start.
9382 ExprResult NewStart = IsNonRectangularLB
9383 ? Start.get()
9384 : tryBuildCapture(SemaRef, Start.get(), Captures);
9385 if (!NewStart.isUsable())
9386 return ExprError();
9387 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9388 VarRef.get()->getType())) {
9389 NewStart = SemaRef.PerformImplicitConversion(
9390 NewStart.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9391 /*AllowExplicit=*/true);
9392 if (!NewStart.isUsable())
9393 return ExprError();
9394 }
9395
9397 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9398 return Init;
9399}
9400
9401/// Build 'VarRef = Start + Iter * Step'.
9403 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9404 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9405 bool IsNonRectangularLB,
9406 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9407 // Add parentheses (for debugging purposes only).
9408 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9409 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9410 !Step.isUsable())
9411 return ExprError();
9412
9413 ExprResult NewStep = Step;
9414 if (Captures)
9415 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9416 if (NewStep.isInvalid())
9417 return ExprError();
9419 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9420 if (!Update.isUsable())
9421 return ExprError();
9422
9423 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9424 // 'VarRef = Start (+|-) Iter * Step'.
9425 if (!Start.isUsable())
9426 return ExprError();
9427 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9428 if (!NewStart.isUsable())
9429 return ExprError();
9430 if (Captures && !IsNonRectangularLB)
9431 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9432 if (NewStart.isInvalid())
9433 return ExprError();
9434
9435 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9436 ExprResult SavedUpdate = Update;
9437 ExprResult UpdateVal;
9438 if (VarRef.get()->getType()->isOverloadableType() ||
9439 NewStart.get()->getType()->isOverloadableType() ||
9440 Update.get()->getType()->isOverloadableType()) {
9441 Sema::TentativeAnalysisScope Trap(SemaRef);
9442
9443 Update =
9444 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9445 if (Update.isUsable()) {
9446 UpdateVal =
9447 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9448 VarRef.get(), SavedUpdate.get());
9449 if (UpdateVal.isUsable()) {
9450 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9451 UpdateVal.get());
9452 }
9453 }
9454 }
9455
9456 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9457 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9458 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9459 NewStart.get(), SavedUpdate.get());
9460 if (!Update.isUsable())
9461 return ExprError();
9462
9463 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9464 VarRef.get()->getType())) {
9466 Update.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9467 /*AllowExplicit=*/true);
9468 if (!Update.isUsable())
9469 return ExprError();
9470 }
9471
9472 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9473 }
9474 return Update;
9475}
9476
9477/// Convert integer expression \a E to make it have at least \a Bits
9478/// bits.
9479static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9480 if (E == nullptr)
9481 return ExprError();
9482 ASTContext &C = SemaRef.Context;
9483 QualType OldType = E->getType();
9484 unsigned HasBits = C.getTypeSize(OldType);
9485 if (HasBits >= Bits)
9486 return ExprResult(E);
9487 // OK to convert to signed, because new type has more bits than old.
9488 QualType NewType = C.getIntTypeForBitwidth(Bits, /*Signed=*/true);
9489 return SemaRef.PerformImplicitConversion(
9490 E, NewType, AssignmentAction::Converting, /*AllowExplicit=*/true);
9491}
9492
9493/// Check if the given expression \a E is a constant integer that fits
9494/// into \a Bits bits.
9495static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9496 if (E == nullptr)
9497 return false;
9498 if (std::optional<llvm::APSInt> Result =
9500 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9501 return false;
9502}
9503
9504/// Build preinits statement for the given declarations.
9506 MutableArrayRef<Decl *> PreInits) {
9507 if (!PreInits.empty()) {
9508 return new (Context) DeclStmt(
9509 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9511 }
9512 return nullptr;
9513}
9514
9515/// Append the \p Item or the content of a CompoundStmt to the list \p
9516/// TargetList.
9517///
9518/// A CompoundStmt is used as container in case multiple statements need to be
9519/// stored in lieu of using an explicit list. Flattening is necessary because
9520/// contained DeclStmts need to be visible after the execution of the list. Used
9521/// for OpenMP pre-init declarations/statements.
9523 Stmt *Item) {
9524 // nullptr represents an empty list.
9525 if (!Item)
9526 return;
9527
9528 if (auto *CS = dyn_cast<CompoundStmt>(Item))
9529 llvm::append_range(TargetList, CS->body());
9530 else
9531 TargetList.push_back(Item);
9532}
9533
9534/// Build preinits statement for the given declarations.
9535static Stmt *
9537 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9538 if (!Captures.empty()) {
9539 SmallVector<Decl *, 16> PreInits;
9540 for (const auto &Pair : Captures)
9541 PreInits.push_back(Pair.second->getDecl());
9542 return buildPreInits(Context, PreInits);
9543 }
9544 return nullptr;
9545}
9546
9547/// Build pre-init statement for the given statements.
9548static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
9549 if (PreInits.empty())
9550 return nullptr;
9551
9552 SmallVector<Stmt *> Stmts;
9553 for (Stmt *S : PreInits)
9554 appendFlattenedStmtList(Stmts, S);
9555 return CompoundStmt::Create(Context, PreInits, FPOptionsOverride(), {}, {});
9556}
9557
9558/// Build postupdate expression for the given list of postupdates expressions.
9559static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9560 Expr *PostUpdate = nullptr;
9561 if (!PostUpdates.empty()) {
9562 for (Expr *E : PostUpdates) {
9563 Expr *ConvE = S.BuildCStyleCastExpr(
9564 E->getExprLoc(),
9566 E->getExprLoc(), E)
9567 .get();
9568 PostUpdate = PostUpdate
9569 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9570 PostUpdate, ConvE)
9571 .get()
9572 : ConvE;
9573 }
9574 }
9575 return PostUpdate;
9576}
9577
9578/// Look for variables declared in the body parts of a for-loop nest. Used
9579/// for verifying loop nest structure before performing a loop collapse
9580/// operation.
9582 int NestingDepth = 0;
9583 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9584
9585public:
9586 explicit ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl *> &VD)
9587 : VarDecls(VD) {}
9588
9589 bool VisitForStmt(ForStmt *F) override {
9590 ++NestingDepth;
9591 TraverseStmt(F->getBody());
9592 --NestingDepth;
9593 return false;
9594 }
9595
9597 ++NestingDepth;
9598 TraverseStmt(RF->getBody());
9599 --NestingDepth;
9600 return false;
9601 }
9602
9603 bool VisitVarDecl(VarDecl *D) override {
9604 Decl *C = D->getCanonicalDecl();
9605 if (NestingDepth > 0)
9606 VarDecls.insert(C);
9607 return true;
9608 }
9609};
9610
9611/// Called on a for stmt to check itself and nested loops (if any).
9612/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9613/// number of collapsed loops otherwise.
9614static unsigned
9615checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9616 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9617 DSAStackTy &DSA,
9618 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9620 unsigned NestedLoopCount = 1;
9621 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9623 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopVarDecls;
9624
9625 if (CollapseLoopCountExpr) {
9626 // Found 'collapse' clause - calculate collapse number.
9628 if (!CollapseLoopCountExpr->isValueDependent() &&
9629 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9630 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9631
9632 ForVarDeclFinder FVDF{CollapsedLoopVarDecls};
9633 FVDF.TraverseStmt(AStmt);
9634 } else {
9635 Built.clear(/*Size=*/1);
9636 return 1;
9637 }
9638 }
9639 unsigned OrderedLoopCount = 1;
9640 if (OrderedLoopCountExpr) {
9641 // Found 'ordered' clause - calculate collapse number.
9642 Expr::EvalResult EVResult;
9643 if (!OrderedLoopCountExpr->isValueDependent() &&
9644 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9645 SemaRef.getASTContext())) {
9646 llvm::APSInt Result = EVResult.Val.getInt();
9647 if (Result.getLimitedValue() < NestedLoopCount) {
9648 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9649 diag::err_omp_wrong_ordered_loop_count)
9650 << OrderedLoopCountExpr->getSourceRange();
9651 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9652 diag::note_collapse_loop_count)
9653 << CollapseLoopCountExpr->getSourceRange();
9654 }
9655 OrderedLoopCount = Result.getLimitedValue();
9656 } else {
9657 Built.clear(/*Size=*/1);
9658 return 1;
9659 }
9660 }
9661 // This is helper routine for loop directives (e.g., 'for', 'simd',
9662 // 'for simd', etc.).
9663 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9664 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9665 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9668 SupportsNonPerfectlyNested, NumLoops,
9669 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9670 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9671 &IterSpaces, &Captures,
9672 &CollapsedLoopVarDecls](unsigned Cnt, Stmt *CurStmt) {
9674 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9675 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9676 VarsWithImplicitDSA, IterSpaces, Captures,
9677 CollapsedLoopVarDecls))
9678 return true;
9679 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9680 IterSpaces[Cnt].CounterVar) {
9681 // Handle initialization of captured loop iterator variables.
9682 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9683 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9684 Captures[DRE] = DRE;
9685 }
9686 }
9687 return false;
9688 },
9689 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9690 Stmt *DependentPreInits = Transform->getPreInits();
9691 if (!DependentPreInits)
9692 return;
9693
9694 // Search for pre-init declared variables that need to be captured
9695 // to be referenceable inside the directive.
9696 SmallVector<Stmt *> Constituents;
9697 appendFlattenedStmtList(Constituents, DependentPreInits);
9698 for (Stmt *S : Constituents) {
9699 if (auto *DC = dyn_cast<DeclStmt>(S)) {
9700 for (Decl *C : DC->decls()) {
9701 auto *D = cast<VarDecl>(C);
9703 SemaRef, D, D->getType().getNonReferenceType(),
9704 Transform->getBeginLoc());
9705 Captures[Ref] = Ref;
9706 }
9707 }
9708 }
9709 }))
9710 return 0;
9711
9712 Built.clear(/*size=*/NestedLoopCount);
9713
9714 if (SemaRef.CurContext->isDependentContext())
9715 return NestedLoopCount;
9716
9717 // An example of what is generated for the following code:
9718 //
9719 // #pragma omp simd collapse(2) ordered(2)
9720 // for (i = 0; i < NI; ++i)
9721 // for (k = 0; k < NK; ++k)
9722 // for (j = J0; j < NJ; j+=2) {
9723 // <loop body>
9724 // }
9725 //
9726 // We generate the code below.
9727 // Note: the loop body may be outlined in CodeGen.
9728 // Note: some counters may be C++ classes, operator- is used to find number of
9729 // iterations and operator+= to calculate counter value.
9730 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9731 // or i64 is currently supported).
9732 //
9733 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9734 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9735 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9736 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9737 // // similar updates for vars in clauses (e.g. 'linear')
9738 // <loop body (using local i and j)>
9739 // }
9740 // i = NI; // assign final values of counters
9741 // j = NJ;
9742 //
9743
9744 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9745 // the iteration counts of the collapsed for loops.
9746 // Precondition tests if there is at least one iteration (all conditions are
9747 // true).
9748 auto PreCond = ExprResult(IterSpaces[0].PreCond);
9749 Expr *N0 = IterSpaces[0].NumIterations;
9750 ExprResult LastIteration32 = widenIterationCount(
9751 /*Bits=*/32,
9752 SemaRef
9753 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
9755 /*AllowExplicit=*/true)
9756 .get(),
9757 SemaRef);
9758 ExprResult LastIteration64 = widenIterationCount(
9759 /*Bits=*/64,
9760 SemaRef
9761 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
9763 /*AllowExplicit=*/true)
9764 .get(),
9765 SemaRef);
9766
9767 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
9768 return NestedLoopCount;
9769
9770 ASTContext &C = SemaRef.Context;
9771 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
9772
9773 Scope *CurScope = DSA.getCurScope();
9774 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9775 if (PreCond.isUsable()) {
9776 PreCond =
9777 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
9778 PreCond.get(), IterSpaces[Cnt].PreCond);
9779 }
9780 Expr *N = IterSpaces[Cnt].NumIterations;
9782 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
9783 if (LastIteration32.isUsable())
9784 LastIteration32 = SemaRef.BuildBinOp(
9785 CurScope, Loc, BO_Mul, LastIteration32.get(),
9786 SemaRef
9789 /*AllowExplicit=*/true)
9790 .get());
9791 if (LastIteration64.isUsable())
9792 LastIteration64 = SemaRef.BuildBinOp(
9793 CurScope, Loc, BO_Mul, LastIteration64.get(),
9794 SemaRef
9797 /*AllowExplicit=*/true)
9798 .get());
9799 }
9800
9801 // Choose either the 32-bit or 64-bit version.
9802 ExprResult LastIteration = LastIteration64;
9803 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
9804 (LastIteration32.isUsable() &&
9805 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
9806 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9807 fitsInto(
9808 /*Bits=*/32,
9809 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
9810 LastIteration64.get(), SemaRef))))
9811 LastIteration = LastIteration32;
9812 QualType VType = LastIteration.get()->getType();
9813 QualType RealVType = VType;
9814 QualType StrideVType = VType;
9815 if (isOpenMPTaskLoopDirective(DKind)) {
9816 VType =
9817 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9818 StrideVType =
9819 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9820 }
9821
9822 if (!LastIteration.isUsable())
9823 return 0;
9824
9825 // Save the number of iterations.
9826 ExprResult NumIterations = LastIteration;
9827 {
9828 LastIteration = SemaRef.BuildBinOp(
9829 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
9830 LastIteration.get(),
9831 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9832 if (!LastIteration.isUsable())
9833 return 0;
9834 }
9835
9836 // Calculate the last iteration number beforehand instead of doing this on
9837 // each iteration. Do not do this if the number of iterations may be kfold-ed.
9838 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
9839 ExprResult CalcLastIteration;
9840 if (!IsConstant) {
9841 ExprResult SaveRef =
9842 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
9843 LastIteration = SaveRef;
9844
9845 // Prepare SaveRef + 1.
9846 NumIterations = SemaRef.BuildBinOp(
9847 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
9848 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9849 if (!NumIterations.isUsable())
9850 return 0;
9851 }
9852
9853 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
9854
9855 // Build variables passed into runtime, necessary for worksharing directives.
9856 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9861 // Lower bound variable, initialized with zero.
9862 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
9863 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
9864 SemaRef.AddInitializerToDecl(LBDecl,
9865 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9866 /*DirectInit=*/false);
9867
9868 // Upper bound variable, initialized with last iteration number.
9869 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
9870 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
9871 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
9872 /*DirectInit=*/false);
9873
9874 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
9875 // This will be used to implement clause 'lastprivate'.
9876 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
9877 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
9878 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
9879 SemaRef.AddInitializerToDecl(ILDecl,
9880 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9881 /*DirectInit=*/false);
9882
9883 // Stride variable returned by runtime (we initialize it to 1 by default).
9884 VarDecl *STDecl =
9885 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
9886 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
9887 SemaRef.AddInitializerToDecl(STDecl,
9888 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
9889 /*DirectInit=*/false);
9890
9891 // Build expression: UB = min(UB, LastIteration)
9892 // It is necessary for CodeGen of directives with static scheduling.
9893 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
9894 UB.get(), LastIteration.get());
9895 ExprResult CondOp = SemaRef.ActOnConditionalOp(
9896 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
9897 LastIteration.get(), UB.get());
9898 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
9899 CondOp.get());
9900 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue=*/false);
9901
9902 // If we have a combined directive that combines 'distribute', 'for' or
9903 // 'simd' we need to be able to access the bounds of the schedule of the
9904 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
9905 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
9907 // Lower bound variable, initialized with zero.
9908 VarDecl *CombLBDecl =
9909 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
9910 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
9911 SemaRef.AddInitializerToDecl(
9912 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9913 /*DirectInit=*/false);
9914
9915 // Upper bound variable, initialized with last iteration number.
9916 VarDecl *CombUBDecl =
9917 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
9918 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
9919 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
9920 /*DirectInit=*/false);
9921
9922 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
9923 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
9924 ExprResult CombCondOp =
9925 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
9926 LastIteration.get(), CombUB.get());
9927 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
9928 CombCondOp.get());
9929 CombEUB =
9930 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue=*/false);
9931
9932 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
9933 // We expect to have at least 2 more parameters than the 'parallel'
9934 // directive does - the lower and upper bounds of the previous schedule.
9935 assert(CD->getNumParams() >= 4 &&
9936 "Unexpected number of parameters in loop combined directive");
9937
9938 // Set the proper type for the bounds given what we learned from the
9939 // enclosed loops.
9940 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
9941 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
9942
9943 // Previous lower and upper bounds are obtained from the region
9944 // parameters.
9945 PrevLB =
9946 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
9947 PrevUB =
9948 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
9949 }
9950 }
9951
9952 // Build the iteration variable and its initialization before loop.
9953 ExprResult IV;
9954 ExprResult Init, CombInit;
9955 {
9956 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
9957 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
9958 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
9963 ? LB.get()
9964 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
9965 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
9966 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue=*/false);
9967
9969 Expr *CombRHS =
9974 ? CombLB.get()
9975 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
9976 CombInit =
9977 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
9978 CombInit =
9979 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue=*/false);
9980 }
9981 }
9982
9983 bool UseStrictCompare =
9984 RealVType->hasUnsignedIntegerRepresentation() &&
9985 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
9986 return LIS.IsStrictCompare;
9987 });
9988 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
9989 // unsigned IV)) for worksharing loops.
9990 SourceLocation CondLoc = AStmt->getBeginLoc();
9991 Expr *BoundUB = UB.get();
9992 if (UseStrictCompare) {
9993 BoundUB =
9994 SemaRef
9995 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
9996 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
9997 .get();
9998 BoundUB =
9999 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue=*/false).get();
10000 }
10001 ExprResult Cond =
10006 ? SemaRef.BuildBinOp(CurScope, CondLoc,
10007 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
10008 BoundUB)
10009 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10010 NumIterations.get());
10011 ExprResult CombDistCond;
10013 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10014 NumIterations.get());
10015 }
10016
10017 ExprResult CombCond;
10019 Expr *BoundCombUB = CombUB.get();
10020 if (UseStrictCompare) {
10021 BoundCombUB =
10022 SemaRef
10023 .BuildBinOp(
10024 CurScope, CondLoc, BO_Add, BoundCombUB,
10025 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10026 .get();
10027 BoundCombUB =
10028 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue=*/false)
10029 .get();
10030 }
10031 CombCond =
10032 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10033 IV.get(), BoundCombUB);
10034 }
10035 // Loop increment (IV = IV + 1)
10036 SourceLocation IncLoc = AStmt->getBeginLoc();
10037 ExprResult Inc =
10038 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
10039 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
10040 if (!Inc.isUsable())
10041 return 0;
10042 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
10043 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue=*/false);
10044 if (!Inc.isUsable())
10045 return 0;
10046
10047 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10048 // Used for directives with static scheduling.
10049 // In combined construct, add combined version that use CombLB and CombUB
10050 // base variables for the update
10051 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10056 // LB + ST
10057 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
10058 if (!NextLB.isUsable())
10059 return 0;
10060 // LB = LB + ST
10061 NextLB =
10062 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
10063 NextLB =
10064 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue=*/false);
10065 if (!NextLB.isUsable())
10066 return 0;
10067 // UB + ST
10068 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
10069 if (!NextUB.isUsable())
10070 return 0;
10071 // UB = UB + ST
10072 NextUB =
10073 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
10074 NextUB =
10075 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue=*/false);
10076 if (!NextUB.isUsable())
10077 return 0;
10079 CombNextLB =
10080 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
10081 if (!NextLB.isUsable())
10082 return 0;
10083 // LB = LB + ST
10084 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
10085 CombNextLB.get());
10086 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
10087 /*DiscardedValue=*/false);
10088 if (!CombNextLB.isUsable())
10089 return 0;
10090 // UB + ST
10091 CombNextUB =
10092 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
10093 if (!CombNextUB.isUsable())
10094 return 0;
10095 // UB = UB + ST
10096 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
10097 CombNextUB.get());
10098 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
10099 /*DiscardedValue=*/false);
10100 if (!CombNextUB.isUsable())
10101 return 0;
10102 }
10103 }
10104
10105 // Create increment expression for distribute loop when combined in a same
10106 // directive with for as IV = IV + ST; ensure upper bound expression based
10107 // on PrevUB instead of NumIterations - used to implement 'for' when found
10108 // in combination with 'distribute', like in 'distribute parallel for'
10109 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10110 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10112 DistCond = SemaRef.BuildBinOp(
10113 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10114 assert(DistCond.isUsable() && "distribute cond expr was not built");
10115
10116 DistInc =
10117 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10118 assert(DistInc.isUsable() && "distribute inc expr was not built");
10119 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10120 DistInc.get());
10121 DistInc =
10122 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue=*/false);
10123 assert(DistInc.isUsable() && "distribute inc expr was not built");
10124
10125 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10126 // construct
10127 ExprResult NewPrevUB = PrevUB;
10128 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10129 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10130 PrevUB.get()->getType())) {
10131 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10132 DistEUBLoc,
10134 DistEUBLoc, NewPrevUB.get());
10135 if (!NewPrevUB.isUsable())
10136 return 0;
10137 }
10138 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10139 UB.get(), NewPrevUB.get());
10140 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10141 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10142 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10143 CondOp.get());
10144 PrevEUB =
10145 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue=*/false);
10146
10147 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10148 // parallel for is in combination with a distribute directive with
10149 // schedule(static, 1)
10150 Expr *BoundPrevUB = PrevUB.get();
10151 if (UseStrictCompare) {
10152 BoundPrevUB =
10153 SemaRef
10154 .BuildBinOp(
10155 CurScope, CondLoc, BO_Add, BoundPrevUB,
10156 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10157 .get();
10158 BoundPrevUB =
10159 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue=*/false)
10160 .get();
10161 }
10162 ParForInDistCond =
10163 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10164 IV.get(), BoundPrevUB);
10165 }
10166
10167 // Build updates and final values of the loop counters.
10168 bool HasErrors = false;
10169 Built.Counters.resize(NestedLoopCount);
10170 Built.Inits.resize(NestedLoopCount);
10171 Built.Updates.resize(NestedLoopCount);
10172 Built.Finals.resize(NestedLoopCount);
10173 Built.DependentCounters.resize(NestedLoopCount);
10174 Built.DependentInits.resize(NestedLoopCount);
10175 Built.FinalsConditions.resize(NestedLoopCount);
10176 {
10177 // We implement the following algorithm for obtaining the
10178 // original loop iteration variable values based on the
10179 // value of the collapsed loop iteration variable IV.
10180 //
10181 // Let n+1 be the number of collapsed loops in the nest.
10182 // Iteration variables (I0, I1, .... In)
10183 // Iteration counts (N0, N1, ... Nn)
10184 //
10185 // Acc = IV;
10186 //
10187 // To compute Ik for loop k, 0 <= k <= n, generate:
10188 // Prod = N(k+1) * N(k+2) * ... * Nn;
10189 // Ik = Acc / Prod;
10190 // Acc -= Ik * Prod;
10191 //
10192 ExprResult Acc = IV;
10193 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10194 LoopIterationSpace &IS = IterSpaces[Cnt];
10195 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10197
10198 // Compute prod
10199 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10200 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10201 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10202 IterSpaces[K].NumIterations);
10203
10204 // Iter = Acc / Prod
10205 // If there is at least one more inner loop to avoid
10206 // multiplication by 1.
10207 if (Cnt + 1 < NestedLoopCount)
10208 Iter =
10209 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10210 else
10211 Iter = Acc;
10212 if (!Iter.isUsable()) {
10213 HasErrors = true;
10214 break;
10215 }
10216
10217 // Update Acc:
10218 // Acc -= Iter * Prod
10219 // Check if there is at least one more inner loop to avoid
10220 // multiplication by 1.
10221 if (Cnt + 1 < NestedLoopCount)
10222 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10223 Prod.get());
10224 else
10225 Prod = Iter;
10226 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10227
10228 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10229 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10230 DeclRefExpr *CounterVar = buildDeclRefExpr(
10231 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10232 /*RefersToCapture=*/true);
10234 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10235 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10236 if (!Init.isUsable()) {
10237 HasErrors = true;
10238 break;
10239 }
10241 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10242 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10243 if (!Update.isUsable()) {
10244 HasErrors = true;
10245 break;
10246 }
10247
10248 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10249 ExprResult Final =
10250 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10251 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10252 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10253 if (!Final.isUsable()) {
10254 HasErrors = true;
10255 break;
10256 }
10257
10258 if (!Update.isUsable() || !Final.isUsable()) {
10259 HasErrors = true;
10260 break;
10261 }
10262 // Save results
10263 Built.Counters[Cnt] = IS.CounterVar;
10264 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10265 Built.Inits[Cnt] = Init.get();
10266 Built.Updates[Cnt] = Update.get();
10267 Built.Finals[Cnt] = Final.get();
10268 Built.DependentCounters[Cnt] = nullptr;
10269 Built.DependentInits[Cnt] = nullptr;
10270 Built.FinalsConditions[Cnt] = nullptr;
10271 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10272 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10273 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10274 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10275 }
10276 }
10277 }
10278
10279 if (HasErrors)
10280 return 0;
10281
10282 // Save results
10283 Built.IterationVarRef = IV.get();
10284 Built.LastIteration = LastIteration.get();
10285 Built.NumIterations = NumIterations.get();
10286 Built.CalcLastIteration = SemaRef
10287 .ActOnFinishFullExpr(CalcLastIteration.get(),
10288 /*DiscardedValue=*/false)
10289 .get();
10290 Built.PreCond = PreCond.get();
10291 Built.PreInits = buildPreInits(C, Captures);
10292 Built.Cond = Cond.get();
10293 Built.Init = Init.get();
10294 Built.Inc = Inc.get();
10295 Built.LB = LB.get();
10296 Built.UB = UB.get();
10297 Built.IL = IL.get();
10298 Built.ST = ST.get();
10299 Built.EUB = EUB.get();
10300 Built.NLB = NextLB.get();
10301 Built.NUB = NextUB.get();
10302 Built.PrevLB = PrevLB.get();
10303 Built.PrevUB = PrevUB.get();
10304 Built.DistInc = DistInc.get();
10305 Built.PrevEUB = PrevEUB.get();
10306 Built.DistCombinedFields.LB = CombLB.get();
10307 Built.DistCombinedFields.UB = CombUB.get();
10308 Built.DistCombinedFields.EUB = CombEUB.get();
10309 Built.DistCombinedFields.Init = CombInit.get();
10310 Built.DistCombinedFields.Cond = CombCond.get();
10311 Built.DistCombinedFields.NLB = CombNextLB.get();
10312 Built.DistCombinedFields.NUB = CombNextUB.get();
10313 Built.DistCombinedFields.DistCond = CombDistCond.get();
10314 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10315
10316 return NestedLoopCount;
10317}
10318
10320 auto CollapseClauses =
10321 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10322 if (CollapseClauses.begin() != CollapseClauses.end())
10323 return (*CollapseClauses.begin())->getNumForLoops();
10324 return nullptr;
10325}
10326
10328 auto OrderedClauses =
10329 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10330 if (OrderedClauses.begin() != OrderedClauses.end())
10331 return (*OrderedClauses.begin())->getNumForLoops();
10332 return nullptr;
10333}
10334
10336 const ArrayRef<OMPClause *> Clauses) {
10337 const OMPSafelenClause *Safelen = nullptr;
10338 const OMPSimdlenClause *Simdlen = nullptr;
10339
10340 for (const OMPClause *Clause : Clauses) {
10341 if (Clause->getClauseKind() == OMPC_safelen)
10342 Safelen = cast<OMPSafelenClause>(Clause);
10343 else if (Clause->getClauseKind() == OMPC_simdlen)
10344 Simdlen = cast<OMPSimdlenClause>(Clause);
10345 if (Safelen && Simdlen)
10346 break;
10347 }
10348
10349 if (Simdlen && Safelen) {
10350 const Expr *SimdlenLength = Simdlen->getSimdlen();
10351 const Expr *SafelenLength = Safelen->getSafelen();
10352 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10353 SimdlenLength->isInstantiationDependent() ||
10354 SimdlenLength->containsUnexpandedParameterPack())
10355 return false;
10356 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10357 SafelenLength->isInstantiationDependent() ||
10358 SafelenLength->containsUnexpandedParameterPack())
10359 return false;
10360 Expr::EvalResult SimdlenResult, SafelenResult;
10361 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10362 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10363 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10364 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10365 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10366 // If both simdlen and safelen clauses are specified, the value of the
10367 // simdlen parameter must be less than or equal to the value of the safelen
10368 // parameter.
10369 if (SimdlenRes > SafelenRes) {
10370 S.Diag(SimdlenLength->getExprLoc(),
10371 diag::err_omp_wrong_simdlen_safelen_values)
10372 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10373 return true;
10374 }
10375 }
10376 return false;
10377}
10378
10380 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10381 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10382 if (!AStmt)
10383 return StmtError();
10384
10385 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_simd, AStmt);
10386
10387 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10389 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10390 // define the nested loops number.
10391 unsigned NestedLoopCount = checkOpenMPLoop(
10392 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10393 CS, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10394 if (NestedLoopCount == 0)
10395 return StmtError();
10396
10397 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10398 return StmtError();
10399
10401 return StmtError();
10402
10403 auto *SimdDirective = OMPSimdDirective::Create(
10404 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10405 return SimdDirective;
10406}
10407
10409 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10410 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10411 if (!AStmt)
10412 return StmtError();
10413
10414 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10416 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10417 // define the nested loops number.
10418 unsigned NestedLoopCount = checkOpenMPLoop(
10419 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10420 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10421 if (NestedLoopCount == 0)
10422 return StmtError();
10423
10424 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10425 return StmtError();
10426
10427 auto *ForDirective = OMPForDirective::Create(
10428 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10429 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10430 return ForDirective;
10431}
10432
10434 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10435 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10436 if (!AStmt)
10437 return StmtError();
10438
10439 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_for_simd, AStmt);
10440
10441 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10443 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10444 // define the nested loops number.
10445 unsigned NestedLoopCount =
10446 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10447 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10448 VarsWithImplicitDSA, B);
10449 if (NestedLoopCount == 0)
10450 return StmtError();
10451
10452 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10453 return StmtError();
10454
10456 return StmtError();
10457
10458 return OMPForSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
10459 NestedLoopCount, Clauses, AStmt, B);
10460}
10461
10463 Stmt *AStmt, DSAStackTy *Stack) {
10464 if (!AStmt)
10465 return true;
10466
10467 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10468 auto BaseStmt = AStmt;
10469 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10470 BaseStmt = CS->getCapturedStmt();
10471 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10472 auto S = C->children();
10473 if (S.begin() == S.end())
10474 return true;
10475 // All associated statements must be '#pragma omp section' except for
10476 // the first one.
10477 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10478 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10479 if (SectionStmt)
10480 SemaRef.Diag(SectionStmt->getBeginLoc(),
10481 diag::err_omp_sections_substmt_not_section)
10482 << getOpenMPDirectiveName(DKind);
10483 return true;
10484 }
10485 cast<OMPSectionDirective>(SectionStmt)
10486 ->setHasCancel(Stack->isCancelRegion());
10487 }
10488 } else {
10489 SemaRef.Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10490 << getOpenMPDirectiveName(DKind);
10491 return true;
10492 }
10493 return false;
10494}
10495
10498 Stmt *AStmt, SourceLocation StartLoc,
10499 SourceLocation EndLoc) {
10500 if (checkSectionsDirective(SemaRef, OMPD_sections, AStmt, DSAStack))
10501 return StmtError();
10502
10504
10506 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10507 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10508}
10509
10511 SourceLocation StartLoc,
10512 SourceLocation EndLoc) {
10513 if (!AStmt)
10514 return StmtError();
10515
10517 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10518
10519 return OMPSectionDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt,
10520 DSAStack->isCancelRegion());
10521}
10522
10525 if (auto *CE = dyn_cast<CallExpr>(E))
10526 if (CE->getDirectCallee())
10527 return E;
10528 return nullptr;
10529}
10530
10533 Stmt *AStmt, SourceLocation StartLoc,
10534 SourceLocation EndLoc) {
10535 if (!AStmt)
10536 return StmtError();
10537
10538 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10539
10540 // 5.1 OpenMP
10541 // expression-stmt : an expression statement with one of the following forms:
10542 // expression = target-call ( [expression-list] );
10543 // target-call ( [expression-list] );
10544
10545 SourceLocation TargetCallLoc;
10546
10548 Expr *TargetCall = nullptr;
10549
10550 auto *E = dyn_cast<Expr>(S);
10551 if (!E) {
10552 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10553 return StmtError();
10554 }
10555
10557
10558 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10559 if (BO->getOpcode() == BO_Assign)
10560 TargetCall = getDirectCallExpr(BO->getRHS());
10561 } else {
10562 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10563 if (COCE->getOperator() == OO_Equal)
10564 TargetCall = getDirectCallExpr(COCE->getArg(1));
10565 if (!TargetCall)
10566 TargetCall = getDirectCallExpr(E);
10567 }
10568 if (!TargetCall) {
10569 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10570 return StmtError();
10571 }
10572 TargetCallLoc = TargetCall->getExprLoc();
10573 }
10574
10576
10577 return OMPDispatchDirective::Create(getASTContext(), StartLoc, EndLoc,
10578 Clauses, AStmt, TargetCallLoc);
10579}
10580
10583 DSAStackTy *Stack) {
10584 bool ErrorFound = false;
10585 for (OMPClause *C : Clauses) {
10586 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10587 for (Expr *RefExpr : LPC->varlist()) {
10588 SourceLocation ELoc;
10589 SourceRange ERange;
10590 Expr *SimpleRefExpr = RefExpr;
10591 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10592 if (ValueDecl *D = Res.first) {
10593 auto &&Info = Stack->isLoopControlVariable(D);
10594 if (!Info.first) {
10595 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10596 << getOpenMPDirectiveName(K);
10597 ErrorFound = true;
10598 }
10599 }
10600 }
10601 }
10602 }
10603 return ErrorFound;
10604}
10605
10607 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10608 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10609 if (!AStmt)
10610 return StmtError();
10611
10612 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10613 // A list item may not appear in a lastprivate clause unless it is the
10614 // loop iteration variable of a loop that is associated with the construct.
10615 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack))
10616 return StmtError();
10617
10618 setBranchProtectedScope(SemaRef, OMPD_loop, AStmt);
10619
10621 // In presence of clause 'collapse', it will define the nested loops number.
10622 unsigned NestedLoopCount = checkOpenMPLoop(
10623 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10624 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10625 if (NestedLoopCount == 0)
10626 return StmtError();
10627
10628 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10629 "omp loop exprs were not built");
10630
10631 return OMPGenericLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
10632 NestedLoopCount, Clauses, AStmt, B);
10633}
10634
10636 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10637 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10638 if (!AStmt)
10639 return StmtError();
10640
10641 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10642 // A list item may not appear in a lastprivate clause unless it is the
10643 // loop iteration variable of a loop that is associated with the construct.
10644 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack))
10645 return StmtError();
10646
10647 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_teams_loop, AStmt);
10648
10650 // In presence of clause 'collapse', it will define the nested loops number.
10651 unsigned NestedLoopCount =
10652 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10653 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10654 VarsWithImplicitDSA, B);
10655 if (NestedLoopCount == 0)
10656 return StmtError();
10657
10658 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10659 "omp loop exprs were not built");
10660
10661 DSAStack->setParentTeamsRegionLoc(StartLoc);
10662
10664 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10665}
10666
10668 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10669 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10670 if (!AStmt)
10671 return StmtError();
10672
10673 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10674 // A list item may not appear in a lastprivate clause unless it is the
10675 // loop iteration variable of a loop that is associated with the construct.
10676 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop,
10677 DSAStack))
10678 return StmtError();
10679
10680 CapturedStmt *CS =
10681 setBranchProtectedScope(SemaRef, OMPD_target_teams_loop, AStmt);
10682
10684 // In presence of clause 'collapse', it will define the nested loops number.
10685 unsigned NestedLoopCount =
10686 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10687 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10688 VarsWithImplicitDSA, B);
10689 if (NestedLoopCount == 0)
10690 return StmtError();
10691
10692 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10693 "omp loop exprs were not built");
10694
10696 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10698}
10699
10701 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10702 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10703 if (!AStmt)
10704 return StmtError();
10705
10706 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10707 // A list item may not appear in a lastprivate clause unless it is the
10708 // loop iteration variable of a loop that is associated with the construct.
10709 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_parallel_loop,
10710 DSAStack))
10711 return StmtError();
10712
10713 CapturedStmt *CS =
10714 setBranchProtectedScope(SemaRef, OMPD_parallel_loop, AStmt);
10715
10717 // In presence of clause 'collapse', it will define the nested loops number.
10718 unsigned NestedLoopCount =
10719 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
10720 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10721 VarsWithImplicitDSA, B);
10722 if (NestedLoopCount == 0)
10723 return StmtError();
10724
10725 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10726 "omp loop exprs were not built");
10727
10729 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10730}
10731
10733 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10734 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10735 if (!AStmt)
10736 return StmtError();
10737
10738 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10739 // A list item may not appear in a lastprivate clause unless it is the
10740 // loop iteration variable of a loop that is associated with the construct.
10741 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_parallel_loop,
10742 DSAStack))
10743 return StmtError();
10744
10745 CapturedStmt *CS =
10746 setBranchProtectedScope(SemaRef, OMPD_target_parallel_loop, AStmt);
10747
10749 // In presence of clause 'collapse', it will define the nested loops number.
10750 unsigned NestedLoopCount =
10751 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
10752 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10753 VarsWithImplicitDSA, B);
10754 if (NestedLoopCount == 0)
10755 return StmtError();
10756
10757 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10758 "omp loop exprs were not built");
10759
10761 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10762}
10763
10765 Stmt *AStmt,
10766 SourceLocation StartLoc,
10767 SourceLocation EndLoc) {
10768 if (!AStmt)
10769 return StmtError();
10770
10771 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10772
10774
10775 // OpenMP [2.7.3, single Construct, Restrictions]
10776 // The copyprivate clause must not be used with the nowait clause.
10777 const OMPClause *Nowait = nullptr;
10778 const OMPClause *Copyprivate = nullptr;
10779 for (const OMPClause *Clause : Clauses) {
10780 if (Clause->getClauseKind() == OMPC_nowait)
10781 Nowait = Clause;
10782 else if (Clause->getClauseKind() == OMPC_copyprivate)
10783 Copyprivate = Clause;
10784 if (Copyprivate && Nowait) {
10785 Diag(Copyprivate->getBeginLoc(),
10786 diag::err_omp_single_copyprivate_with_nowait);
10787 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
10788 return StmtError();
10789 }
10790 }
10791
10792 return OMPSingleDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
10793 AStmt);
10794}
10795
10797 SourceLocation StartLoc,
10798 SourceLocation EndLoc) {
10799 if (!AStmt)
10800 return StmtError();
10801
10803
10804 return OMPMasterDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt);
10805}
10806
10808 Stmt *AStmt,
10809 SourceLocation StartLoc,
10810 SourceLocation EndLoc) {
10811 if (!AStmt)
10812 return StmtError();
10813
10815
10816 return OMPMaskedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
10817 AStmt);
10818}
10819
10821 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
10822 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
10823 if (!AStmt)
10824 return StmtError();
10825
10826 bool ErrorFound = false;
10827 llvm::APSInt Hint;
10828 SourceLocation HintLoc;
10829 bool DependentHint = false;
10830 for (const OMPClause *C : Clauses) {
10831 if (C->getClauseKind() == OMPC_hint) {
10832 if (!DirName.getName()) {
10833 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
10834 ErrorFound = true;
10835 }
10836 Expr *E = cast<OMPHintClause>(C)->getHint();
10837 if (E->isTypeDependent() || E->isValueDependent() ||
10839 DependentHint = true;
10840 } else {
10842 HintLoc = C->getBeginLoc();
10843 }
10844 }
10845 }
10846 if (ErrorFound)
10847 return StmtError();
10848 const auto Pair = DSAStack->getCriticalWithHint(DirName);
10849 if (Pair.first && DirName.getName() && !DependentHint) {
10850 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
10851 Diag(StartLoc, diag::err_omp_critical_with_hint);
10852 if (HintLoc.isValid())
10853 Diag(HintLoc, diag::note_omp_critical_hint_here)
10854 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
10855 else
10856 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
10857 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
10858 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
10859 << 1
10860 << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()),
10861 /*Radix=*/10, /*Signed=*/false);
10862 } else {
10863 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
10864 }
10865 }
10866 }
10867
10869
10870 auto *Dir = OMPCriticalDirective::Create(getASTContext(), DirName, StartLoc,
10871 EndLoc, Clauses, AStmt);
10872 if (!Pair.first && DirName.getName() && !DependentHint)
10873 DSAStack->addCriticalWithHint(Dir, Hint);
10874 return Dir;
10875}
10876
10878 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10879 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10880 if (!AStmt)
10881 return StmtError();
10882
10883 setBranchProtectedScope(SemaRef, OMPD_parallel_for, AStmt);
10884
10886 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10887 // define the nested loops number.
10888 unsigned NestedLoopCount =
10889 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
10890 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
10891 VarsWithImplicitDSA, B);
10892 if (NestedLoopCount == 0)
10893 return StmtError();
10894
10895 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10896 return StmtError();
10897
10899 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10900 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10901}
10902
10904 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10905 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10906 if (!AStmt)
10907 return StmtError();
10908
10909 CapturedStmt *CS =
10910 setBranchProtectedScope(SemaRef, OMPD_parallel_for_simd, AStmt);
10911
10913 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10914 // define the nested loops number.
10915 unsigned NestedLoopCount =
10916 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
10917 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10918 VarsWithImplicitDSA, B);
10919 if (NestedLoopCount == 0)
10920 return StmtError();
10921
10922 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10923 return StmtError();
10924
10926 return StmtError();
10927
10929 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10930}
10931
10933 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10934 SourceLocation EndLoc) {
10935 if (!AStmt)
10936 return StmtError();
10937
10938 setBranchProtectedScope(SemaRef, OMPD_parallel_master, AStmt);
10939
10941 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10942 DSAStack->getTaskgroupReductionRef());
10943}
10944
10946 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10947 SourceLocation EndLoc) {
10948 if (!AStmt)
10949 return StmtError();
10950
10951 setBranchProtectedScope(SemaRef, OMPD_parallel_masked, AStmt);
10952
10954 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10955 DSAStack->getTaskgroupReductionRef());
10956}
10957
10959 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10960 SourceLocation EndLoc) {
10961 if (checkSectionsDirective(SemaRef, OMPD_parallel_sections, AStmt, DSAStack))
10962 return StmtError();
10963
10965
10967 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10968 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10969}
10970
10971/// Find and diagnose mutually exclusive clause kinds.
10973 Sema &S, ArrayRef<OMPClause *> Clauses,
10974 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
10975 const OMPClause *PrevClause = nullptr;
10976 bool ErrorFound = false;
10977 for (const OMPClause *C : Clauses) {
10978 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
10979 if (!PrevClause) {
10980 PrevClause = C;
10981 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
10982 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
10983 << getOpenMPClauseName(C->getClauseKind())
10984 << getOpenMPClauseName(PrevClause->getClauseKind());
10985 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
10986 << getOpenMPClauseName(PrevClause->getClauseKind());
10987 ErrorFound = true;
10988 }
10989 }
10990 }
10991 return ErrorFound;
10992}
10993
10995 Stmt *AStmt,
10996 SourceLocation StartLoc,
10997 SourceLocation EndLoc) {
10998 if (!AStmt)
10999 return StmtError();
11000
11001 // OpenMP 5.0, 2.10.1 task Construct
11002 // If a detach clause appears on the directive, then a mergeable clause cannot
11003 // appear on the same directive.
11005 {OMPC_detach, OMPC_mergeable}))
11006 return StmtError();
11007
11008 setBranchProtectedScope(SemaRef, OMPD_task, AStmt);
11009
11010 return OMPTaskDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11011 AStmt, DSAStack->isCancelRegion());
11012}
11013
11015 SourceLocation EndLoc) {
11016 return OMPTaskyieldDirective::Create(getASTContext(), StartLoc, EndLoc);
11017}
11018
11020 SourceLocation EndLoc) {
11021 return OMPBarrierDirective::Create(getASTContext(), StartLoc, EndLoc);
11022}
11023
11025 SourceLocation StartLoc,
11026 SourceLocation EndLoc,
11027 bool InExContext) {
11028 const OMPAtClause *AtC =
11029 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11030
11031 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11032 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11033 return StmtError();
11034 }
11035
11036 const OMPSeverityClause *SeverityC =
11037 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11038 const OMPMessageClause *MessageC =
11039 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11040 Expr *ME = MessageC ? MessageC->getMessageString() : nullptr;
11041
11042 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11043 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11044 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11045 << (ME ? cast<StringLiteral>(ME)->getString() : "WARNING");
11046 else
11047 Diag(StartLoc, diag::err_diagnose_if_succeeded)
11048 << (ME ? cast<StringLiteral>(ME)->getString() : "ERROR");
11049 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11050 return StmtError();
11051 }
11052 return OMPErrorDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11053}
11054
11057 SourceLocation StartLoc,
11058 SourceLocation EndLoc) {
11059 const OMPNowaitClause *NowaitC =
11060 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11061 bool HasDependC =
11062 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11063 .empty();
11064 if (NowaitC && !HasDependC) {
11065 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11066 return StmtError();
11067 }
11068
11069 return OMPTaskwaitDirective::Create(getASTContext(), StartLoc, EndLoc,
11070 Clauses);
11071}
11072
11075 Stmt *AStmt, SourceLocation StartLoc,
11076 SourceLocation EndLoc) {
11077 if (!AStmt)
11078 return StmtError();
11079
11080 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11081
11083
11084 return OMPTaskgroupDirective::Create(getASTContext(), StartLoc, EndLoc,
11085 Clauses, AStmt,
11086 DSAStack->getTaskgroupReductionRef());
11087}
11088
11090 SourceLocation StartLoc,
11091 SourceLocation EndLoc) {
11092 OMPFlushClause *FC = nullptr;
11093 OMPClause *OrderClause = nullptr;
11094 for (OMPClause *C : Clauses) {
11095 if (C->getClauseKind() == OMPC_flush)
11096 FC = cast<OMPFlushClause>(C);
11097 else
11098 OrderClause = C;
11099 }
11100 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11101 SourceLocation MemOrderLoc;
11102 for (const OMPClause *C : Clauses) {
11103 if (C->getClauseKind() == OMPC_acq_rel ||
11104 C->getClauseKind() == OMPC_acquire ||
11105 C->getClauseKind() == OMPC_release ||
11106 C->getClauseKind() == OMPC_seq_cst /*OpenMP 5.1*/) {
11107 if (MemOrderKind != OMPC_unknown) {
11108 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11109 << getOpenMPDirectiveName(OMPD_flush) << 1
11110 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11111 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11112 << getOpenMPClauseName(MemOrderKind);
11113 } else {
11114 MemOrderKind = C->getClauseKind();
11115 MemOrderLoc = C->getBeginLoc();
11116 }
11117 }
11118 }
11119 if (FC && OrderClause) {
11120 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11121 << getOpenMPClauseName(OrderClause->getClauseKind());
11122 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11123 << getOpenMPClauseName(OrderClause->getClauseKind());
11124 return StmtError();
11125 }
11126 return OMPFlushDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11127}
11128
11130 SourceLocation StartLoc,
11131 SourceLocation EndLoc) {
11132 if (Clauses.empty()) {
11133 Diag(StartLoc, diag::err_omp_depobj_expected);
11134 return StmtError();
11135 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11136 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11137 return StmtError();
11138 }
11139 // Only depobj expression and another single clause is allowed.
11140 if (Clauses.size() > 2) {
11141 Diag(Clauses[2]->getBeginLoc(),
11142 diag::err_omp_depobj_single_clause_expected);
11143 return StmtError();
11144 } else if (Clauses.size() < 1) {
11145 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11146 return StmtError();
11147 }
11148 return OMPDepobjDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11149}
11150
11152 SourceLocation StartLoc,
11153 SourceLocation EndLoc) {
11154 // Check that exactly one clause is specified.
11155 if (Clauses.size() != 1) {
11156 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11157 diag::err_omp_scan_single_clause_expected);
11158 return StmtError();
11159 }
11160 // Check that scan directive is used in the scope of the OpenMP loop body.
11161 if (Scope *S = DSAStack->getCurScope()) {
11162 Scope *ParentS = S->getParent();
11163 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11164 !ParentS->getBreakParent()->isOpenMPLoopScope())
11165 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11166 << getOpenMPDirectiveName(OMPD_scan) << 5);
11167 }
11168 // Check that only one instance of scan directives is used in the same outer
11169 // region.
11170 if (DSAStack->doesParentHasScanDirective()) {
11171 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11172 Diag(DSAStack->getParentScanDirectiveLoc(),
11173 diag::note_omp_previous_directive)
11174 << "scan";
11175 return StmtError();
11176 }
11177 DSAStack->setParentHasScanDirective(StartLoc);
11178 return OMPScanDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11179}
11180
11183 Stmt *AStmt, SourceLocation StartLoc,
11184 SourceLocation EndLoc) {
11185 const OMPClause *DependFound = nullptr;
11186 const OMPClause *DependSourceClause = nullptr;
11187 const OMPClause *DependSinkClause = nullptr;
11188 const OMPClause *DoacrossFound = nullptr;
11189 const OMPClause *DoacrossSourceClause = nullptr;
11190 const OMPClause *DoacrossSinkClause = nullptr;
11191 bool ErrorFound = false;
11192 const OMPThreadsClause *TC = nullptr;
11193 const OMPSIMDClause *SC = nullptr;
11194 for (const OMPClause *C : Clauses) {
11195 auto DOC = dyn_cast<OMPDoacrossClause>(C);
11196 auto DC = dyn_cast<OMPDependClause>(C);
11197 if (DC || DOC) {
11198 DependFound = DC ? C : nullptr;
11199 DoacrossFound = DOC ? C : nullptr;
11200 OMPDoacrossKind ODK;
11201 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11202 (DOC && (ODK.isSource(DOC)))) {
11203 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11204 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11205 << getOpenMPDirectiveName(OMPD_ordered)
11206 << getOpenMPClauseName(DC ? OMPC_depend : OMPC_doacross) << 2;
11207 ErrorFound = true;
11208 } else {
11209 if (DC)
11210 DependSourceClause = C;
11211 else
11212 DoacrossSourceClause = C;
11213 }
11214 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11215 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11216 << (DC ? "depend" : "doacross") << 0;
11217 ErrorFound = true;
11218 }
11219 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11220 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11221 if (DependSourceClause || DoacrossSourceClause) {
11222 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11223 << (DC ? "depend" : "doacross") << 1;
11224 ErrorFound = true;
11225 }
11226 if (DC)
11227 DependSinkClause = C;
11228 else
11229 DoacrossSinkClause = C;
11230 }
11231 } else if (C->getClauseKind() == OMPC_threads) {
11232 TC = cast<OMPThreadsClause>(C);
11233 } else if (C->getClauseKind() == OMPC_simd) {
11234 SC = cast<OMPSIMDClause>(C);
11235 }
11236 }
11237 if (!ErrorFound && !SC &&
11238 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11239 // OpenMP [2.8.1,simd Construct, Restrictions]
11240 // An ordered construct with the simd clause is the only OpenMP construct
11241 // that can appear in the simd region.
11242 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11243 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11244 ErrorFound = true;
11245 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11247 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11248 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11249 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross)
11250 << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
11251 ErrorFound = true;
11252 } else if ((DependFound || DoacrossFound) &&
11253 !DSAStack->getParentOrderedRegionParam().first) {
11255 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11256 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11257 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross);
11258 ErrorFound = true;
11259 } else if (TC || Clauses.empty()) {
11260 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11261 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11262 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11263 << (TC != nullptr);
11264 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11265 ErrorFound = true;
11266 }
11267 }
11268 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11269 return StmtError();
11270
11271 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11272 // During execution of an iteration of a worksharing-loop or a loop nest
11273 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11274 // must not execute more than one ordered region corresponding to an ordered
11275 // construct without a depend clause.
11276 if (!DependFound && !DoacrossFound) {
11277 if (DSAStack->doesParentHasOrderedDirective()) {
11278 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11279 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11280 diag::note_omp_previous_directive)
11281 << "ordered";
11282 return StmtError();
11283 }
11284 DSAStack->setParentHasOrderedDirective(StartLoc);
11285 }
11286
11287 if (AStmt) {
11288 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11289
11291 }
11292
11293 return OMPOrderedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11294 AStmt);
11295}
11296
11297namespace {
11298/// Helper class for checking expression in 'omp atomic [update]'
11299/// construct.
11300class OpenMPAtomicUpdateChecker {
11301 /// Error results for atomic update expressions.
11302 enum ExprAnalysisErrorCode {
11303 /// A statement is not an expression statement.
11304 NotAnExpression,
11305 /// Expression is not builtin binary or unary operation.
11306 NotABinaryOrUnaryExpression,
11307 /// Unary operation is not post-/pre- increment/decrement operation.
11308 NotAnUnaryIncDecExpression,
11309 /// An expression is not of scalar type.
11310 NotAScalarType,
11311 /// A binary operation is not an assignment operation.
11312 NotAnAssignmentOp,
11313 /// RHS part of the binary operation is not a binary expression.
11314 NotABinaryExpression,
11315 /// RHS part is not additive/multiplicative/shift/bitwise binary
11316 /// expression.
11317 NotABinaryOperator,
11318 /// RHS binary operation does not have reference to the updated LHS
11319 /// part.
11320 NotAnUpdateExpression,
11321 /// An expression contains semantical error not related to
11322 /// 'omp atomic [update]'
11323 NotAValidExpression,
11324 /// No errors is found.
11325 NoError
11326 };
11327 /// Reference to Sema.
11328 Sema &SemaRef;
11329 /// A location for note diagnostics (when error is found).
11330 SourceLocation NoteLoc;
11331 /// 'x' lvalue part of the source atomic expression.
11332 Expr *X;
11333 /// 'expr' rvalue part of the source atomic expression.
11334 Expr *E;
11335 /// Helper expression of the form
11336 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11337 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11338 Expr *UpdateExpr;
11339 /// Is 'x' a LHS in a RHS part of full update expression. It is
11340 /// important for non-associative operations.
11341 bool IsXLHSInRHSPart;
11343 SourceLocation OpLoc;
11344 /// true if the source expression is a postfix unary operation, false
11345 /// if it is a prefix unary operation.
11346 bool IsPostfixUpdate;
11347
11348public:
11349 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11350 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11351 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11352 /// Check specified statement that it is suitable for 'atomic update'
11353 /// constructs and extract 'x', 'expr' and Operation from the original
11354 /// expression. If DiagId and NoteId == 0, then only check is performed
11355 /// without error notification.
11356 /// \param DiagId Diagnostic which should be emitted if error is found.
11357 /// \param NoteId Diagnostic note for the main error message.
11358 /// \return true if statement is not an update expression, false otherwise.
11359 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11360 /// Return the 'x' lvalue part of the source atomic expression.
11361 Expr *getX() const { return X; }
11362 /// Return the 'expr' rvalue part of the source atomic expression.
11363 Expr *getExpr() const { return E; }
11364 /// Return the update expression used in calculation of the updated
11365 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11366 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11367 Expr *getUpdateExpr() const { return UpdateExpr; }
11368 /// Return true if 'x' is LHS in RHS part of full update expression,
11369 /// false otherwise.
11370 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11371
11372 /// true if the source expression is a postfix unary operation, false
11373 /// if it is a prefix unary operation.
11374 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11375
11376private:
11377 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11378 unsigned NoteId = 0);
11379};
11380
11381bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11382 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11383 ExprAnalysisErrorCode ErrorFound = NoError;
11384 SourceLocation ErrorLoc, NoteLoc;
11385 SourceRange ErrorRange, NoteRange;
11386 // Allowed constructs are:
11387 // x = x binop expr;
11388 // x = expr binop x;
11389 if (AtomicBinOp->getOpcode() == BO_Assign) {
11390 X = AtomicBinOp->getLHS();
11391 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11392 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11393 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11394 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11395 AtomicInnerBinOp->isBitwiseOp()) {
11396 Op = AtomicInnerBinOp->getOpcode();
11397 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11398 Expr *LHS = AtomicInnerBinOp->getLHS();
11399 Expr *RHS = AtomicInnerBinOp->getRHS();
11400 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11401 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11402 /*Canonical=*/true);
11403 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11404 /*Canonical=*/true);
11405 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11406 /*Canonical=*/true);
11407 if (XId == LHSId) {
11408 E = RHS;
11409 IsXLHSInRHSPart = true;
11410 } else if (XId == RHSId) {
11411 E = LHS;
11412 IsXLHSInRHSPart = false;
11413 } else {
11414 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11415 ErrorRange = AtomicInnerBinOp->getSourceRange();
11416 NoteLoc = X->getExprLoc();
11417 NoteRange = X->getSourceRange();
11418 ErrorFound = NotAnUpdateExpression;
11419 }
11420 } else {
11421 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11422 ErrorRange = AtomicInnerBinOp->getSourceRange();
11423 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11424 NoteRange = SourceRange(NoteLoc, NoteLoc);
11425 ErrorFound = NotABinaryOperator;
11426 }
11427 } else {
11428 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11429 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11430 ErrorFound = NotABinaryExpression;
11431 }
11432 } else {
11433 ErrorLoc = AtomicBinOp->getExprLoc();
11434 ErrorRange = AtomicBinOp->getSourceRange();
11435 NoteLoc = AtomicBinOp->getOperatorLoc();
11436 NoteRange = SourceRange(NoteLoc, NoteLoc);
11437 ErrorFound = NotAnAssignmentOp;
11438 }
11439 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11440 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11441 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11442 return true;
11443 }
11444 if (SemaRef.CurContext->isDependentContext())
11445 E = X = UpdateExpr = nullptr;
11446 return ErrorFound != NoError;
11447}
11448
11449bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11450 unsigned NoteId) {
11451 ExprAnalysisErrorCode ErrorFound = NoError;
11452 SourceLocation ErrorLoc, NoteLoc;
11453 SourceRange ErrorRange, NoteRange;
11454 // Allowed constructs are:
11455 // x++;
11456 // x--;
11457 // ++x;
11458 // --x;
11459 // x binop= expr;
11460 // x = x binop expr;
11461 // x = expr binop x;
11462 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11463 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11464 if (AtomicBody->getType()->isScalarType() ||
11465 AtomicBody->isInstantiationDependent()) {
11466 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11467 AtomicBody->IgnoreParenImpCasts())) {
11468 // Check for Compound Assignment Operation
11470 AtomicCompAssignOp->getOpcode());
11471 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11472 E = AtomicCompAssignOp->getRHS();
11473 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11474 IsXLHSInRHSPart = true;
11475 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11476 AtomicBody->IgnoreParenImpCasts())) {
11477 // Check for Binary Operation
11478 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11479 return true;
11480 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11481 AtomicBody->IgnoreParenImpCasts())) {
11482 // Check for Unary Operation
11483 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11484 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11485 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11486 OpLoc = AtomicUnaryOp->getOperatorLoc();
11487 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11488 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11489 IsXLHSInRHSPart = true;
11490 } else {
11491 ErrorFound = NotAnUnaryIncDecExpression;
11492 ErrorLoc = AtomicUnaryOp->getExprLoc();
11493 ErrorRange = AtomicUnaryOp->getSourceRange();
11494 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11495 NoteRange = SourceRange(NoteLoc, NoteLoc);
11496 }
11497 } else if (!AtomicBody->isInstantiationDependent()) {
11498 ErrorFound = NotABinaryOrUnaryExpression;
11499 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11500 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11501 } else if (AtomicBody->containsErrors()) {
11502 ErrorFound = NotAValidExpression;
11503 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11504 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11505 }
11506 } else {
11507 ErrorFound = NotAScalarType;
11508 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11509 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11510 }
11511 } else {
11512 ErrorFound = NotAnExpression;
11513 NoteLoc = ErrorLoc = S->getBeginLoc();
11514 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11515 }
11516 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11517 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11518 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11519 return true;
11520 }
11521 if (SemaRef.CurContext->isDependentContext())
11522 E = X = UpdateExpr = nullptr;
11523 if (ErrorFound == NoError && E && X) {
11524 // Build an update expression of form 'OpaqueValueExpr(x) binop
11525 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11526 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11527 auto *OVEX = new (SemaRef.getASTContext())
11528 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11529 auto *OVEExpr = new (SemaRef.getASTContext())
11532 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11533 IsXLHSInRHSPart ? OVEExpr : OVEX);
11534 if (Update.isInvalid())
11535 return true;
11536 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11538 if (Update.isInvalid())
11539 return true;
11540 UpdateExpr = Update.get();
11541 }
11542 return ErrorFound != NoError;
11543}
11544
11545/// Get the node id of the fixed point of an expression \a S.
11546llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11547 llvm::FoldingSetNodeID Id;
11548 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11549 return Id;
11550}
11551
11552/// Check if two expressions are same.
11553bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11554 const Expr *RHS) {
11555 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11556}
11557
11558class OpenMPAtomicCompareChecker {
11559public:
11560 /// All kinds of errors that can occur in `atomic compare`
11561 enum ErrorTy {
11562 /// Empty compound statement.
11563 NoStmt = 0,
11564 /// More than one statement in a compound statement.
11565 MoreThanOneStmt,
11566 /// Not an assignment binary operator.
11567 NotAnAssignment,
11568 /// Not a conditional operator.
11569 NotCondOp,
11570 /// Wrong false expr. According to the spec, 'x' should be at the false
11571 /// expression of a conditional expression.
11572 WrongFalseExpr,
11573 /// The condition of a conditional expression is not a binary operator.
11574 NotABinaryOp,
11575 /// Invalid binary operator (not <, >, or ==).
11576 InvalidBinaryOp,
11577 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11578 InvalidComparison,
11579 /// X is not a lvalue.
11580 XNotLValue,
11581 /// Not a scalar.
11582 NotScalar,
11583 /// Not an integer.
11584 NotInteger,
11585 /// 'else' statement is not expected.
11586 UnexpectedElse,
11587 /// Not an equality operator.
11588 NotEQ,
11589 /// Invalid assignment (not v == x).
11590 InvalidAssignment,
11591 /// Not if statement
11592 NotIfStmt,
11593 /// More than two statements in a compound statement.
11594 MoreThanTwoStmts,
11595 /// Not a compound statement.
11596 NotCompoundStmt,
11597 /// No else statement.
11598 NoElse,
11599 /// Not 'if (r)'.
11600 InvalidCondition,
11601 /// No error.
11602 NoError,
11603 };
11604
11605 struct ErrorInfoTy {
11606 ErrorTy Error;
11607 SourceLocation ErrorLoc;
11608 SourceRange ErrorRange;
11609 SourceLocation NoteLoc;
11610 SourceRange NoteRange;
11611 };
11612
11613 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11614
11615 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11616 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11617
11618 Expr *getX() const { return X; }
11619 Expr *getE() const { return E; }
11620 Expr *getD() const { return D; }
11621 Expr *getCond() const { return C; }
11622 bool isXBinopExpr() const { return IsXBinopExpr; }
11623
11624protected:
11625 /// Reference to ASTContext
11626 ASTContext &ContextRef;
11627 /// 'x' lvalue part of the source atomic expression.
11628 Expr *X = nullptr;
11629 /// 'expr' or 'e' rvalue part of the source atomic expression.
11630 Expr *E = nullptr;
11631 /// 'd' rvalue part of the source atomic expression.
11632 Expr *D = nullptr;
11633 /// 'cond' part of the source atomic expression. It is in one of the following
11634 /// forms:
11635 /// expr ordop x
11636 /// x ordop expr
11637 /// x == e
11638 /// e == x
11639 Expr *C = nullptr;
11640 /// True if the cond expr is in the form of 'x ordop expr'.
11641 bool IsXBinopExpr = true;
11642
11643 /// Check if it is a valid conditional update statement (cond-update-stmt).
11644 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11645
11646 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11647 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11648
11649 /// Check if all captured values have right type.
11650 bool checkType(ErrorInfoTy &ErrorInfo) const;
11651
11652 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11653 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11655 return true;
11656
11657 if (ShouldBeLValue && !E->isLValue()) {
11658 ErrorInfo.Error = ErrorTy::XNotLValue;
11659 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11660 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11661 return false;
11662 }
11663
11664 QualType QTy = E->getType();
11665 if (!QTy->isScalarType()) {
11666 ErrorInfo.Error = ErrorTy::NotScalar;
11667 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11668 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11669 return false;
11670 }
11671 if (ShouldBeInteger && !QTy->isIntegerType()) {
11672 ErrorInfo.Error = ErrorTy::NotInteger;
11673 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11674 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11675 return false;
11676 }
11677
11678 return true;
11679 }
11680};
11681
11682bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11683 ErrorInfoTy &ErrorInfo) {
11684 auto *Then = S->getThen();
11685 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11686 if (CS->body_empty()) {
11687 ErrorInfo.Error = ErrorTy::NoStmt;
11688 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11689 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11690 return false;
11691 }
11692 if (CS->size() > 1) {
11693 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11694 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11695 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11696 return false;
11697 }
11698 Then = CS->body_front();
11699 }
11700
11701 auto *BO = dyn_cast<BinaryOperator>(Then);
11702 if (!BO) {
11703 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11704 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11705 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11706 return false;
11707 }
11708 if (BO->getOpcode() != BO_Assign) {
11709 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11710 ErrorInfo.ErrorLoc = BO->getExprLoc();
11711 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11712 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11713 return false;
11714 }
11715
11716 X = BO->getLHS();
11717
11718 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11719 if (!Cond) {
11720 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11721 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11722 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11723 return false;
11724 }
11725
11726 switch (Cond->getOpcode()) {
11727 case BO_EQ: {
11728 C = Cond;
11729 D = BO->getRHS();
11730 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11731 E = Cond->getRHS();
11732 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11733 E = Cond->getLHS();
11734 } else {
11735 ErrorInfo.Error = ErrorTy::InvalidComparison;
11736 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11737 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11738 return false;
11739 }
11740 break;
11741 }
11742 case BO_LT:
11743 case BO_GT: {
11744 E = BO->getRHS();
11745 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
11746 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
11747 C = Cond;
11748 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
11749 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11750 C = Cond;
11751 IsXBinopExpr = false;
11752 } else {
11753 ErrorInfo.Error = ErrorTy::InvalidComparison;
11754 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11755 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11756 return false;
11757 }
11758 break;
11759 }
11760 default:
11761 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11762 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11763 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11764 return false;
11765 }
11766
11767 if (S->getElse()) {
11768 ErrorInfo.Error = ErrorTy::UnexpectedElse;
11769 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
11770 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
11771 return false;
11772 }
11773
11774 return true;
11775}
11776
11777bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
11778 ErrorInfoTy &ErrorInfo) {
11779 auto *BO = dyn_cast<BinaryOperator>(S);
11780 if (!BO) {
11781 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11782 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11783 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11784 return false;
11785 }
11786 if (BO->getOpcode() != BO_Assign) {
11787 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11788 ErrorInfo.ErrorLoc = BO->getExprLoc();
11789 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11790 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11791 return false;
11792 }
11793
11794 X = BO->getLHS();
11795
11796 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
11797 if (!CO) {
11798 ErrorInfo.Error = ErrorTy::NotCondOp;
11799 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
11800 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
11801 return false;
11802 }
11803
11804 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
11805 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
11806 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
11807 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11808 CO->getFalseExpr()->getSourceRange();
11809 return false;
11810 }
11811
11812 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
11813 if (!Cond) {
11814 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11815 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11816 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11817 CO->getCond()->getSourceRange();
11818 return false;
11819 }
11820
11821 switch (Cond->getOpcode()) {
11822 case BO_EQ: {
11823 C = Cond;
11824 D = CO->getTrueExpr();
11825 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11826 E = Cond->getRHS();
11827 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11828 E = Cond->getLHS();
11829 } else {
11830 ErrorInfo.Error = ErrorTy::InvalidComparison;
11831 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11832 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11833 return false;
11834 }
11835 break;
11836 }
11837 case BO_LT:
11838 case BO_GT: {
11839 E = CO->getTrueExpr();
11840 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
11841 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
11842 C = Cond;
11843 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
11844 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11845 C = Cond;
11846 IsXBinopExpr = false;
11847 } else {
11848 ErrorInfo.Error = ErrorTy::InvalidComparison;
11849 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11850 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11851 return false;
11852 }
11853 break;
11854 }
11855 default:
11856 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11857 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11858 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11859 return false;
11860 }
11861
11862 return true;
11863}
11864
11865bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
11866 // 'x' and 'e' cannot be nullptr
11867 assert(X && E && "X and E cannot be nullptr");
11868
11869 if (!CheckValue(X, ErrorInfo, true))
11870 return false;
11871
11872 if (!CheckValue(E, ErrorInfo, false))
11873 return false;
11874
11875 if (D && !CheckValue(D, ErrorInfo, false))
11876 return false;
11877
11878 return true;
11879}
11880
11881bool OpenMPAtomicCompareChecker::checkStmt(
11882 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
11883 auto *CS = dyn_cast<CompoundStmt>(S);
11884 if (CS) {
11885 if (CS->body_empty()) {
11886 ErrorInfo.Error = ErrorTy::NoStmt;
11887 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11888 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11889 return false;
11890 }
11891
11892 if (CS->size() != 1) {
11893 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11894 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11895 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11896 return false;
11897 }
11898 S = CS->body_front();
11899 }
11900
11901 auto Res = false;
11902
11903 if (auto *IS = dyn_cast<IfStmt>(S)) {
11904 // Check if the statement is in one of the following forms
11905 // (cond-update-stmt):
11906 // if (expr ordop x) { x = expr; }
11907 // if (x ordop expr) { x = expr; }
11908 // if (x == e) { x = d; }
11909 Res = checkCondUpdateStmt(IS, ErrorInfo);
11910 } else {
11911 // Check if the statement is in one of the following forms (cond-expr-stmt):
11912 // x = expr ordop x ? expr : x;
11913 // x = x ordop expr ? expr : x;
11914 // x = x == e ? d : x;
11915 Res = checkCondExprStmt(S, ErrorInfo);
11916 }
11917
11918 if (!Res)
11919 return false;
11920
11921 return checkType(ErrorInfo);
11922}
11923
11924class OpenMPAtomicCompareCaptureChecker final
11925 : public OpenMPAtomicCompareChecker {
11926public:
11927 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
11928
11929 Expr *getV() const { return V; }
11930 Expr *getR() const { return R; }
11931 bool isFailOnly() const { return IsFailOnly; }
11932 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11933
11934 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
11935 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11936
11937private:
11938 bool checkType(ErrorInfoTy &ErrorInfo);
11939
11940 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
11941 // form of 'conditional-update-capture-atomic' structured block on the v5.2
11942 // spec p.p. 82:
11943 // (1) { v = x; cond-update-stmt }
11944 // (2) { cond-update-stmt v = x; }
11945 // (3) if(x == e) { x = d; } else { v = x; }
11946 // (4) { r = x == e; if(r) { x = d; } }
11947 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
11948
11949 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
11950 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
11951
11952 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
11953 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
11954 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
11955
11956 /// 'v' lvalue part of the source atomic expression.
11957 Expr *V = nullptr;
11958 /// 'r' lvalue part of the source atomic expression.
11959 Expr *R = nullptr;
11960 /// If 'v' is only updated when the comparison fails.
11961 bool IsFailOnly = false;
11962 /// If original value of 'x' must be stored in 'v', not an updated one.
11963 bool IsPostfixUpdate = false;
11964};
11965
11966bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
11967 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
11968 return false;
11969
11970 if (V && !CheckValue(V, ErrorInfo, true))
11971 return false;
11972
11973 if (R && !CheckValue(R, ErrorInfo, true, true))
11974 return false;
11975
11976 return true;
11977}
11978
11979bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
11980 ErrorInfoTy &ErrorInfo) {
11981 IsFailOnly = true;
11982
11983 auto *Then = S->getThen();
11984 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11985 if (CS->body_empty()) {
11986 ErrorInfo.Error = ErrorTy::NoStmt;
11987 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11988 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11989 return false;
11990 }
11991 if (CS->size() > 1) {
11992 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11993 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11994 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11995 return false;
11996 }
11997 Then = CS->body_front();
11998 }
11999
12000 auto *BO = dyn_cast<BinaryOperator>(Then);
12001 if (!BO) {
12002 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12003 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12004 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12005 return false;
12006 }
12007 if (BO->getOpcode() != BO_Assign) {
12008 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12009 ErrorInfo.ErrorLoc = BO->getExprLoc();
12010 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12011 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12012 return false;
12013 }
12014
12015 X = BO->getLHS();
12016 D = BO->getRHS();
12017
12018 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12019 if (!Cond) {
12020 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12021 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12022 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12023 return false;
12024 }
12025 if (Cond->getOpcode() != BO_EQ) {
12026 ErrorInfo.Error = ErrorTy::NotEQ;
12027 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12028 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12029 return false;
12030 }
12031
12032 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12033 E = Cond->getRHS();
12034 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12035 E = Cond->getLHS();
12036 } else {
12037 ErrorInfo.Error = ErrorTy::InvalidComparison;
12038 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12039 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12040 return false;
12041 }
12042
12043 C = Cond;
12044
12045 if (!S->getElse()) {
12046 ErrorInfo.Error = ErrorTy::NoElse;
12047 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12048 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12049 return false;
12050 }
12051
12052 auto *Else = S->getElse();
12053 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12054 if (CS->body_empty()) {
12055 ErrorInfo.Error = ErrorTy::NoStmt;
12056 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12057 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12058 return false;
12059 }
12060 if (CS->size() > 1) {
12061 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12062 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12063 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12064 return false;
12065 }
12066 Else = CS->body_front();
12067 }
12068
12069 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12070 if (!ElseBO) {
12071 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12072 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12073 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12074 return false;
12075 }
12076 if (ElseBO->getOpcode() != BO_Assign) {
12077 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12078 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12079 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12080 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12081 return false;
12082 }
12083
12084 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12085 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12086 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12087 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12088 ElseBO->getRHS()->getSourceRange();
12089 return false;
12090 }
12091
12092 V = ElseBO->getLHS();
12093
12094 return checkType(ErrorInfo);
12095}
12096
12097bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12098 ErrorInfoTy &ErrorInfo) {
12099 // We don't check here as they should be already done before call this
12100 // function.
12101 auto *CS = cast<CompoundStmt>(S);
12102 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12103 auto *S1 = cast<BinaryOperator>(CS->body_front());
12104 auto *S2 = cast<IfStmt>(CS->body_back());
12105 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12106
12107 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12108 ErrorInfo.Error = ErrorTy::InvalidCondition;
12109 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12110 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12111 return false;
12112 }
12113
12114 R = S1->getLHS();
12115
12116 auto *Then = S2->getThen();
12117 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12118 if (ThenCS->body_empty()) {
12119 ErrorInfo.Error = ErrorTy::NoStmt;
12120 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12121 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12122 return false;
12123 }
12124 if (ThenCS->size() > 1) {
12125 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12126 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12127 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12128 return false;
12129 }
12130 Then = ThenCS->body_front();
12131 }
12132
12133 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12134 if (!ThenBO) {
12135 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12136 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12137 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12138 return false;
12139 }
12140 if (ThenBO->getOpcode() != BO_Assign) {
12141 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12142 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12143 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12144 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12145 return false;
12146 }
12147
12148 X = ThenBO->getLHS();
12149 D = ThenBO->getRHS();
12150
12151 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12152 if (BO->getOpcode() != BO_EQ) {
12153 ErrorInfo.Error = ErrorTy::NotEQ;
12154 ErrorInfo.ErrorLoc = BO->getExprLoc();
12155 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12156 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12157 return false;
12158 }
12159
12160 C = BO;
12161
12162 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12163 E = BO->getRHS();
12164 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12165 E = BO->getLHS();
12166 } else {
12167 ErrorInfo.Error = ErrorTy::InvalidComparison;
12168 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12169 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12170 return false;
12171 }
12172
12173 if (S2->getElse()) {
12174 IsFailOnly = true;
12175
12176 auto *Else = S2->getElse();
12177 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12178 if (ElseCS->body_empty()) {
12179 ErrorInfo.Error = ErrorTy::NoStmt;
12180 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12181 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12182 return false;
12183 }
12184 if (ElseCS->size() > 1) {
12185 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12186 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12187 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12188 return false;
12189 }
12190 Else = ElseCS->body_front();
12191 }
12192
12193 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12194 if (!ElseBO) {
12195 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12196 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12197 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12198 return false;
12199 }
12200 if (ElseBO->getOpcode() != BO_Assign) {
12201 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12202 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12203 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12204 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12205 return false;
12206 }
12207 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12208 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12209 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12210 ErrorInfo.NoteLoc = X->getExprLoc();
12211 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12212 ErrorInfo.NoteRange = X->getSourceRange();
12213 return false;
12214 }
12215
12216 V = ElseBO->getLHS();
12217 }
12218
12219 return checkType(ErrorInfo);
12220}
12221
12222bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12223 ErrorInfoTy &ErrorInfo) {
12224 // if(x == e) { x = d; } else { v = x; }
12225 if (auto *IS = dyn_cast<IfStmt>(S))
12226 return checkForm3(IS, ErrorInfo);
12227
12228 auto *CS = dyn_cast<CompoundStmt>(S);
12229 if (!CS) {
12230 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12231 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12232 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12233 return false;
12234 }
12235 if (CS->body_empty()) {
12236 ErrorInfo.Error = ErrorTy::NoStmt;
12237 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12238 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12239 return false;
12240 }
12241
12242 // { if(x == e) { x = d; } else { v = x; } }
12243 if (CS->size() == 1) {
12244 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12245 if (!IS) {
12246 ErrorInfo.Error = ErrorTy::NotIfStmt;
12247 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12248 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12249 CS->body_front()->getSourceRange();
12250 return false;
12251 }
12252
12253 return checkForm3(IS, ErrorInfo);
12254 } else if (CS->size() == 2) {
12255 auto *S1 = CS->body_front();
12256 auto *S2 = CS->body_back();
12257
12258 Stmt *UpdateStmt = nullptr;
12259 Stmt *CondUpdateStmt = nullptr;
12260 Stmt *CondExprStmt = nullptr;
12261
12262 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12263 // It could be one of the following cases:
12264 // { v = x; cond-update-stmt }
12265 // { v = x; cond-expr-stmt }
12266 // { cond-expr-stmt; v = x; }
12267 // form 45
12268 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12269 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12270 // check if form 45
12271 if (isa<IfStmt>(S2))
12272 return checkForm45(CS, ErrorInfo);
12273 // { cond-expr-stmt; v = x; }
12274 CondExprStmt = S1;
12275 UpdateStmt = S2;
12276 } else {
12277 IsPostfixUpdate = true;
12278 UpdateStmt = S1;
12279 if (isa<IfStmt>(S2)) {
12280 // { v = x; cond-update-stmt }
12281 CondUpdateStmt = S2;
12282 } else {
12283 // { v = x; cond-expr-stmt }
12284 CondExprStmt = S2;
12285 }
12286 }
12287 } else {
12288 // { cond-update-stmt v = x; }
12289 UpdateStmt = S2;
12290 CondUpdateStmt = S1;
12291 }
12292
12293 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12294 auto *IS = dyn_cast<IfStmt>(CUS);
12295 if (!IS) {
12296 ErrorInfo.Error = ErrorTy::NotIfStmt;
12297 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12298 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12299 return false;
12300 }
12301
12302 return checkCondUpdateStmt(IS, ErrorInfo);
12303 };
12304
12305 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12306 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12307 auto *BO = dyn_cast<BinaryOperator>(US);
12308 if (!BO) {
12309 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12310 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12311 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12312 return false;
12313 }
12314 if (BO->getOpcode() != BO_Assign) {
12315 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12316 ErrorInfo.ErrorLoc = BO->getExprLoc();
12317 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12318 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12319 return false;
12320 }
12321 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12322 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12323 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12324 ErrorInfo.NoteLoc = this->X->getExprLoc();
12325 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12326 ErrorInfo.NoteRange = this->X->getSourceRange();
12327 return false;
12328 }
12329
12330 this->V = BO->getLHS();
12331
12332 return true;
12333 };
12334
12335 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12336 return false;
12337 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12338 return false;
12339 if (!CheckUpdateStmt(UpdateStmt))
12340 return false;
12341 } else {
12342 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12343 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12344 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12345 return false;
12346 }
12347
12348 return checkType(ErrorInfo);
12349}
12350} // namespace
12351
12353 Stmt *AStmt,
12354 SourceLocation StartLoc,
12355 SourceLocation EndLoc) {
12356 ASTContext &Context = getASTContext();
12357 // Register location of the first atomic directive.
12358 DSAStack->addAtomicDirectiveLoc(StartLoc);
12359 if (!AStmt)
12360 return StmtError();
12361
12362 // 1.2.2 OpenMP Language Terminology
12363 // Structured block - An executable statement with a single entry at the
12364 // top and a single exit at the bottom.
12365 // The point of exit cannot be a branch out of the structured block.
12366 // longjmp() and throw() must not violate the entry/exit criteria.
12367 OpenMPClauseKind AtomicKind = OMPC_unknown;
12368 SourceLocation AtomicKindLoc;
12369 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12370 SourceLocation MemOrderLoc;
12371 bool MutexClauseEncountered = false;
12372 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12373 for (const OMPClause *C : Clauses) {
12374 switch (C->getClauseKind()) {
12375 case OMPC_read:
12376 case OMPC_write:
12377 case OMPC_update:
12378 MutexClauseEncountered = true;
12379 [[fallthrough]];
12380 case OMPC_capture:
12381 case OMPC_compare: {
12382 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12383 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12384 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12385 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12386 << getOpenMPClauseName(AtomicKind);
12387 } else {
12388 AtomicKind = C->getClauseKind();
12389 AtomicKindLoc = C->getBeginLoc();
12390 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12391 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12392 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12393 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12394 << getOpenMPClauseName(AtomicKind);
12395 }
12396 }
12397 break;
12398 }
12399 case OMPC_weak:
12400 case OMPC_fail: {
12401 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12402 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12403 << getOpenMPClauseName(C->getClauseKind())
12404 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12405 return StmtError();
12406 }
12407 break;
12408 }
12409 case OMPC_seq_cst:
12410 case OMPC_acq_rel:
12411 case OMPC_acquire:
12412 case OMPC_release:
12413 case OMPC_relaxed: {
12414 if (MemOrderKind != OMPC_unknown) {
12415 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12416 << getOpenMPDirectiveName(OMPD_atomic) << 0
12417 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12418 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12419 << getOpenMPClauseName(MemOrderKind);
12420 } else {
12421 MemOrderKind = C->getClauseKind();
12422 MemOrderLoc = C->getBeginLoc();
12423 }
12424 break;
12425 }
12426 // The following clauses are allowed, but we don't need to do anything here.
12427 case OMPC_hint:
12428 break;
12429 default:
12430 llvm_unreachable("unknown clause is encountered");
12431 }
12432 }
12433 bool IsCompareCapture = false;
12434 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12435 EncounteredAtomicKinds.contains(OMPC_capture)) {
12436 IsCompareCapture = true;
12437 AtomicKind = OMPC_compare;
12438 }
12439 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12440 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12441 // release.
12442 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12443 // acquire.
12444 // If atomic-clause is update or not present then memory-order-clause must not
12445 // be acq_rel or acquire.
12446 if ((AtomicKind == OMPC_read &&
12447 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12448 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12449 AtomicKind == OMPC_unknown) &&
12450 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12451 SourceLocation Loc = AtomicKindLoc;
12452 if (AtomicKind == OMPC_unknown)
12453 Loc = StartLoc;
12454 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12455 << getOpenMPClauseName(AtomicKind)
12456 << (AtomicKind == OMPC_unknown ? 1 : 0)
12457 << getOpenMPClauseName(MemOrderKind);
12458 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12459 << getOpenMPClauseName(MemOrderKind);
12460 }
12461
12462 Stmt *Body = AStmt;
12463 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12464 Body = EWC->getSubExpr();
12465
12466 Expr *X = nullptr;
12467 Expr *V = nullptr;
12468 Expr *E = nullptr;
12469 Expr *UE = nullptr;
12470 Expr *D = nullptr;
12471 Expr *CE = nullptr;
12472 Expr *R = nullptr;
12473 bool IsXLHSInRHSPart = false;
12474 bool IsPostfixUpdate = false;
12475 bool IsFailOnly = false;
12476 // OpenMP [2.12.6, atomic Construct]
12477 // In the next expressions:
12478 // * x and v (as applicable) are both l-value expressions with scalar type.
12479 // * During the execution of an atomic region, multiple syntactic
12480 // occurrences of x must designate the same storage location.
12481 // * Neither of v and expr (as applicable) may access the storage location
12482 // designated by x.
12483 // * Neither of x and expr (as applicable) may access the storage location
12484 // designated by v.
12485 // * expr is an expression with scalar type.
12486 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12487 // * binop, binop=, ++, and -- are not overloaded operators.
12488 // * The expression x binop expr must be numerically equivalent to x binop
12489 // (expr). This requirement is satisfied if the operators in expr have
12490 // precedence greater than binop, or by using parentheses around expr or
12491 // subexpressions of expr.
12492 // * The expression expr binop x must be numerically equivalent to (expr)
12493 // binop x. This requirement is satisfied if the operators in expr have
12494 // precedence equal to or greater than binop, or by using parentheses around
12495 // expr or subexpressions of expr.
12496 // * For forms that allow multiple occurrences of x, the number of times
12497 // that x is evaluated is unspecified.
12498 if (AtomicKind == OMPC_read) {
12499 enum {
12500 NotAnExpression,
12501 NotAnAssignmentOp,
12502 NotAScalarType,
12503 NotAnLValue,
12504 NoError
12505 } ErrorFound = NoError;
12506 SourceLocation ErrorLoc, NoteLoc;
12507 SourceRange ErrorRange, NoteRange;
12508 // If clause is read:
12509 // v = x;
12510 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12511 const auto *AtomicBinOp =
12512 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12513 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12514 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12515 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12516 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12517 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12518 if (!X->isLValue() || !V->isLValue()) {
12519 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12520 ErrorFound = NotAnLValue;
12521 ErrorLoc = AtomicBinOp->getExprLoc();
12522 ErrorRange = AtomicBinOp->getSourceRange();
12523 NoteLoc = NotLValueExpr->getExprLoc();
12524 NoteRange = NotLValueExpr->getSourceRange();
12525 }
12526 } else if (!X->isInstantiationDependent() ||
12527 !V->isInstantiationDependent()) {
12528 const Expr *NotScalarExpr =
12529 (X->isInstantiationDependent() || X->getType()->isScalarType())
12530 ? V
12531 : X;
12532 ErrorFound = NotAScalarType;
12533 ErrorLoc = AtomicBinOp->getExprLoc();
12534 ErrorRange = AtomicBinOp->getSourceRange();
12535 NoteLoc = NotScalarExpr->getExprLoc();
12536 NoteRange = NotScalarExpr->getSourceRange();
12537 }
12538 } else if (!AtomicBody->isInstantiationDependent()) {
12539 ErrorFound = NotAnAssignmentOp;
12540 ErrorLoc = AtomicBody->getExprLoc();
12541 ErrorRange = AtomicBody->getSourceRange();
12542 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12543 : AtomicBody->getExprLoc();
12544 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12545 : AtomicBody->getSourceRange();
12546 }
12547 } else {
12548 ErrorFound = NotAnExpression;
12549 NoteLoc = ErrorLoc = Body->getBeginLoc();
12550 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12551 }
12552 if (ErrorFound != NoError) {
12553 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12554 << ErrorRange;
12555 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12556 << ErrorFound << NoteRange;
12557 return StmtError();
12558 }
12560 V = X = nullptr;
12561 } else if (AtomicKind == OMPC_write) {
12562 enum {
12563 NotAnExpression,
12564 NotAnAssignmentOp,
12565 NotAScalarType,
12566 NotAnLValue,
12567 NoError
12568 } ErrorFound = NoError;
12569 SourceLocation ErrorLoc, NoteLoc;
12570 SourceRange ErrorRange, NoteRange;
12571 // If clause is write:
12572 // x = expr;
12573 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12574 const auto *AtomicBinOp =
12575 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12576 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12577 X = AtomicBinOp->getLHS();
12578 E = AtomicBinOp->getRHS();
12579 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12581 if (!X->isLValue()) {
12582 ErrorFound = NotAnLValue;
12583 ErrorLoc = AtomicBinOp->getExprLoc();
12584 ErrorRange = AtomicBinOp->getSourceRange();
12585 NoteLoc = X->getExprLoc();
12586 NoteRange = X->getSourceRange();
12587 }
12588 } else if (!X->isInstantiationDependent() ||
12590 const Expr *NotScalarExpr =
12591 (X->isInstantiationDependent() || X->getType()->isScalarType())
12592 ? E
12593 : X;
12594 ErrorFound = NotAScalarType;
12595 ErrorLoc = AtomicBinOp->getExprLoc();
12596 ErrorRange = AtomicBinOp->getSourceRange();
12597 NoteLoc = NotScalarExpr->getExprLoc();
12598 NoteRange = NotScalarExpr->getSourceRange();
12599 }
12600 } else if (!AtomicBody->isInstantiationDependent()) {
12601 ErrorFound = NotAnAssignmentOp;
12602 ErrorLoc = AtomicBody->getExprLoc();
12603 ErrorRange = AtomicBody->getSourceRange();
12604 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12605 : AtomicBody->getExprLoc();
12606 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12607 : AtomicBody->getSourceRange();
12608 }
12609 } else {
12610 ErrorFound = NotAnExpression;
12611 NoteLoc = ErrorLoc = Body->getBeginLoc();
12612 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12613 }
12614 if (ErrorFound != NoError) {
12615 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12616 << ErrorRange;
12617 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12618 << ErrorFound << NoteRange;
12619 return StmtError();
12620 }
12622 E = X = nullptr;
12623 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12624 // If clause is update:
12625 // x++;
12626 // x--;
12627 // ++x;
12628 // --x;
12629 // x binop= expr;
12630 // x = x binop expr;
12631 // x = expr binop x;
12632 OpenMPAtomicUpdateChecker Checker(SemaRef);
12633 if (Checker.checkStatement(
12634 Body,
12635 (AtomicKind == OMPC_update)
12636 ? diag::err_omp_atomic_update_not_expression_statement
12637 : diag::err_omp_atomic_not_expression_statement,
12638 diag::note_omp_atomic_update))
12639 return StmtError();
12641 E = Checker.getExpr();
12642 X = Checker.getX();
12643 UE = Checker.getUpdateExpr();
12644 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12645 }
12646 } else if (AtomicKind == OMPC_capture) {
12647 enum {
12648 NotAnAssignmentOp,
12649 NotACompoundStatement,
12650 NotTwoSubstatements,
12651 NotASpecificExpression,
12652 NoError
12653 } ErrorFound = NoError;
12654 SourceLocation ErrorLoc, NoteLoc;
12655 SourceRange ErrorRange, NoteRange;
12656 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12657 // If clause is a capture:
12658 // v = x++;
12659 // v = x--;
12660 // v = ++x;
12661 // v = --x;
12662 // v = x binop= expr;
12663 // v = x = x binop expr;
12664 // v = x = expr binop x;
12665 const auto *AtomicBinOp =
12666 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12667 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12668 V = AtomicBinOp->getLHS();
12669 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12670 OpenMPAtomicUpdateChecker Checker(SemaRef);
12671 if (Checker.checkStatement(
12672 Body, diag::err_omp_atomic_capture_not_expression_statement,
12673 diag::note_omp_atomic_update))
12674 return StmtError();
12675 E = Checker.getExpr();
12676 X = Checker.getX();
12677 UE = Checker.getUpdateExpr();
12678 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12679 IsPostfixUpdate = Checker.isPostfixUpdate();
12680 } else if (!AtomicBody->isInstantiationDependent()) {
12681 ErrorLoc = AtomicBody->getExprLoc();
12682 ErrorRange = AtomicBody->getSourceRange();
12683 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12684 : AtomicBody->getExprLoc();
12685 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12686 : AtomicBody->getSourceRange();
12687 ErrorFound = NotAnAssignmentOp;
12688 }
12689 if (ErrorFound != NoError) {
12690 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12691 << ErrorRange;
12692 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12693 return StmtError();
12694 }
12696 UE = V = E = X = nullptr;
12697 } else {
12698 // If clause is a capture:
12699 // { v = x; x = expr; }
12700 // { v = x; x++; }
12701 // { v = x; x--; }
12702 // { v = x; ++x; }
12703 // { v = x; --x; }
12704 // { v = x; x binop= expr; }
12705 // { v = x; x = x binop expr; }
12706 // { v = x; x = expr binop x; }
12707 // { x++; v = x; }
12708 // { x--; v = x; }
12709 // { ++x; v = x; }
12710 // { --x; v = x; }
12711 // { x binop= expr; v = x; }
12712 // { x = x binop expr; v = x; }
12713 // { x = expr binop x; v = x; }
12714 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
12715 // Check that this is { expr1; expr2; }
12716 if (CS->size() == 2) {
12717 Stmt *First = CS->body_front();
12718 Stmt *Second = CS->body_back();
12719 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
12720 First = EWC->getSubExpr()->IgnoreParenImpCasts();
12721 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
12722 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
12723 // Need to find what subexpression is 'v' and what is 'x'.
12724 OpenMPAtomicUpdateChecker Checker(SemaRef);
12725 bool IsUpdateExprFound = !Checker.checkStatement(Second);
12726 BinaryOperator *BinOp = nullptr;
12727 if (IsUpdateExprFound) {
12728 BinOp = dyn_cast<BinaryOperator>(First);
12729 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12730 }
12731 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
12732 // { v = x; x++; }
12733 // { v = x; x--; }
12734 // { v = x; ++x; }
12735 // { v = x; --x; }
12736 // { v = x; x binop= expr; }
12737 // { v = x; x = x binop expr; }
12738 // { v = x; x = expr binop x; }
12739 // Check that the first expression has form v = x.
12740 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12741 llvm::FoldingSetNodeID XId, PossibleXId;
12742 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12743 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12744 IsUpdateExprFound = XId == PossibleXId;
12745 if (IsUpdateExprFound) {
12746 V = BinOp->getLHS();
12747 X = Checker.getX();
12748 E = Checker.getExpr();
12749 UE = Checker.getUpdateExpr();
12750 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12751 IsPostfixUpdate = true;
12752 }
12753 }
12754 if (!IsUpdateExprFound) {
12755 IsUpdateExprFound = !Checker.checkStatement(First);
12756 BinOp = nullptr;
12757 if (IsUpdateExprFound) {
12758 BinOp = dyn_cast<BinaryOperator>(Second);
12759 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12760 }
12761 if (IsUpdateExprFound &&
12763 // { x++; v = x; }
12764 // { x--; v = x; }
12765 // { ++x; v = x; }
12766 // { --x; v = x; }
12767 // { x binop= expr; v = x; }
12768 // { x = x binop expr; v = x; }
12769 // { x = expr binop x; v = x; }
12770 // Check that the second expression has form v = x.
12771 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12772 llvm::FoldingSetNodeID XId, PossibleXId;
12773 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12774 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12775 IsUpdateExprFound = XId == PossibleXId;
12776 if (IsUpdateExprFound) {
12777 V = BinOp->getLHS();
12778 X = Checker.getX();
12779 E = Checker.getExpr();
12780 UE = Checker.getUpdateExpr();
12781 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12782 IsPostfixUpdate = false;
12783 }
12784 }
12785 }
12786 if (!IsUpdateExprFound) {
12787 // { v = x; x = expr; }
12788 auto *FirstExpr = dyn_cast<Expr>(First);
12789 auto *SecondExpr = dyn_cast<Expr>(Second);
12790 if (!FirstExpr || !SecondExpr ||
12791 !(FirstExpr->isInstantiationDependent() ||
12792 SecondExpr->isInstantiationDependent())) {
12793 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
12794 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
12795 ErrorFound = NotAnAssignmentOp;
12796 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
12797 : First->getBeginLoc();
12798 NoteRange = ErrorRange = FirstBinOp
12799 ? FirstBinOp->getSourceRange()
12800 : SourceRange(ErrorLoc, ErrorLoc);
12801 } else {
12802 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
12803 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
12804 ErrorFound = NotAnAssignmentOp;
12805 NoteLoc = ErrorLoc = SecondBinOp
12806 ? SecondBinOp->getOperatorLoc()
12807 : Second->getBeginLoc();
12808 NoteRange = ErrorRange =
12809 SecondBinOp ? SecondBinOp->getSourceRange()
12810 : SourceRange(ErrorLoc, ErrorLoc);
12811 } else {
12812 Expr *PossibleXRHSInFirst =
12813 FirstBinOp->getRHS()->IgnoreParenImpCasts();
12814 Expr *PossibleXLHSInSecond =
12815 SecondBinOp->getLHS()->IgnoreParenImpCasts();
12816 llvm::FoldingSetNodeID X1Id, X2Id;
12817 PossibleXRHSInFirst->Profile(X1Id, Context,
12818 /*Canonical=*/true);
12819 PossibleXLHSInSecond->Profile(X2Id, Context,
12820 /*Canonical=*/true);
12821 IsUpdateExprFound = X1Id == X2Id;
12822 if (IsUpdateExprFound) {
12823 V = FirstBinOp->getLHS();
12824 X = SecondBinOp->getLHS();
12825 E = SecondBinOp->getRHS();
12826 UE = nullptr;
12827 IsXLHSInRHSPart = false;
12828 IsPostfixUpdate = true;
12829 } else {
12830 ErrorFound = NotASpecificExpression;
12831 ErrorLoc = FirstBinOp->getExprLoc();
12832 ErrorRange = FirstBinOp->getSourceRange();
12833 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
12834 NoteRange = SecondBinOp->getRHS()->getSourceRange();
12835 }
12836 }
12837 }
12838 }
12839 }
12840 } else {
12841 NoteLoc = ErrorLoc = Body->getBeginLoc();
12842 NoteRange = ErrorRange =
12843 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12844 ErrorFound = NotTwoSubstatements;
12845 }
12846 } else {
12847 NoteLoc = ErrorLoc = Body->getBeginLoc();
12848 NoteRange = ErrorRange =
12849 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12850 ErrorFound = NotACompoundStatement;
12851 }
12852 }
12853 if (ErrorFound != NoError) {
12854 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
12855 << ErrorRange;
12856 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12857 return StmtError();
12858 }
12860 UE = V = E = X = nullptr;
12861 } else if (AtomicKind == OMPC_compare) {
12862 if (IsCompareCapture) {
12863 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
12864 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
12865 if (!Checker.checkStmt(Body, ErrorInfo)) {
12866 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
12867 << ErrorInfo.ErrorRange;
12868 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12869 << ErrorInfo.Error << ErrorInfo.NoteRange;
12870 return StmtError();
12871 }
12872 X = Checker.getX();
12873 E = Checker.getE();
12874 D = Checker.getD();
12875 CE = Checker.getCond();
12876 V = Checker.getV();
12877 R = Checker.getR();
12878 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12879 IsXLHSInRHSPart = Checker.isXBinopExpr();
12880 IsFailOnly = Checker.isFailOnly();
12881 IsPostfixUpdate = Checker.isPostfixUpdate();
12882 } else {
12883 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
12884 OpenMPAtomicCompareChecker Checker(SemaRef);
12885 if (!Checker.checkStmt(Body, ErrorInfo)) {
12886 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
12887 << ErrorInfo.ErrorRange;
12888 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12889 << ErrorInfo.Error << ErrorInfo.NoteRange;
12890 return StmtError();
12891 }
12892 X = Checker.getX();
12893 E = Checker.getE();
12894 D = Checker.getD();
12895 CE = Checker.getCond();
12896 // The weak clause may only appear if the resulting atomic operation is
12897 // an atomic conditional update for which the comparison tests for
12898 // equality. It was not possible to do this check in
12899 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
12900 // could not be performed (Clauses are not available).
12901 auto *It = find_if(Clauses, [](OMPClause *C) {
12902 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
12903 });
12904 if (It != Clauses.end()) {
12905 auto *Cond = dyn_cast<BinaryOperator>(CE);
12906 if (Cond->getOpcode() != BO_EQ) {
12907 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
12908 ErrorInfo.ErrorLoc = Cond->getExprLoc();
12909 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
12910 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12911
12912 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
12913 << ErrorInfo.ErrorRange;
12914 return StmtError();
12915 }
12916 }
12917 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12918 IsXLHSInRHSPart = Checker.isXBinopExpr();
12919 }
12920 }
12921
12923
12925 Context, StartLoc, EndLoc, Clauses, AStmt,
12926 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
12927}
12928
12930 Stmt *AStmt,
12931 SourceLocation StartLoc,
12932 SourceLocation EndLoc) {
12933 if (!AStmt)
12934 return StmtError();
12935
12936 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target, AStmt);
12937
12938 // OpenMP [2.16, Nesting of Regions]
12939 // If specified, a teams construct must be contained within a target
12940 // construct. That target construct must contain no statements or directives
12941 // outside of the teams construct.
12942 if (DSAStack->hasInnerTeamsRegion()) {
12943 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
12944 bool OMPTeamsFound = true;
12945 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
12946 auto I = CS->body_begin();
12947 while (I != CS->body_end()) {
12948 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
12949 bool IsTeams = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
12950 if (!IsTeams || I != CS->body_begin()) {
12951 OMPTeamsFound = false;
12952 if (IsTeams && I != CS->body_begin()) {
12953 // This is the two teams case. Since the InnerTeamsRegionLoc will
12954 // point to this second one reset the iterator to the other teams.
12955 --I;
12956 }
12957 break;
12958 }
12959 ++I;
12960 }
12961 assert(I != CS->body_end() && "Not found statement");
12962 S = *I;
12963 } else {
12964 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
12965 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
12966 }
12967 if (!OMPTeamsFound) {
12968 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
12969 Diag(DSAStack->getInnerTeamsRegionLoc(),
12970 diag::note_omp_nested_teams_construct_here);
12971 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
12972 << isa<OMPExecutableDirective>(S);
12973 return StmtError();
12974 }
12975 }
12976
12977 return OMPTargetDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
12978 AStmt);
12979}
12980
12982 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12983 SourceLocation EndLoc) {
12984 if (!AStmt)
12985 return StmtError();
12986
12987 setBranchProtectedScope(SemaRef, OMPD_target_parallel, AStmt);
12988
12990 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
12991 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
12992}
12993
12995 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12996 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
12997 if (!AStmt)
12998 return StmtError();
12999
13000 CapturedStmt *CS =
13001 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for, AStmt);
13002
13004 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13005 // define the nested loops number.
13006 unsigned NestedLoopCount =
13007 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13008 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13009 VarsWithImplicitDSA, B);
13010 if (NestedLoopCount == 0)
13011 return StmtError();
13012
13013 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13014 return StmtError();
13015
13017 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13018 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13019}
13020
13021/// Check for existence of a map clause in the list of clauses.
13023 const OpenMPClauseKind K) {
13024 return llvm::any_of(
13025 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13026}
13027
13028template <typename... Params>
13030 const Params... ClauseTypes) {
13031 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13032}
13033
13034/// Check if the variables in the mapping clause are externally visible.
13036 for (const OMPClause *C : Clauses) {
13037 if (auto *TC = dyn_cast<OMPToClause>(C))
13038 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13039 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13040 (VD->isExternallyVisible() &&
13041 VD->getVisibility() != HiddenVisibility);
13042 });
13043 else if (auto *FC = dyn_cast<OMPFromClause>(C))
13044 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13045 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13046 (VD->isExternallyVisible() &&
13047 VD->getVisibility() != HiddenVisibility);
13048 });
13049 }
13050
13051 return true;
13052}
13053
13056 Stmt *AStmt, SourceLocation StartLoc,
13057 SourceLocation EndLoc) {
13058 if (!AStmt)
13059 return StmtError();
13060
13061 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13062
13063 // OpenMP [2.12.2, target data Construct, Restrictions]
13064 // At least one map, use_device_addr or use_device_ptr clause must appear on
13065 // the directive.
13066 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13067 (getLangOpts().OpenMP < 50 ||
13068 !hasClauses(Clauses, OMPC_use_device_addr))) {
13069 StringRef Expected;
13070 if (getLangOpts().OpenMP < 50)
13071 Expected = "'map' or 'use_device_ptr'";
13072 else
13073 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13074 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13075 << Expected << getOpenMPDirectiveName(OMPD_target_data);
13076 return StmtError();
13077 }
13078
13080
13081 return OMPTargetDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13082 Clauses, AStmt);
13083}
13084
13086 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13087 SourceLocation EndLoc, Stmt *AStmt) {
13088 if (!AStmt)
13089 return StmtError();
13090
13091 setBranchProtectedScope(SemaRef, OMPD_target_enter_data, AStmt);
13092
13093 // OpenMP [2.10.2, Restrictions, p. 99]
13094 // At least one map clause must appear on the directive.
13095 if (!hasClauses(Clauses, OMPC_map)) {
13096 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13097 << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
13098 return StmtError();
13099 }
13100
13101 return OMPTargetEnterDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13102 Clauses, AStmt);
13103}
13104
13106 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13107 SourceLocation EndLoc, Stmt *AStmt) {
13108 if (!AStmt)
13109 return StmtError();
13110
13111 setBranchProtectedScope(SemaRef, OMPD_target_exit_data, AStmt);
13112
13113 // OpenMP [2.10.3, Restrictions, p. 102]
13114 // At least one map clause must appear on the directive.
13115 if (!hasClauses(Clauses, OMPC_map)) {
13116 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13117 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
13118 return StmtError();
13119 }
13120
13121 return OMPTargetExitDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13122 Clauses, AStmt);
13123}
13124
13126 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13127 SourceLocation EndLoc, Stmt *AStmt) {
13128 if (!AStmt)
13129 return StmtError();
13130
13131 setBranchProtectedScope(SemaRef, OMPD_target_update, AStmt);
13132
13133 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13134 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13135 return StmtError();
13136 }
13137
13138 if (!isClauseMappable(Clauses)) {
13139 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13140 return StmtError();
13141 }
13142
13143 return OMPTargetUpdateDirective::Create(getASTContext(), StartLoc, EndLoc,
13144 Clauses, AStmt);
13145}
13146
13147/// This checks whether a \p ClauseType clause \p C has at most \p Max
13148/// expression. If not, a diag of number \p Diag will be emitted.
13149template <typename ClauseType>
13150static bool checkNumExprsInClause(SemaBase &SemaRef,
13151 ArrayRef<OMPClause *> Clauses,
13152 unsigned MaxNum, unsigned Diag) {
13153 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13154 if (ClauseItr == Clauses.end())
13155 return true;
13156 const auto *C = cast<ClauseType>(*ClauseItr);
13157 auto VarList = C->getVarRefs();
13158 if (VarList.size() > MaxNum) {
13159 SemaRef.Diag(VarList[MaxNum]->getBeginLoc(), Diag)
13160 << getOpenMPClauseName(C->getClauseKind());
13161 return false;
13162 }
13163 return true;
13164}
13165
13167 Stmt *AStmt,
13168 SourceLocation StartLoc,
13169 SourceLocation EndLoc) {
13170 if (!AStmt)
13171 return StmtError();
13172
13173 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13174 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
13175 !checkNumExprsInClause<OMPThreadLimitClause>(
13176 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
13177 return StmtError();
13178
13179 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13180 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13181 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13182
13183 setBranchProtectedScope(SemaRef, OMPD_teams, AStmt);
13184
13185 DSAStack->setParentTeamsRegionLoc(StartLoc);
13186
13187 return OMPTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13188 AStmt);
13189}
13190
13192 SourceLocation StartLoc, SourceLocation EndLoc,
13193 OpenMPDirectiveKind CancelRegion) {
13194 if (DSAStack->isParentNowaitRegion()) {
13195 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13196 return StmtError();
13197 }
13198 if (DSAStack->isParentOrderedRegion()) {
13199 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13200 return StmtError();
13201 }
13203 EndLoc, CancelRegion);
13204}
13205
13207 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13208 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13209 if (DSAStack->isParentNowaitRegion()) {
13210 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13211 return StmtError();
13212 }
13213 if (DSAStack->isParentOrderedRegion()) {
13214 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13215 return StmtError();
13216 }
13217 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13218 return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13219 CancelRegion);
13220}
13221
13223 ArrayRef<OMPClause *> Clauses) {
13224 const OMPClause *ReductionClause = nullptr;
13225 const OMPClause *NogroupClause = nullptr;
13226 for (const OMPClause *C : Clauses) {
13227 if (C->getClauseKind() == OMPC_reduction) {
13228 ReductionClause = C;
13229 if (NogroupClause)
13230 break;
13231 continue;
13232 }
13233 if (C->getClauseKind() == OMPC_nogroup) {
13234 NogroupClause = C;
13235 if (ReductionClause)
13236 break;
13237 continue;
13238 }
13239 }
13240 if (ReductionClause && NogroupClause) {
13241 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13242 << SourceRange(NogroupClause->getBeginLoc(),
13243 NogroupClause->getEndLoc());
13244 return true;
13245 }
13246 return false;
13247}
13248
13250 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13251 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13252 if (!AStmt)
13253 return StmtError();
13254
13255 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13257 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13258 // define the nested loops number.
13259 unsigned NestedLoopCount =
13260 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13261 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13262 *DSAStack, VarsWithImplicitDSA, B);
13263 if (NestedLoopCount == 0)
13264 return StmtError();
13265
13266 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13267 "omp for loop exprs were not built");
13268
13269 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13270 // The grainsize clause and num_tasks clause are mutually exclusive and may
13271 // not appear on the same taskloop directive.
13273 {OMPC_grainsize, OMPC_num_tasks}))
13274 return StmtError();
13275 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13276 // If a reduction clause is present on the taskloop directive, the nogroup
13277 // clause must not be specified.
13279 return StmtError();
13280
13282 return OMPTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13283 NestedLoopCount, Clauses, AStmt, B,
13284 DSAStack->isCancelRegion());
13285}
13286
13288 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13289 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13290 if (!AStmt)
13291 return StmtError();
13292
13293 CapturedStmt *CS =
13294 setBranchProtectedScope(SemaRef, OMPD_taskloop_simd, AStmt);
13295
13296 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13298 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13299 // define the nested loops number.
13300 unsigned NestedLoopCount =
13301 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13302 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13303 VarsWithImplicitDSA, B);
13304 if (NestedLoopCount == 0)
13305 return StmtError();
13306
13307 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13308 return StmtError();
13309
13310 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13311 // The grainsize clause and num_tasks clause are mutually exclusive and may
13312 // not appear on the same taskloop directive.
13314 {OMPC_grainsize, OMPC_num_tasks}))
13315 return StmtError();
13316 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13317 // If a reduction clause is present on the taskloop directive, the nogroup
13318 // clause must not be specified.
13320 return StmtError();
13322 return StmtError();
13323
13324 return OMPTaskLoopSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13325 NestedLoopCount, Clauses, AStmt, B);
13326}
13327
13329 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13330 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13331 if (!AStmt)
13332 return StmtError();
13333
13334 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13336 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13337 // define the nested loops number.
13338 unsigned NestedLoopCount =
13339 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13340 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13341 *DSAStack, VarsWithImplicitDSA, B);
13342 if (NestedLoopCount == 0)
13343 return StmtError();
13344
13345 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13346 "omp for loop exprs were not built");
13347
13348 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13349 // The grainsize clause and num_tasks clause are mutually exclusive and may
13350 // not appear on the same taskloop directive.
13352 {OMPC_grainsize, OMPC_num_tasks}))
13353 return StmtError();
13354 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13355 // If a reduction clause is present on the taskloop directive, the nogroup
13356 // clause must not be specified.
13358 return StmtError();
13359
13361 return OMPMasterTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13362 NestedLoopCount, Clauses, AStmt, B,
13363 DSAStack->isCancelRegion());
13364}
13365
13367 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13368 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13369 if (!AStmt)
13370 return StmtError();
13371
13372 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13374 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13375 // define the nested loops number.
13376 unsigned NestedLoopCount =
13377 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13378 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13379 *DSAStack, VarsWithImplicitDSA, B);
13380 if (NestedLoopCount == 0)
13381 return StmtError();
13382
13383 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13384 "omp for loop exprs were not built");
13385
13386 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13387 // The grainsize clause and num_tasks clause are mutually exclusive and may
13388 // not appear on the same taskloop directive.
13390 {OMPC_grainsize, OMPC_num_tasks}))
13391 return StmtError();
13392 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13393 // If a reduction clause is present on the taskloop directive, the nogroup
13394 // clause must not be specified.
13396 return StmtError();
13397
13399 return OMPMaskedTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13400 NestedLoopCount, Clauses, AStmt, B,
13401 DSAStack->isCancelRegion());
13402}
13403
13405 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13406 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13407 if (!AStmt)
13408 return StmtError();
13409
13410 CapturedStmt *CS =
13411 setBranchProtectedScope(SemaRef, OMPD_master_taskloop_simd, AStmt);
13412
13413 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13415 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13416 // define the nested loops number.
13417 unsigned NestedLoopCount =
13418 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13419 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13420 VarsWithImplicitDSA, B);
13421 if (NestedLoopCount == 0)
13422 return StmtError();
13423
13424 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13425 return StmtError();
13426
13427 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13428 // The grainsize clause and num_tasks clause are mutually exclusive and may
13429 // not appear on the same taskloop directive.
13431 {OMPC_grainsize, OMPC_num_tasks}))
13432 return StmtError();
13433 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13434 // If a reduction clause is present on the taskloop directive, the nogroup
13435 // clause must not be specified.
13437 return StmtError();
13439 return StmtError();
13440
13442 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13443}
13444
13446 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13447 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13448 if (!AStmt)
13449 return StmtError();
13450
13451 CapturedStmt *CS =
13452 setBranchProtectedScope(SemaRef, OMPD_masked_taskloop_simd, AStmt);
13453
13454 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13456 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13457 // define the nested loops number.
13458 unsigned NestedLoopCount =
13459 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13460 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13461 VarsWithImplicitDSA, B);
13462 if (NestedLoopCount == 0)
13463 return StmtError();
13464
13465 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13466 return StmtError();
13467
13468 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13469 // The grainsize clause and num_tasks clause are mutually exclusive and may
13470 // not appear on the same taskloop directive.
13472 {OMPC_grainsize, OMPC_num_tasks}))
13473 return StmtError();
13474 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13475 // If a reduction clause is present on the taskloop directive, the nogroup
13476 // clause must not be specified.
13478 return StmtError();
13480 return StmtError();
13481
13483 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13484}
13485
13487 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13488 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13489 if (!AStmt)
13490 return StmtError();
13491
13492 CapturedStmt *CS =
13493 setBranchProtectedScope(SemaRef, OMPD_parallel_master_taskloop, AStmt);
13494
13496 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13497 // define the nested loops number.
13498 unsigned NestedLoopCount = checkOpenMPLoop(
13499 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13500 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13501 VarsWithImplicitDSA, B);
13502 if (NestedLoopCount == 0)
13503 return StmtError();
13504
13505 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13506 "omp for loop exprs were not built");
13507
13508 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13509 // The grainsize clause and num_tasks clause are mutually exclusive and may
13510 // not appear on the same taskloop directive.
13512 {OMPC_grainsize, OMPC_num_tasks}))
13513 return StmtError();
13514 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13515 // If a reduction clause is present on the taskloop directive, the nogroup
13516 // clause must not be specified.
13518 return StmtError();
13519
13521 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13522 DSAStack->isCancelRegion());
13523}
13524
13526 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13527 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13528 if (!AStmt)
13529 return StmtError();
13530
13531 CapturedStmt *CS =
13532 setBranchProtectedScope(SemaRef, OMPD_parallel_masked_taskloop, AStmt);
13533
13535 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13536 // define the nested loops number.
13537 unsigned NestedLoopCount = checkOpenMPLoop(
13538 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13539 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13540 VarsWithImplicitDSA, B);
13541 if (NestedLoopCount == 0)
13542 return StmtError();
13543
13544 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13545 "omp for loop exprs were not built");
13546
13547 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13548 // The grainsize clause and num_tasks clause are mutually exclusive and may
13549 // not appear on the same taskloop directive.
13551 {OMPC_grainsize, OMPC_num_tasks}))
13552 return StmtError();
13553 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13554 // If a reduction clause is present on the taskloop directive, the nogroup
13555 // clause must not be specified.
13557 return StmtError();
13558
13560 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13561 DSAStack->isCancelRegion());
13562}
13563
13565 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13566 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13567 if (!AStmt)
13568 return StmtError();
13569
13571 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13572
13574 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13575 // define the nested loops number.
13576 unsigned NestedLoopCount = checkOpenMPLoop(
13577 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13578 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13579 VarsWithImplicitDSA, B);
13580 if (NestedLoopCount == 0)
13581 return StmtError();
13582
13583 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13584 return StmtError();
13585
13586 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13587 // The grainsize clause and num_tasks clause are mutually exclusive and may
13588 // not appear on the same taskloop directive.
13590 {OMPC_grainsize, OMPC_num_tasks}))
13591 return StmtError();
13592 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13593 // If a reduction clause is present on the taskloop directive, the nogroup
13594 // clause must not be specified.
13596 return StmtError();
13598 return StmtError();
13599
13601 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13602}
13603
13605 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13606 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13607 if (!AStmt)
13608 return StmtError();
13609
13611 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13612
13614 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13615 // define the nested loops number.
13616 unsigned NestedLoopCount = checkOpenMPLoop(
13617 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13618 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13619 VarsWithImplicitDSA, B);
13620 if (NestedLoopCount == 0)
13621 return StmtError();
13622
13623 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13624 return StmtError();
13625
13626 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13627 // The grainsize clause and num_tasks clause are mutually exclusive and may
13628 // not appear on the same taskloop directive.
13630 {OMPC_grainsize, OMPC_num_tasks}))
13631 return StmtError();
13632 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13633 // If a reduction clause is present on the taskloop directive, the nogroup
13634 // clause must not be specified.
13636 return StmtError();
13638 return StmtError();
13639
13641 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13642}
13643
13645 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13646 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13647 if (!AStmt)
13648 return StmtError();
13649
13650 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13652 // In presence of clause 'collapse' with number of loops, it will
13653 // define the nested loops number.
13654 unsigned NestedLoopCount =
13655 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
13656 nullptr /*ordered not a clause on distribute*/, AStmt,
13657 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13658 if (NestedLoopCount == 0)
13659 return StmtError();
13660
13661 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13662 "omp for loop exprs were not built");
13663
13665 auto *DistributeDirective = OMPDistributeDirective::Create(
13666 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13667 return DistributeDirective;
13668}
13669
13671 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13672 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13673 if (!AStmt)
13674 return StmtError();
13675
13676 CapturedStmt *CS =
13677 setBranchProtectedScope(SemaRef, OMPD_distribute_parallel_for, AStmt);
13678
13680 // In presence of clause 'collapse' with number of loops, it will
13681 // define the nested loops number.
13682 unsigned NestedLoopCount = checkOpenMPLoop(
13683 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13684 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13685 VarsWithImplicitDSA, B);
13686 if (NestedLoopCount == 0)
13687 return StmtError();
13688
13689 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13690 "omp for loop exprs were not built");
13691
13693 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13694 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13695}
13696
13698 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13699 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13700 if (!AStmt)
13701 return StmtError();
13702
13704 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
13705
13707 // In presence of clause 'collapse' with number of loops, it will
13708 // define the nested loops number.
13709 unsigned NestedLoopCount = checkOpenMPLoop(
13710 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13711 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13712 VarsWithImplicitDSA, B);
13713 if (NestedLoopCount == 0)
13714 return StmtError();
13715
13716 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13717 return StmtError();
13718
13720 return StmtError();
13721
13723 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13724}
13725
13727 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13728 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13729 if (!AStmt)
13730 return StmtError();
13731
13732 CapturedStmt *CS =
13733 setBranchProtectedScope(SemaRef, OMPD_distribute_simd, AStmt);
13734
13736 // In presence of clause 'collapse' with number of loops, it will
13737 // define the nested loops number.
13738 unsigned NestedLoopCount =
13739 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
13740 nullptr /*ordered not a clause on distribute*/, CS,
13741 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13742 if (NestedLoopCount == 0)
13743 return StmtError();
13744
13745 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13746 return StmtError();
13747
13749 return StmtError();
13750
13751 return OMPDistributeSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13752 NestedLoopCount, Clauses, AStmt, B);
13753}
13754
13756 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13757 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13758 if (!AStmt)
13759 return StmtError();
13760
13761 CapturedStmt *CS =
13762 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for_simd, AStmt);
13763
13765 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13766 // define the nested loops number.
13767 unsigned NestedLoopCount = checkOpenMPLoop(
13768 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
13769 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13770 VarsWithImplicitDSA, B);
13771 if (NestedLoopCount == 0)
13772 return StmtError();
13773
13774 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13775 return StmtError();
13776
13778 return StmtError();
13779
13781 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13782}
13783
13785 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13786 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13787 if (!AStmt)
13788 return StmtError();
13789
13790 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target_simd, AStmt);
13791
13793 // In presence of clause 'collapse' with number of loops, it will define the
13794 // nested loops number.
13795 unsigned NestedLoopCount =
13796 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
13797 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13798 VarsWithImplicitDSA, B);
13799 if (NestedLoopCount == 0)
13800 return StmtError();
13801
13802 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13803 return StmtError();
13804
13806 return StmtError();
13807
13808 return OMPTargetSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13809 NestedLoopCount, Clauses, AStmt, B);
13810}
13811
13813 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13814 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13815 if (!AStmt)
13816 return StmtError();
13817
13818 CapturedStmt *CS =
13819 setBranchProtectedScope(SemaRef, OMPD_teams_distribute, AStmt);
13820
13822 // In presence of clause 'collapse' with number of loops, it will
13823 // define the nested loops number.
13824 unsigned NestedLoopCount =
13825 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
13826 nullptr /*ordered not a clause on distribute*/, CS,
13827 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13828 if (NestedLoopCount == 0)
13829 return StmtError();
13830
13831 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13832 "omp teams distribute loop exprs were not built");
13833
13834 DSAStack->setParentTeamsRegionLoc(StartLoc);
13835
13837 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13838}
13839
13841 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13842 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13843 if (!AStmt)
13844 return StmtError();
13845
13846 CapturedStmt *CS =
13847 setBranchProtectedScope(SemaRef, OMPD_teams_distribute_simd, AStmt);
13848
13850 // In presence of clause 'collapse' with number of loops, it will
13851 // define the nested loops number.
13852 unsigned NestedLoopCount = checkOpenMPLoop(
13853 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
13854 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13855 VarsWithImplicitDSA, B);
13856 if (NestedLoopCount == 0)
13857 return StmtError();
13858
13859 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13860 return StmtError();
13861
13863 return StmtError();
13864
13865 DSAStack->setParentTeamsRegionLoc(StartLoc);
13866
13868 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13869}
13870
13872 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13873 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13874 if (!AStmt)
13875 return StmtError();
13876
13878 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
13879
13881 // In presence of clause 'collapse' with number of loops, it will
13882 // define the nested loops number.
13883 unsigned NestedLoopCount = checkOpenMPLoop(
13884 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13885 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13886 VarsWithImplicitDSA, B);
13887 if (NestedLoopCount == 0)
13888 return StmtError();
13889
13890 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13891 return StmtError();
13892
13894 return StmtError();
13895
13896 DSAStack->setParentTeamsRegionLoc(StartLoc);
13897
13899 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13900}
13901
13903 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13904 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13905 if (!AStmt)
13906 return StmtError();
13907
13909 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
13910
13912 // In presence of clause 'collapse' with number of loops, it will
13913 // define the nested loops number.
13914 unsigned NestedLoopCount = checkOpenMPLoop(
13915 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13916 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13917 VarsWithImplicitDSA, B);
13918
13919 if (NestedLoopCount == 0)
13920 return StmtError();
13921
13922 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13923 "omp for loop exprs were not built");
13924
13925 DSAStack->setParentTeamsRegionLoc(StartLoc);
13926
13928 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13929 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13930}
13931
13933 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13934 SourceLocation EndLoc) {
13935 if (!AStmt)
13936 return StmtError();
13937
13938 setBranchProtectedScope(SemaRef, OMPD_target_teams, AStmt);
13939
13940 const OMPClause *BareClause = nullptr;
13941 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) &&
13942 hasClauses(Clauses, OMPC_thread_limit);
13943 bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) {
13944 BareClause = C;
13945 return C->getClauseKind() == OMPC_ompx_bare;
13946 });
13947
13948 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
13949 Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
13950 return StmtError();
13951 }
13952
13953 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
13954 unsigned DiagNo = HasBareClause
13955 ? diag::err_ompx_more_than_three_expr_not_allowed
13956 : diag::err_omp_multi_expr_not_allowed;
13957 if (!checkNumExprsInClause<OMPNumTeamsClause>(*this, Clauses,
13958 ClauseMaxNumExprs, DiagNo) ||
13959 !checkNumExprsInClause<OMPThreadLimitClause>(*this, Clauses,
13960 ClauseMaxNumExprs, DiagNo))
13961 return StmtError();
13962
13963 return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc,
13964 Clauses, AStmt);
13965}
13966
13968 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13969 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13970 if (!AStmt)
13971 return StmtError();
13972
13973 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13974 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
13975 !checkNumExprsInClause<OMPThreadLimitClause>(
13976 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
13977 return StmtError();
13978
13979 CapturedStmt *CS =
13980 setBranchProtectedScope(SemaRef, OMPD_target_teams_distribute, AStmt);
13981
13983 // In presence of clause 'collapse' with number of loops, it will
13984 // define the nested loops number.
13985 unsigned NestedLoopCount = checkOpenMPLoop(
13986 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
13987 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13988 VarsWithImplicitDSA, B);
13989 if (NestedLoopCount == 0)
13990 return StmtError();
13991
13992 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13993 "omp target teams distribute loop exprs were not built");
13994
13996 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13997}
13998
14000 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14001 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14002 if (!AStmt)
14003 return StmtError();
14004
14005 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14006 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14007 !checkNumExprsInClause<OMPThreadLimitClause>(
14008 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14009 return StmtError();
14010
14012 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14013
14015 // In presence of clause 'collapse' with number of loops, it will
14016 // define the nested loops number.
14017 unsigned NestedLoopCount = checkOpenMPLoop(
14018 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14019 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14020 VarsWithImplicitDSA, B);
14021 if (NestedLoopCount == 0)
14022 return StmtError();
14023
14024 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14025 return StmtError();
14026
14028 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14029 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14030}
14031
14033 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14034 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14035 if (!AStmt)
14036 return StmtError();
14037
14038 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14039 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14040 !checkNumExprsInClause<OMPThreadLimitClause>(
14041 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14042 return StmtError();
14043
14045 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14046
14048 // In presence of clause 'collapse' with number of loops, it will
14049 // define the nested loops number.
14050 unsigned NestedLoopCount =
14051 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14052 getCollapseNumberExpr(Clauses),
14053 nullptr /*ordered not a clause on distribute*/, CS,
14054 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14055 if (NestedLoopCount == 0)
14056 return StmtError();
14057
14058 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14059 return StmtError();
14060
14062 return StmtError();
14063
14065 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14066}
14067
14069 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14070 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14071 if (!AStmt)
14072 return StmtError();
14073
14074 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14075 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14076 !checkNumExprsInClause<OMPThreadLimitClause>(
14077 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14078 return StmtError();
14079
14081 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14082
14084 // In presence of clause 'collapse' with number of loops, it will
14085 // define the nested loops number.
14086 unsigned NestedLoopCount = checkOpenMPLoop(
14087 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14088 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14089 VarsWithImplicitDSA, B);
14090 if (NestedLoopCount == 0)
14091 return StmtError();
14092
14093 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14094 return StmtError();
14095
14097 return StmtError();
14098
14100 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14101}
14102
14103bool SemaOpenMP::checkTransformableLoopNest(
14104 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14106 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *, 0>> &OriginalInits) {
14107 OriginalInits.emplace_back();
14109 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14110 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14111 Stmt *CurStmt) {
14112 VarsWithInheritedDSAType TmpDSA;
14113 unsigned SingleNumLoops =
14114 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14115 TmpDSA, LoopHelpers[Cnt]);
14116 if (SingleNumLoops == 0)
14117 return true;
14118 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14119 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14120 OriginalInits.back().push_back(For->getInit());
14121 Body = For->getBody();
14122 } else {
14123 assert(isa<CXXForRangeStmt>(CurStmt) &&
14124 "Expected canonical for or range-based for loops.");
14125 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14126 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14127 Body = CXXFor->getBody();
14128 }
14129 OriginalInits.emplace_back();
14130 return false;
14131 },
14132 [&OriginalInits](OMPLoopBasedDirective *Transform) {
14133 Stmt *DependentPreInits;
14134 if (auto *Dir = dyn_cast<OMPTileDirective>(Transform))
14135 DependentPreInits = Dir->getPreInits();
14136 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
14137 DependentPreInits = Dir->getPreInits();
14138 else if (auto *Dir = dyn_cast<OMPReverseDirective>(Transform))
14139 DependentPreInits = Dir->getPreInits();
14140 else if (auto *Dir = dyn_cast<OMPInterchangeDirective>(Transform))
14141 DependentPreInits = Dir->getPreInits();
14142 else
14143 llvm_unreachable("Unhandled loop transformation");
14144
14145 appendFlattenedStmtList(OriginalInits.back(), DependentPreInits);
14146 });
14147 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14148 OriginalInits.pop_back();
14149 return Result;
14150}
14151
14152/// Add preinit statements that need to be propageted from the selected loop.
14153static void addLoopPreInits(ASTContext &Context,
14155 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
14156 SmallVectorImpl<Stmt *> &PreInits) {
14157
14158 // For range-based for-statements, ensure that their syntactic sugar is
14159 // executed by adding them as pre-init statements.
14160 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14161 Stmt *RangeInit = CXXRangeFor->getInit();
14162 if (RangeInit)
14163 PreInits.push_back(RangeInit);
14164
14165 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14166 PreInits.push_back(new (Context) DeclStmt(RangeStmt->getDeclGroup(),
14167 RangeStmt->getBeginLoc(),
14168 RangeStmt->getEndLoc()));
14169
14170 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14171 PreInits.push_back(new (Context) DeclStmt(RangeEnd->getDeclGroup(),
14172 RangeEnd->getBeginLoc(),
14173 RangeEnd->getEndLoc()));
14174 }
14175
14176 llvm::append_range(PreInits, OriginalInit);
14177
14178 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
14179 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
14180 PreInits.push_back(new (Context) DeclStmt(
14181 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14182 }
14183
14184 // Gather declarations for the data members used as counters.
14185 for (Expr *CounterRef : LoopHelper.Counters) {
14186 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14187 if (isa<OMPCapturedExprDecl>(CounterDecl))
14188 PreInits.push_back(new (Context) DeclStmt(
14189 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
14190 }
14191}
14192
14193/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
14194/// loop of a construct.
14195static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) {
14196 size_t NumLoops = LoopStmts.size();
14198 AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
14199 [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
14200 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
14201 LoopStmts[Cnt] = CurStmt;
14202 return false;
14203 });
14204 assert(!is_contained(LoopStmts, nullptr) &&
14205 "Expecting a loop statement for each affected loop");
14206}
14207
14209 Stmt *AStmt,
14210 SourceLocation StartLoc,
14211 SourceLocation EndLoc) {
14212 ASTContext &Context = getASTContext();
14213 Scope *CurScope = SemaRef.getCurScope();
14214
14215 const auto *SizesClause =
14216 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14217 if (!SizesClause ||
14218 llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; }))
14219 return StmtError();
14220 unsigned NumLoops = SizesClause->getNumSizes();
14221
14222 // Empty statement should only be possible if there already was an error.
14223 if (!AStmt)
14224 return StmtError();
14225
14226 // Verify and diagnose loop nest.
14228 Stmt *Body = nullptr;
14229 SmallVector<SmallVector<Stmt *, 0>, 4> OriginalInits;
14230 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14231 OriginalInits))
14232 return StmtError();
14233
14234 // Delay tiling to when template is completely instantiated.
14236 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14237 NumLoops, AStmt, nullptr, nullptr);
14238
14239 assert(LoopHelpers.size() == NumLoops &&
14240 "Expecting loop iteration space dimensionality to match number of "
14241 "affected loops");
14242 assert(OriginalInits.size() == NumLoops &&
14243 "Expecting loop iteration space dimensionality to match number of "
14244 "affected loops");
14245
14246 // Collect all affected loop statements.
14247 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14248 collectLoopStmts(AStmt, LoopStmts);
14249
14250 SmallVector<Stmt *, 4> PreInits;
14251 CaptureVars CopyTransformer(SemaRef);
14252
14253 // Create iteration variables for the generated loops.
14254 SmallVector<VarDecl *, 4> FloorIndVars;
14255 SmallVector<VarDecl *, 4> TileIndVars;
14256 FloorIndVars.resize(NumLoops);
14257 TileIndVars.resize(NumLoops);
14258 for (unsigned I = 0; I < NumLoops; ++I) {
14259 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14260
14261 assert(LoopHelper.Counters.size() == 1 &&
14262 "Expect single-dimensional loop iteration space");
14263 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14264 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14265 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14266 QualType CntTy = IterVarRef->getType();
14267
14268 // Iteration variable for the floor (i.e. outer) loop.
14269 {
14270 std::string FloorCntName =
14271 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14272 VarDecl *FloorCntDecl =
14273 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14274 FloorIndVars[I] = FloorCntDecl;
14275 }
14276
14277 // Iteration variable for the tile (i.e. inner) loop.
14278 {
14279 std::string TileCntName =
14280 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14281
14282 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14283 // used by the expressions to derive the original iteration variable's
14284 // value from the logical iteration number.
14285 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14286 TileCntDecl->setDeclName(
14287 &SemaRef.PP.getIdentifierTable().get(TileCntName));
14288 TileIndVars[I] = TileCntDecl;
14289 }
14290
14291 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
14292 PreInits);
14293 }
14294
14295 // Once the original iteration values are set, append the innermost body.
14296 Stmt *Inner = Body;
14297
14298 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
14299 SizesClause, CurScope](int I) -> Expr * {
14300 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14301 if (isa<ConstantExpr>(DimTileSizeExpr))
14302 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14303
14304 // When the tile size is not a constant but a variable, it is possible to
14305 // pass non-positive numbers. For instance:
14306 // \code{c}
14307 // int a = 0;
14308 // #pragma omp tile sizes(a)
14309 // for (int i = 0; i < 42; ++i)
14310 // body(i);
14311 // \endcode
14312 // Although there is no meaningful interpretation of the tile size, the body
14313 // should still be executed 42 times to avoid surprises. To preserve the
14314 // invariant that every loop iteration is executed exactly once and not
14315 // cause an infinite loop, apply a minimum tile size of one.
14316 // Build expr:
14317 // \code{c}
14318 // (TS <= 0) ? 1 : TS
14319 // \endcode
14320 QualType DimTy = DimTileSizeExpr->getType();
14321 uint64_t DimWidth = Context.getTypeSize(DimTy);
14323 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14324 IntegerLiteral *One =
14325 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
14327 CurScope, {}, BO_LE,
14328 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
14329 Expr *MinOne = new (Context) ConditionalOperator(
14330 Cond, {}, One, {},
14331 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14333 return MinOne;
14334 };
14335
14336 // Create tile loops from the inside to the outside.
14337 for (int I = NumLoops - 1; I >= 0; --I) {
14338 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14339 Expr *NumIterations = LoopHelper.NumIterations;
14340 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14341 QualType IVTy = NumIterations->getType();
14342 Stmt *LoopStmt = LoopStmts[I];
14343
14344 // Commonly used variables. One of the constraints of an AST is that every
14345 // node object must appear at most once, hence we define lamdas that create
14346 // a new AST node at every use.
14347 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
14348 OrigCntVar]() {
14349 return buildDeclRefExpr(SemaRef, TileIndVars[I], IVTy,
14350 OrigCntVar->getExprLoc());
14351 };
14352 auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, IVTy,
14353 OrigCntVar]() {
14354 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14355 OrigCntVar->getExprLoc());
14356 };
14357
14358 // For init-statement: auto .tile.iv = .floor.iv
14360 TileIndVars[I], SemaRef.DefaultLvalueConversion(MakeFloorIVRef()).get(),
14361 /*DirectInit=*/false);
14362 Decl *CounterDecl = TileIndVars[I];
14363 StmtResult InitStmt = new (Context)
14364 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14365 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14366 if (!InitStmt.isUsable())
14367 return StmtError();
14368
14369 // For cond-expression:
14370 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
14371 ExprResult EndOfTile =
14372 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14373 MakeFloorIVRef(), MakeDimTileSize(I));
14374 if (!EndOfTile.isUsable())
14375 return StmtError();
14376 ExprResult IsPartialTile =
14377 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14378 NumIterations, EndOfTile.get());
14379 if (!IsPartialTile.isUsable())
14380 return StmtError();
14381 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
14382 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14383 IsPartialTile.get(), NumIterations, EndOfTile.get());
14384 if (!MinTileAndIterSpace.isUsable())
14385 return StmtError();
14386 ExprResult CondExpr =
14387 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14388 MakeTileIVRef(), MinTileAndIterSpace.get());
14389 if (!CondExpr.isUsable())
14390 return StmtError();
14391
14392 // For incr-statement: ++.tile.iv
14393 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14394 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
14395 if (!IncrStmt.isUsable())
14396 return StmtError();
14397
14398 // Statements to set the original iteration variable's value from the
14399 // logical iteration number.
14400 // Generated for loop is:
14401 // \code
14402 // Original_for_init;
14403 // for (auto .tile.iv = .floor.iv;
14404 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
14405 // ++.tile.iv) {
14406 // Original_Body;
14407 // Original_counter_update;
14408 // }
14409 // \endcode
14410 // FIXME: If the innermost body is an loop itself, inserting these
14411 // statements stops it being recognized as a perfectly nested loop (e.g.
14412 // for applying tiling again). If this is the case, sink the expressions
14413 // further into the inner loop.
14414 SmallVector<Stmt *, 4> BodyParts;
14415 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14416 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14417 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14418 BodyParts.push_back(Inner);
14419 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
14420 Inner->getBeginLoc(), Inner->getEndLoc());
14421 Inner = new (Context)
14422 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14423 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14424 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14425 }
14426
14427 // Create floor loops from the inside to the outside.
14428 for (int I = NumLoops - 1; I >= 0; --I) {
14429 auto &LoopHelper = LoopHelpers[I];
14430 Expr *NumIterations = LoopHelper.NumIterations;
14431 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14432 QualType IVTy = NumIterations->getType();
14433
14434 // Commonly used variables. One of the constraints of an AST is that every
14435 // node object must appear at most once, hence we define lamdas that create
14436 // a new AST node at every use.
14437 auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, IVTy,
14438 OrigCntVar]() {
14439 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14440 OrigCntVar->getExprLoc());
14441 };
14442
14443 // For init-statement: auto .floor.iv = 0
14445 FloorIndVars[I],
14446 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14447 /*DirectInit=*/false);
14448 Decl *CounterDecl = FloorIndVars[I];
14449 StmtResult InitStmt = new (Context)
14450 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14451 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14452 if (!InitStmt.isUsable())
14453 return StmtError();
14454
14455 // For cond-expression: .floor.iv < NumIterations
14456 ExprResult CondExpr =
14457 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14458 MakeFloorIVRef(), NumIterations);
14459 if (!CondExpr.isUsable())
14460 return StmtError();
14461
14462 // For incr-statement: .floor.iv += DimTileSize
14463 ExprResult IncrStmt =
14464 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
14465 MakeFloorIVRef(), MakeDimTileSize(I));
14466 if (!IncrStmt.isUsable())
14467 return StmtError();
14468
14469 Inner = new (Context)
14470 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14471 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14472 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14473 }
14474
14475 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
14476 AStmt, Inner,
14477 buildPreInits(Context, PreInits));
14478}
14479
14481 Stmt *AStmt,
14482 SourceLocation StartLoc,
14483 SourceLocation EndLoc) {
14484 ASTContext &Context = getASTContext();
14485 Scope *CurScope = SemaRef.getCurScope();
14486 // Empty statement should only be possible if there already was an error.
14487 if (!AStmt)
14488 return StmtError();
14489
14491 {OMPC_partial, OMPC_full}))
14492 return StmtError();
14493
14494 const OMPFullClause *FullClause =
14495 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
14496 const OMPPartialClause *PartialClause =
14497 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
14498 assert(!(FullClause && PartialClause) &&
14499 "mutual exclusivity must have been checked before");
14500
14501 constexpr unsigned NumLoops = 1;
14502 Stmt *Body = nullptr;
14504 NumLoops);
14505 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
14506 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
14507 Body, OriginalInits))
14508 return StmtError();
14509
14510 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
14511
14512 // Delay unrolling to when template is completely instantiated.
14514 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14515 NumGeneratedLoops, nullptr, nullptr);
14516
14517 assert(LoopHelpers.size() == NumLoops &&
14518 "Expecting a single-dimensional loop iteration space");
14519 assert(OriginalInits.size() == NumLoops &&
14520 "Expecting a single-dimensional loop iteration space");
14521 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
14522
14523 if (FullClause) {
14525 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
14526 /*SuppressExprDiags=*/true)
14527 .isUsable()) {
14528 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
14529 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
14530 << "#pragma omp unroll full";
14531 return StmtError();
14532 }
14533 }
14534
14535 // The generated loop may only be passed to other loop-associated directive
14536 // when a partial clause is specified. Without the requirement it is
14537 // sufficient to generate loop unroll metadata at code-generation.
14538 if (NumGeneratedLoops == 0)
14539 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14540 NumGeneratedLoops, nullptr, nullptr);
14541
14542 // Otherwise, we need to provide a de-sugared/transformed AST that can be
14543 // associated with another loop directive.
14544 //
14545 // The canonical loop analysis return by checkTransformableLoopNest assumes
14546 // the following structure to be the same loop without transformations or
14547 // directives applied: \code OriginalInits; LoopHelper.PreInits;
14548 // LoopHelper.Counters;
14549 // for (; IV < LoopHelper.NumIterations; ++IV) {
14550 // LoopHelper.Updates;
14551 // Body;
14552 // }
14553 // \endcode
14554 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
14555 // and referenced by LoopHelper.IterationVarRef.
14556 //
14557 // The unrolling directive transforms this into the following loop:
14558 // \code
14559 // OriginalInits; \
14560 // LoopHelper.PreInits; > NewPreInits
14561 // LoopHelper.Counters; /
14562 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
14563 // #pragma clang loop unroll_count(Factor)
14564 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
14565 // {
14566 // LoopHelper.Updates;
14567 // Body;
14568 // }
14569 // }
14570 // \endcode
14571 // where UIV is a new logical iteration counter. IV must be the same VarDecl
14572 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
14573 // references it. If the partially unrolled loop is associated with another
14574 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
14575 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
14576 // OpenMP canonical loop. The inner loop is not an associable canonical loop
14577 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
14578 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
14579 // property of the OMPLoopBasedDirective instead of statements in
14580 // CompoundStatement. This is to allow the loop to become a non-outermost loop
14581 // of a canonical loop nest where these PreInits are emitted before the
14582 // outermost directive.
14583
14584 // Find the loop statement.
14585 Stmt *LoopStmt = nullptr;
14586 collectLoopStmts(AStmt, {LoopStmt});
14587
14588 // Determine the PreInit declarations.
14589 SmallVector<Stmt *, 4> PreInits;
14590 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14591
14592 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14593 QualType IVTy = IterationVarRef->getType();
14594 assert(LoopHelper.Counters.size() == 1 &&
14595 "Expecting a single-dimensional loop iteration space");
14596 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14597
14598 // Determine the unroll factor.
14599 uint64_t Factor;
14600 SourceLocation FactorLoc;
14601 if (Expr *FactorVal = PartialClause->getFactor()) {
14602 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
14603 FactorLoc = FactorVal->getExprLoc();
14604 } else {
14605 // TODO: Use a better profitability model.
14606 Factor = 2;
14607 }
14608 assert(Factor > 0 && "Expected positive unroll factor");
14609 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
14611 getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor),
14612 IVTy, FactorLoc);
14613 };
14614
14615 // Iteration variable SourceLocations.
14616 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
14617 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
14618 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
14619
14620 // Internal variable names.
14621 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14622 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
14623 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
14624 std::string InnerTripCountName =
14625 (Twine(".unroll_inner.tripcount.") + OrigVarName).str();
14626
14627 // Create the iteration variable for the unrolled loop.
14628 VarDecl *OuterIVDecl =
14629 buildVarDecl(SemaRef, {}, IVTy, OuterIVName, nullptr, OrigVar);
14630 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
14631 return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc);
14632 };
14633
14634 // Iteration variable for the inner loop: Reuse the iteration variable created
14635 // by checkOpenMPLoop.
14636 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14637 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(InnerIVName));
14638 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
14639 return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc);
14640 };
14641
14642 // Make a copy of the NumIterations expression for each use: By the AST
14643 // constraints, every expression object in a DeclContext must be unique.
14644 CaptureVars CopyTransformer(SemaRef);
14645 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
14646 return AssertSuccess(
14647 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
14648 };
14649
14650 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
14651 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(MakeOuterRef());
14652 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(),
14653 /*DirectInit=*/false);
14654 StmtResult InnerInit = new (Context)
14655 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14656 if (!InnerInit.isUsable())
14657 return StmtError();
14658
14659 // Inner For cond-expression:
14660 // \code
14661 // .unroll_inner.iv < .unrolled.iv + Factor &&
14662 // .unroll_inner.iv < NumIterations
14663 // \endcode
14664 // This conjunction of two conditions allows ScalarEvolution to derive the
14665 // maximum trip count of the inner loop.
14666 ExprResult EndOfTile =
14667 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14668 MakeOuterRef(), MakeFactorExpr());
14669 if (!EndOfTile.isUsable())
14670 return StmtError();
14671 ExprResult InnerCond1 =
14672 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14673 MakeInnerRef(), EndOfTile.get());
14674 if (!InnerCond1.isUsable())
14675 return StmtError();
14676 ExprResult InnerCond2 =
14677 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14678 MakeInnerRef(), MakeNumIterations());
14679 if (!InnerCond2.isUsable())
14680 return StmtError();
14681 ExprResult InnerCond =
14682 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
14683 InnerCond1.get(), InnerCond2.get());
14684 if (!InnerCond.isUsable())
14685 return StmtError();
14686
14687 // Inner For incr-statement: ++.unroll_inner.iv
14688 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
14689 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
14690 if (!InnerIncr.isUsable())
14691 return StmtError();
14692
14693 // Inner For statement.
14694 SmallVector<Stmt *> InnerBodyStmts;
14695 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14696 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14697 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
14698 InnerBodyStmts.push_back(Body);
14699 CompoundStmt *InnerBody =
14701 Body->getBeginLoc(), Body->getEndLoc());
14702 ForStmt *InnerFor = new (Context)
14703 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
14704 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
14705 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14706
14707 // Unroll metadata for the inner loop.
14708 // This needs to take into account the remainder portion of the unrolled loop,
14709 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
14710 // supports multiple loop exits. Instead, unroll using a factor equivalent to
14711 // the maximum trip count, which will also generate a remainder loop. Just
14712 // `unroll(enable)` (which could have been useful if the user has not
14713 // specified a concrete factor; even though the outer loop cannot be
14714 // influenced anymore, would avoid more code bloat than necessary) will refuse
14715 // the loop because "Won't unroll; remainder loop could not be generated when
14716 // assuming runtime trip count". Even if it did work, it must not choose a
14717 // larger unroll factor than the maximum loop length, or it would always just
14718 // execute the remainder loop.
14719 LoopHintAttr *UnrollHintAttr =
14720 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
14721 LoopHintAttr::Numeric, MakeFactorExpr());
14722 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
14723 getASTContext(), StartLoc, {UnrollHintAttr}, InnerFor);
14724
14725 // Outer For init-statement: auto .unrolled.iv = 0
14727 OuterIVDecl,
14728 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14729 /*DirectInit=*/false);
14730 StmtResult OuterInit = new (Context)
14731 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14732 if (!OuterInit.isUsable())
14733 return StmtError();
14734
14735 // Outer For cond-expression: .unrolled.iv < NumIterations
14736 ExprResult OuterConde =
14737 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14738 MakeOuterRef(), MakeNumIterations());
14739 if (!OuterConde.isUsable())
14740 return StmtError();
14741
14742 // Outer For incr-statement: .unrolled.iv += Factor
14743 ExprResult OuterIncr =
14744 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
14745 MakeOuterRef(), MakeFactorExpr());
14746 if (!OuterIncr.isUsable())
14747 return StmtError();
14748
14749 // Outer For statement.
14750 ForStmt *OuterFor = new (Context)
14751 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
14752 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
14753 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14754
14755 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14756 NumGeneratedLoops, OuterFor,
14757 buildPreInits(Context, PreInits));
14758}
14759
14761 SourceLocation StartLoc,
14762 SourceLocation EndLoc) {
14763 ASTContext &Context = getASTContext();
14764 Scope *CurScope = SemaRef.getCurScope();
14765
14766 // Empty statement should only be possible if there already was an error.
14767 if (!AStmt)
14768 return StmtError();
14769
14770 constexpr unsigned NumLoops = 1;
14771 Stmt *Body = nullptr;
14773 NumLoops);
14774 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
14775 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
14776 Body, OriginalInits))
14777 return StmtError();
14778
14779 // Delay applying the transformation to when template is completely
14780 // instantiated.
14782 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
14783 nullptr, nullptr);
14784
14785 assert(LoopHelpers.size() == NumLoops &&
14786 "Expecting a single-dimensional loop iteration space");
14787 assert(OriginalInits.size() == NumLoops &&
14788 "Expecting a single-dimensional loop iteration space");
14789 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
14790
14791 // Find the loop statement.
14792 Stmt *LoopStmt = nullptr;
14793 collectLoopStmts(AStmt, {LoopStmt});
14794
14795 // Determine the PreInit declarations.
14796 SmallVector<Stmt *> PreInits;
14797 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14798
14799 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14800 QualType IVTy = IterationVarRef->getType();
14801 uint64_t IVWidth = Context.getTypeSize(IVTy);
14802 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14803
14804 // Iteration variable SourceLocations.
14805 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
14806 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
14807 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
14808
14809 // Locations pointing to the transformation.
14810 SourceLocation TransformLoc = StartLoc;
14811 SourceLocation TransformLocBegin = StartLoc;
14812 SourceLocation TransformLocEnd = EndLoc;
14813
14814 // Internal variable names.
14815 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14816 SmallString<64> ForwardIVName(".forward.iv.");
14817 ForwardIVName += OrigVarName;
14818 SmallString<64> ReversedIVName(".reversed.iv.");
14819 ReversedIVName += OrigVarName;
14820
14821 // LoopHelper.Updates will read the logical iteration number from
14822 // LoopHelper.IterationVarRef, compute the value of the user loop counter of
14823 // that logical iteration from it, then assign it to the user loop counter
14824 // variable. We cannot directly use LoopHelper.IterationVarRef as the
14825 // induction variable of the generated loop because it may cause an underflow:
14826 // \code{.c}
14827 // for (unsigned i = 0; i < n; ++i)
14828 // body(i);
14829 // \endcode
14830 //
14831 // Naive reversal:
14832 // \code{.c}
14833 // for (unsigned i = n-1; i >= 0; --i)
14834 // body(i);
14835 // \endcode
14836 //
14837 // Instead, we introduce a new iteration variable representing the logical
14838 // iteration counter of the original loop, convert it to the logical iteration
14839 // number of the reversed loop, then let LoopHelper.Updates compute the user's
14840 // loop iteration variable from it.
14841 // \code{.cpp}
14842 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
14843 // auto .reversed.iv = n - .forward.iv - 1;
14844 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates
14845 // body(i); // Body
14846 // }
14847 // \endcode
14848
14849 // Subexpressions with more than one use. One of the constraints of an AST is
14850 // that every node object must appear at most once, hence we define a lambda
14851 // that creates a new AST node at every use.
14852 CaptureVars CopyTransformer(SemaRef);
14853 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
14854 return AssertSuccess(
14855 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
14856 };
14857
14858 // Create the iteration variable for the forward loop (from 0 to n-1).
14859 VarDecl *ForwardIVDecl =
14860 buildVarDecl(SemaRef, {}, IVTy, ForwardIVName, nullptr, OrigVar);
14861 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
14862 OrigVarLoc]() {
14863 return buildDeclRefExpr(SemaRef, ForwardIVDecl, IVTy, OrigVarLoc);
14864 };
14865
14866 // Iteration variable for the reversed induction variable (from n-1 downto 0):
14867 // Reuse the iteration variable created by checkOpenMPLoop.
14868 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14869 ReversedIVDecl->setDeclName(
14870 &SemaRef.PP.getIdentifierTable().get(ReversedIVName));
14871
14872 // For init-statement:
14873 // \code{.cpp}
14874 // auto .forward.iv = 0;
14875 // \endcode
14876 auto *Zero = IntegerLiteral::Create(Context, llvm::APInt::getZero(IVWidth),
14877 ForwardIVDecl->getType(), OrigVarLoc);
14878 SemaRef.AddInitializerToDecl(ForwardIVDecl, Zero, /*DirectInit=*/false);
14879 StmtResult Init = new (Context)
14880 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14881 if (!Init.isUsable())
14882 return StmtError();
14883
14884 // Forward iv cond-expression:
14885 // \code{.cpp}
14886 // .forward.iv < MakeNumIterations()
14887 // \endcode
14888 ExprResult Cond =
14889 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14890 MakeForwardRef(), MakeNumIterations());
14891 if (!Cond.isUsable())
14892 return StmtError();
14893
14894 // Forward incr-statement:
14895 // \code{.c}
14896 // ++.forward.iv
14897 // \endcode
14898 ExprResult Incr = SemaRef.BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
14899 UO_PreInc, MakeForwardRef());
14900 if (!Incr.isUsable())
14901 return StmtError();
14902
14903 // Reverse the forward-iv:
14904 // \code{.cpp}
14905 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
14906 // \endcode
14907 auto *One = IntegerLiteral::Create(Context, llvm::APInt(IVWidth, 1), IVTy,
14908 TransformLoc);
14909 ExprResult Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub,
14910 MakeNumIterations(), One);
14911 if (!Minus.isUsable())
14912 return StmtError();
14913 Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.get(),
14914 MakeForwardRef());
14915 if (!Minus.isUsable())
14916 return StmtError();
14917 StmtResult InitReversed = new (Context) DeclStmt(
14918 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
14919 if (!InitReversed.isUsable())
14920 return StmtError();
14921 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.get(),
14922 /*DirectInit=*/false);
14923
14924 // The new loop body.
14925 SmallVector<Stmt *, 4> BodyStmts;
14926 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
14927 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
14928 BodyStmts.push_back(InitReversed.get());
14929 llvm::append_range(BodyStmts, LoopHelper.Updates);
14930 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14931 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
14932 BodyStmts.push_back(Body);
14933 auto *ReversedBody =
14934 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
14935 Body->getBeginLoc(), Body->getEndLoc());
14936
14937 // Finally create the reversed For-statement.
14938 auto *ReversedFor = new (Context)
14939 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
14940 ReversedBody, LoopHelper.Init->getBeginLoc(),
14941 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14942 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
14943 ReversedFor,
14944 buildPreInits(Context, PreInits));
14945}
14946
14948 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14949 SourceLocation EndLoc) {
14950 ASTContext &Context = getASTContext();
14951 DeclContext *CurContext = SemaRef.CurContext;
14952 Scope *CurScope = SemaRef.getCurScope();
14953
14954 // Empty statement should only be possible if there already was an error.
14955 if (!AStmt)
14956 return StmtError();
14957
14958 // interchange without permutation clause swaps two loops.
14959 const OMPPermutationClause *PermutationClause =
14960 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
14961 size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2;
14962
14963 // Verify and diagnose loop nest.
14965 Stmt *Body = nullptr;
14966 SmallVector<SmallVector<Stmt *, 0>, 2> OriginalInits;
14967 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
14968 LoopHelpers, Body, OriginalInits))
14969 return StmtError();
14970
14971 // Delay interchange to when template is completely instantiated.
14972 if (CurContext->isDependentContext())
14973 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
14974 NumLoops, AStmt, nullptr, nullptr);
14975
14976 // An invalid expression in the permutation clause is set to nullptr in
14977 // ActOnOpenMPPermutationClause.
14978 if (PermutationClause &&
14979 llvm::is_contained(PermutationClause->getArgsRefs(), nullptr))
14980 return StmtError();
14981
14982 assert(LoopHelpers.size() == NumLoops &&
14983 "Expecting loop iteration space dimensionaly to match number of "
14984 "affected loops");
14985 assert(OriginalInits.size() == NumLoops &&
14986 "Expecting loop iteration space dimensionaly to match number of "
14987 "affected loops");
14988
14989 // Decode the permutation clause.
14990 SmallVector<uint64_t, 2> Permutation;
14991 if (!PermutationClause) {
14992 Permutation = {1, 0};
14993 } else {
14994 ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs();
14995 llvm::BitVector Flags(PermArgs.size());
14996 for (Expr *PermArg : PermArgs) {
14997 std::optional<llvm::APSInt> PermCstExpr =
14998 PermArg->getIntegerConstantExpr(Context);
14999 if (!PermCstExpr)
15000 continue;
15001 uint64_t PermInt = PermCstExpr->getZExtValue();
15002 assert(1 <= PermInt && PermInt <= NumLoops &&
15003 "Must be a permutation; diagnostic emitted in "
15004 "ActOnOpenMPPermutationClause");
15005 if (Flags[PermInt - 1]) {
15006 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
15007 Diag(PermArg->getExprLoc(),
15008 diag::err_omp_interchange_permutation_value_repeated)
15009 << PermInt << ExprRange;
15010 continue;
15011 }
15012 Flags[PermInt - 1] = true;
15013
15014 Permutation.push_back(PermInt - 1);
15015 }
15016
15017 if (Permutation.size() != NumLoops)
15018 return StmtError();
15019 }
15020
15021 // Nothing to transform with trivial permutation.
15022 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](auto P) {
15023 auto [Idx, Arg] = P;
15024 return Idx == Arg;
15025 }))
15026 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15027 NumLoops, AStmt, AStmt, nullptr);
15028
15029 // Find the affected loops.
15030 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15031 collectLoopStmts(AStmt, LoopStmts);
15032
15033 // Collect pre-init statements on the order before the permuation.
15034 SmallVector<Stmt *> PreInits;
15035 for (auto I : llvm::seq<int>(NumLoops)) {
15036 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15037
15038 assert(LoopHelper.Counters.size() == 1 &&
15039 "Single-dimensional loop iteration space expected");
15040 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15041
15042 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15043 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
15044 PreInits);
15045 }
15046
15047 SmallVector<VarDecl *> PermutedIndVars(NumLoops);
15048 CaptureVars CopyTransformer(SemaRef);
15049
15050 // Create the permuted loops from the inside to the outside of the
15051 // interchanged loop nest. Body of the innermost new loop is the original
15052 // innermost body.
15053 Stmt *Inner = Body;
15054 for (auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
15055 // Get the original loop that belongs to this new position.
15056 uint64_t SourceIdx = Permutation[TargetIdx];
15057 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
15058 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15059 assert(SourceHelper.Counters.size() == 1 &&
15060 "Single-dimensional loop iteration space expected");
15061 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.Counters.front());
15062
15063 // Normalized loop counter variable: From 0 to n-1, always an integer type.
15064 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(SourceHelper.IterationVarRef);
15065 QualType IVTy = IterVarRef->getType();
15066 assert(IVTy->isIntegerType() &&
15067 "Expected the logical iteration counter to be an integer");
15068
15069 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15070 SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
15071
15072 // Make a copy of the NumIterations expression for each use: By the AST
15073 // constraints, every expression object in a DeclContext must be unique.
15074 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
15075 return AssertSuccess(
15076 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
15077 };
15078
15079 // Iteration variable for the permuted loop. Reuse the one from
15080 // checkOpenMPLoop which will also be used to update the original loop
15081 // variable.
15082 SmallString<64> PermutedCntName(".permuted_");
15083 PermutedCntName.append({llvm::utostr(TargetIdx), ".iv.", OrigVarName});
15084 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15085 PermutedCntDecl->setDeclName(
15086 &SemaRef.PP.getIdentifierTable().get(PermutedCntName));
15087 PermutedIndVars[TargetIdx] = PermutedCntDecl;
15088 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
15089 return buildDeclRefExpr(SemaRef, PermutedCntDecl, IVTy, OrigVarLoc);
15090 };
15091
15092 // For init-statement:
15093 // \code
15094 // auto .permuted_{target}.iv = 0
15095 // \endcode
15096 ExprResult Zero = SemaRef.ActOnIntegerConstant(OrigVarLoc, 0);
15097 if (!Zero.isUsable())
15098 return StmtError();
15099 SemaRef.AddInitializerToDecl(PermutedCntDecl, Zero.get(),
15100 /*DirectInit=*/false);
15101 StmtResult InitStmt = new (Context)
15102 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
15103 OrigCntVar->getEndLoc());
15104 if (!InitStmt.isUsable())
15105 return StmtError();
15106
15107 // For cond-expression:
15108 // \code
15109 // .permuted_{target}.iv < MakeNumIterations()
15110 // \endcode
15111 ExprResult CondExpr =
15112 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
15113 MakePermutedRef(), MakeNumIterations());
15114 if (!CondExpr.isUsable())
15115 return StmtError();
15116
15117 // For incr-statement:
15118 // \code
15119 // ++.tile.iv
15120 // \endcode
15121 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15122 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
15123 if (!IncrStmt.isUsable())
15124 return StmtError();
15125
15126 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
15127 SourceHelper.Updates.end());
15128 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
15129 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15130 BodyParts.push_back(Inner);
15131 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15132 Inner->getBeginLoc(), Inner->getEndLoc());
15133 Inner = new (Context) ForStmt(
15134 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
15135 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
15136 SourceHelper.Inc->getEndLoc());
15137 }
15138
15139 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15140 NumLoops, AStmt, Inner,
15141 buildPreInits(Context, PreInits));
15142}
15143
15145 Expr *Expr,
15146 SourceLocation StartLoc,
15147 SourceLocation LParenLoc,
15148 SourceLocation EndLoc) {
15149 OMPClause *Res = nullptr;
15150 switch (Kind) {
15151 case OMPC_final:
15152 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
15153 break;
15154 case OMPC_num_threads:
15155 Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
15156 break;
15157 case OMPC_safelen:
15158 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
15159 break;
15160 case OMPC_simdlen:
15161 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
15162 break;
15163 case OMPC_allocator:
15164 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
15165 break;
15166 case OMPC_collapse:
15167 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
15168 break;
15169 case OMPC_ordered:
15170 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
15171 break;
15172 case OMPC_priority:
15173 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
15174 break;
15175 case OMPC_hint:
15176 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
15177 break;
15178 case OMPC_depobj:
15179 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
15180 break;
15181 case OMPC_detach:
15182 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
15183 break;
15184 case OMPC_novariants:
15185 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
15186 break;
15187 case OMPC_nocontext:
15188 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
15189 break;
15190 case OMPC_filter:
15191 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
15192 break;
15193 case OMPC_partial:
15194 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
15195 break;
15196 case OMPC_message:
15197 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
15198 break;
15199 case OMPC_align:
15200 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
15201 break;
15202 case OMPC_ompx_dyn_cgroup_mem:
15203 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
15204 break;
15205 case OMPC_holds:
15206 Res = ActOnOpenMPHoldsClause(Expr, StartLoc, LParenLoc, EndLoc);
15207 break;
15208 case OMPC_grainsize:
15209 case OMPC_num_tasks:
15210 case OMPC_device:
15211 case OMPC_if:
15212 case OMPC_default:
15213 case OMPC_proc_bind:
15214 case OMPC_schedule:
15215 case OMPC_private:
15216 case OMPC_firstprivate:
15217 case OMPC_lastprivate:
15218 case OMPC_shared:
15219 case OMPC_reduction:
15220 case OMPC_task_reduction:
15221 case OMPC_in_reduction:
15222 case OMPC_linear:
15223 case OMPC_aligned:
15224 case OMPC_copyin:
15225 case OMPC_copyprivate:
15226 case OMPC_nowait:
15227 case OMPC_untied:
15228 case OMPC_mergeable:
15229 case OMPC_threadprivate:
15230 case OMPC_sizes:
15231 case OMPC_allocate:
15232 case OMPC_flush:
15233 case OMPC_read:
15234 case OMPC_write:
15235 case OMPC_update:
15236 case OMPC_capture:
15237 case OMPC_compare:
15238 case OMPC_seq_cst:
15239 case OMPC_acq_rel:
15240 case OMPC_acquire:
15241 case OMPC_release:
15242 case OMPC_relaxed:
15243 case OMPC_depend:
15244 case OMPC_threads:
15245 case OMPC_simd:
15246 case OMPC_map:
15247 case OMPC_nogroup:
15248 case OMPC_dist_schedule:
15249 case OMPC_defaultmap:
15250 case OMPC_unknown:
15251 case OMPC_uniform:
15252 case OMPC_to:
15253 case OMPC_from:
15254 case OMPC_use_device_ptr:
15255 case OMPC_use_device_addr:
15256 case OMPC_is_device_ptr:
15257 case OMPC_unified_address:
15258 case OMPC_unified_shared_memory:
15259 case OMPC_reverse_offload:
15260 case OMPC_dynamic_allocators:
15261 case OMPC_atomic_default_mem_order:
15262 case OMPC_device_type:
15263 case OMPC_match:
15264 case OMPC_nontemporal:
15265 case OMPC_order:
15266 case OMPC_at:
15267 case OMPC_severity:
15268 case OMPC_destroy:
15269 case OMPC_inclusive:
15270 case OMPC_exclusive:
15271 case OMPC_uses_allocators:
15272 case OMPC_affinity:
15273 case OMPC_when:
15274 case OMPC_bind:
15275 case OMPC_num_teams:
15276 case OMPC_thread_limit:
15277 default:
15278 llvm_unreachable("Clause is not allowed.");
15279 }
15280 return Res;
15281}
15282
15283// An OpenMP directive such as 'target parallel' has two captured regions:
15284// for the 'target' and 'parallel' respectively. This function returns
15285// the region in which to capture expressions associated with a clause.
15286// A return value of OMPD_unknown signifies that the expression should not
15287// be captured.
15289 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15290 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15291 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
15292 "Invalid directive with CKind-clause");
15293
15294 // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
15295 if (NameModifier != OMPD_unknown &&
15296 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
15297 return OMPD_unknown;
15298
15299 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(DKind);
15300
15301 // [5.2:341:24-30]
15302 // If the clauses have expressions on them, such as for various clauses where
15303 // the argument of the clause is an expression, or lower-bound, length, or
15304 // stride expressions inside array sections (or subscript and stride
15305 // expressions in subscript-triplet for Fortran), or linear-step or alignment
15306 // expressions, the expressions are evaluated immediately before the construct
15307 // to which the clause has been split or duplicated per the above rules
15308 // (therefore inside of the outer leaf constructs). However, the expressions
15309 // inside the num_teams and thread_limit clauses are always evaluated before
15310 // the outermost leaf construct.
15311
15312 // Process special cases first.
15313 switch (CKind) {
15314 case OMPC_if:
15315 switch (DKind) {
15316 case OMPD_teams_loop:
15317 case OMPD_target_teams_loop:
15318 // For [target] teams loop, assume capture region is 'teams' so it's
15319 // available for codegen later to use if/when necessary.
15320 return OMPD_teams;
15321 case OMPD_target_update:
15322 case OMPD_target_enter_data:
15323 case OMPD_target_exit_data:
15324 return OMPD_task;
15325 default:
15326 break;
15327 }
15328 break;
15329 case OMPC_num_teams:
15330 case OMPC_thread_limit:
15331 case OMPC_ompx_dyn_cgroup_mem:
15332 if (Leafs[0] == OMPD_target)
15333 return OMPD_target;
15334 break;
15335 case OMPC_device:
15336 if (Leafs[0] == OMPD_target ||
15337 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
15338 OMPD_target_enter_data, OMPD_target_exit_data},
15339 DKind))
15340 return OMPD_task;
15341 break;
15342 case OMPC_novariants:
15343 case OMPC_nocontext:
15344 if (DKind == OMPD_dispatch)
15345 return OMPD_task;
15346 break;
15347 case OMPC_when:
15348 if (DKind == OMPD_metadirective)
15349 return OMPD_metadirective;
15350 break;
15351 case OMPC_filter:
15352 return OMPD_unknown;
15353 default:
15354 break;
15355 }
15356
15357 // If none of the special cases above applied, and DKind is a capturing
15358 // directive, find the innermost enclosing leaf construct that allows the
15359 // clause, and returns the corresponding capture region.
15360
15361 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
15362 // Find the index in "Leafs" of the last leaf that allows the given
15363 // clause. The search will only include indexes [0, EndIdx).
15364 // EndIdx may be set to the index of the NameModifier, if present.
15365 int InnermostIdx = [&]() {
15366 for (int I = EndIdx - 1; I >= 0; --I) {
15367 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
15368 return I;
15369 }
15370 return -1;
15371 }();
15372
15373 // Find the nearest enclosing capture region.
15375 for (int I = InnermostIdx - 1; I >= 0; --I) {
15376 if (!isOpenMPCapturingDirective(Leafs[I]))
15377 continue;
15378 Regions.clear();
15379 getOpenMPCaptureRegions(Regions, Leafs[I]);
15380 if (Regions[0] != OMPD_unknown)
15381 return Regions.back();
15382 }
15383 return OMPD_unknown;
15384 };
15385
15386 if (isOpenMPCapturingDirective(DKind)) {
15387 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
15388 for (int I = 0, E = Leafs.size(); I != E; ++I) {
15389 if (Leafs[I] == Dir)
15390 return I + 1;
15391 }
15392 return 0;
15393 };
15394
15395 int End = NameModifier == OMPD_unknown ? Leafs.size()
15396 : GetLeafIndex(NameModifier);
15397 return GetEnclosingRegion(End, CKind);
15398 }
15399
15400 return OMPD_unknown;
15401}
15402
15404 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
15405 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
15406 SourceLocation ColonLoc, SourceLocation EndLoc) {
15407 Expr *ValExpr = Condition;
15408 Stmt *HelperValStmt = nullptr;
15409 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15410 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
15411 !Condition->isInstantiationDependent() &&
15412 !Condition->containsUnexpandedParameterPack()) {
15414 if (Val.isInvalid())
15415 return nullptr;
15416
15417 ValExpr = Val.get();
15418
15419 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15420 CaptureRegion = getOpenMPCaptureRegionForClause(
15421 DKind, OMPC_if, getLangOpts().OpenMP, NameModifier);
15422 if (CaptureRegion != OMPD_unknown &&
15424 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15425 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15426 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15427 HelperValStmt = buildPreInits(getASTContext(), Captures);
15428 }
15429 }
15430
15431 return new (getASTContext())
15432 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
15433 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
15434}
15435
15437 SourceLocation StartLoc,
15438 SourceLocation LParenLoc,
15439 SourceLocation EndLoc) {
15440 Expr *ValExpr = Condition;
15441 Stmt *HelperValStmt = nullptr;
15442 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15443 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
15444 !Condition->isInstantiationDependent() &&
15445 !Condition->containsUnexpandedParameterPack()) {
15447 if (Val.isInvalid())
15448 return nullptr;
15449
15450 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
15451
15452 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15453 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final,
15454 getLangOpts().OpenMP);
15455 if (CaptureRegion != OMPD_unknown &&
15457 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15458 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15459 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15460 HelperValStmt = buildPreInits(getASTContext(), Captures);
15461 }
15462 }
15463
15464 return new (getASTContext()) OMPFinalClause(
15465 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15466}
15467
15470 Expr *Op) {
15471 if (!Op)
15472 return ExprError();
15473
15474 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
15475 public:
15476 IntConvertDiagnoser()
15477 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {}
15478 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
15479 QualType T) override {
15480 return S.Diag(Loc, diag::err_omp_not_integral) << T;
15481 }
15482 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
15483 QualType T) override {
15484 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
15485 }
15486 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
15487 QualType T,
15488 QualType ConvTy) override {
15489 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
15490 }
15491 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
15492 QualType ConvTy) override {
15493 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
15494 << ConvTy->isEnumeralType() << ConvTy;
15495 }
15496 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
15497 QualType T) override {
15498 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
15499 }
15500 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
15501 QualType ConvTy) override {
15502 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
15503 << ConvTy->isEnumeralType() << ConvTy;
15504 }
15505 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
15506 QualType) override {
15507 llvm_unreachable("conversion functions are permitted");
15508 }
15509 } ConvertDiagnoser;
15510 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
15511}
15512
15513static bool
15515 bool StrictlyPositive, bool BuildCapture = false,
15516 OpenMPDirectiveKind DKind = OMPD_unknown,
15517 OpenMPDirectiveKind *CaptureRegion = nullptr,
15518 Stmt **HelperValStmt = nullptr) {
15519 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
15520 !ValExpr->isInstantiationDependent()) {
15521 SourceLocation Loc = ValExpr->getExprLoc();
15524 if (Value.isInvalid())
15525 return false;
15526
15527 ValExpr = Value.get();
15528 // The expression must evaluate to a non-negative integer value.
15529 if (std::optional<llvm::APSInt> Result =
15530 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
15531 if (Result->isSigned() &&
15532 !((!StrictlyPositive && Result->isNonNegative()) ||
15533 (StrictlyPositive && Result->isStrictlyPositive()))) {
15534 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
15535 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
15536 << ValExpr->getSourceRange();
15537 return false;
15538 }
15539 }
15540 if (!BuildCapture)
15541 return true;
15542 *CaptureRegion =
15543 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
15544 if (*CaptureRegion != OMPD_unknown &&
15545 !SemaRef.CurContext->isDependentContext()) {
15546 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15547 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15548 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15549 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
15550 }
15551 }
15552 return true;
15553}
15554
15556 SourceLocation StartLoc,
15557 SourceLocation LParenLoc,
15558 SourceLocation EndLoc) {
15559 Expr *ValExpr = NumThreads;
15560 Stmt *HelperValStmt = nullptr;
15561
15562 // OpenMP [2.5, Restrictions]
15563 // The num_threads expression must evaluate to a positive integer value.
15564 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads,
15565 /*StrictlyPositive=*/true))
15566 return nullptr;
15567
15568 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15570 DKind, OMPC_num_threads, getLangOpts().OpenMP);
15571 if (CaptureRegion != OMPD_unknown &&
15573 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15574 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15575 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15576 HelperValStmt = buildPreInits(getASTContext(), Captures);
15577 }
15578
15579 return new (getASTContext()) OMPNumThreadsClause(
15580 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15581}
15582
15584 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
15585 bool SuppressExprDiags) {
15586 if (!E)
15587 return ExprError();
15588 if (E->isValueDependent() || E->isTypeDependent() ||
15590 return E;
15591
15592 llvm::APSInt Result;
15593 ExprResult ICE;
15594 if (SuppressExprDiags) {
15595 // Use a custom diagnoser that suppresses 'note' diagnostics about the
15596 // expression.
15597 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
15598 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
15600 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
15601 llvm_unreachable("Diagnostic suppressed");
15602 }
15603 } Diagnoser;
15606 } else {
15608 /*FIXME*/ Sema::AllowFold);
15609 }
15610 if (ICE.isInvalid())
15611 return ExprError();
15612
15613 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
15614 (!StrictlyPositive && !Result.isNonNegative())) {
15615 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
15616 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
15617 << E->getSourceRange();
15618 return ExprError();
15619 }
15620 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
15621 CKind == OMPC_allocate) &&
15622 !Result.isPowerOf2()) {
15623 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
15624 << E->getSourceRange();
15625 return ExprError();
15626 }
15627 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
15628 DSAStack->setAssociatedLoops(Result.getExtValue());
15629 else if (CKind == OMPC_ordered)
15630 DSAStack->setAssociatedLoops(Result.getExtValue());
15631 return ICE;
15632}
15633
15635 SourceLocation StartLoc,
15636 SourceLocation LParenLoc,
15637 SourceLocation EndLoc) {
15638 // OpenMP [2.8.1, simd construct, Description]
15639 // The parameter of the safelen clause must be a constant
15640 // positive integer expression.
15641 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
15642 if (Safelen.isInvalid())
15643 return nullptr;
15644 return new (getASTContext())
15645 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
15646}
15647
15649 SourceLocation StartLoc,
15650 SourceLocation LParenLoc,
15651 SourceLocation EndLoc) {
15652 // OpenMP [2.8.1, simd construct, Description]
15653 // The parameter of the simdlen clause must be a constant
15654 // positive integer expression.
15655 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
15656 if (Simdlen.isInvalid())
15657 return nullptr;
15658 return new (getASTContext())
15659 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
15660}
15661
15662/// Tries to find omp_allocator_handle_t type.
15664 DSAStackTy *Stack) {
15665 if (!Stack->getOMPAllocatorHandleT().isNull())
15666 return true;
15667
15668 // Set the allocator handle type.
15669 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
15670 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
15671 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
15672 S.Diag(Loc, diag::err_omp_implied_type_not_found)
15673 << "omp_allocator_handle_t";
15674 return false;
15675 }
15676 QualType AllocatorHandleEnumTy = PT.get();
15677 AllocatorHandleEnumTy.addConst();
15678 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
15679
15680 // Fill the predefined allocator map.
15681 bool ErrorFound = false;
15682 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
15683 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
15684 StringRef Allocator =
15685 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
15686 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
15687 auto *VD = dyn_cast_or_null<ValueDecl>(
15688 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
15689 if (!VD) {
15690 ErrorFound = true;
15691 break;
15692 }
15693 QualType AllocatorType =
15695 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
15696 if (!Res.isUsable()) {
15697 ErrorFound = true;
15698 break;
15699 }
15700 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
15702 /*AllowExplicit=*/true);
15703 if (!Res.isUsable()) {
15704 ErrorFound = true;
15705 break;
15706 }
15707 Stack->setAllocator(AllocatorKind, Res.get());
15708 }
15709 if (ErrorFound) {
15710 S.Diag(Loc, diag::err_omp_implied_type_not_found)
15711 << "omp_allocator_handle_t";
15712 return false;
15713 }
15714
15715 return true;
15716}
15717
15719 SourceLocation StartLoc,
15720 SourceLocation LParenLoc,
15721 SourceLocation EndLoc) {
15722 // OpenMP [2.11.3, allocate Directive, Description]
15723 // allocator is an expression of omp_allocator_handle_t type.
15725 return nullptr;
15726
15728 if (Allocator.isInvalid())
15729 return nullptr;
15731 Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
15733 /*AllowExplicit=*/true);
15734 if (Allocator.isInvalid())
15735 return nullptr;
15736 return new (getASTContext())
15737 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
15738}
15739
15741 SourceLocation StartLoc,
15742 SourceLocation LParenLoc,
15743 SourceLocation EndLoc) {
15744 // OpenMP [2.7.1, loop construct, Description]
15745 // OpenMP [2.8.1, simd construct, Description]
15746 // OpenMP [2.9.6, distribute construct, Description]
15747 // The parameter of the collapse clause must be a constant
15748 // positive integer expression.
15749 ExprResult NumForLoopsResult =
15750 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
15751 if (NumForLoopsResult.isInvalid())
15752 return nullptr;
15753 return new (getASTContext())
15754 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
15755}
15756
15758 SourceLocation EndLoc,
15759 SourceLocation LParenLoc,
15760 Expr *NumForLoops) {
15761 // OpenMP [2.7.1, loop construct, Description]
15762 // OpenMP [2.8.1, simd construct, Description]
15763 // OpenMP [2.9.6, distribute construct, Description]
15764 // The parameter of the ordered clause must be a constant
15765 // positive integer expression if any.
15766 if (NumForLoops && LParenLoc.isValid()) {
15767 ExprResult NumForLoopsResult =
15768 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
15769 if (NumForLoopsResult.isInvalid())
15770 return nullptr;
15771 NumForLoops = NumForLoopsResult.get();
15772 } else {
15773 NumForLoops = nullptr;
15774 }
15775 auto *Clause =
15777 NumForLoops ? DSAStack->getAssociatedLoops() : 0,
15778 StartLoc, LParenLoc, EndLoc);
15779 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
15780 return Clause;
15781}
15782
15784 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
15785 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
15786 OMPClause *Res = nullptr;
15787 switch (Kind) {
15788 case OMPC_default:
15789 Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument),
15790 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15791 break;
15792 case OMPC_proc_bind:
15793 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
15794 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15795 break;
15796 case OMPC_atomic_default_mem_order:
15798 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
15799 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15800 break;
15801 case OMPC_fail:
15802 Res = ActOnOpenMPFailClause(static_cast<OpenMPClauseKind>(Argument),
15803 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15804 break;
15805 case OMPC_update:
15806 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
15807 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15808 break;
15809 case OMPC_bind:
15810 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
15811 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15812 break;
15813 case OMPC_at:
15814 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
15815 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15816 break;
15817 case OMPC_severity:
15819 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
15820 LParenLoc, EndLoc);
15821 break;
15822 case OMPC_if:
15823 case OMPC_final:
15824 case OMPC_num_threads:
15825 case OMPC_safelen:
15826 case OMPC_simdlen:
15827 case OMPC_sizes:
15828 case OMPC_allocator:
15829 case OMPC_collapse:
15830 case OMPC_schedule:
15831 case OMPC_private:
15832 case OMPC_firstprivate:
15833 case OMPC_lastprivate:
15834 case OMPC_shared:
15835 case OMPC_reduction:
15836 case OMPC_task_reduction:
15837 case OMPC_in_reduction:
15838 case OMPC_linear:
15839 case OMPC_aligned:
15840 case OMPC_copyin:
15841 case OMPC_copyprivate:
15842 case OMPC_ordered:
15843 case OMPC_nowait:
15844 case OMPC_untied:
15845 case OMPC_mergeable:
15846 case OMPC_threadprivate:
15847 case OMPC_allocate:
15848 case OMPC_flush:
15849 case OMPC_depobj:
15850 case OMPC_read:
15851 case OMPC_write:
15852 case OMPC_capture:
15853 case OMPC_compare:
15854 case OMPC_seq_cst:
15855 case OMPC_acq_rel:
15856 case OMPC_acquire:
15857 case OMPC_release:
15858 case OMPC_relaxed:
15859 case OMPC_depend:
15860 case OMPC_device:
15861 case OMPC_threads:
15862 case OMPC_simd:
15863 case OMPC_map:
15864 case OMPC_num_teams:
15865 case OMPC_thread_limit:
15866 case OMPC_priority:
15867 case OMPC_grainsize:
15868 case OMPC_nogroup:
15869 case OMPC_num_tasks:
15870 case OMPC_hint:
15871 case OMPC_dist_schedule:
15872 case OMPC_defaultmap:
15873 case OMPC_unknown:
15874 case OMPC_uniform:
15875 case OMPC_to:
15876 case OMPC_from:
15877 case OMPC_use_device_ptr:
15878 case OMPC_use_device_addr:
15879 case OMPC_is_device_ptr:
15880 case OMPC_has_device_addr:
15881 case OMPC_unified_address:
15882 case OMPC_unified_shared_memory:
15883 case OMPC_reverse_offload:
15884 case OMPC_dynamic_allocators:
15885 case OMPC_device_type:
15886 case OMPC_match:
15887 case OMPC_nontemporal:
15888 case OMPC_destroy:
15889 case OMPC_novariants:
15890 case OMPC_nocontext:
15891 case OMPC_detach:
15892 case OMPC_inclusive:
15893 case OMPC_exclusive:
15894 case OMPC_uses_allocators:
15895 case OMPC_affinity:
15896 case OMPC_when:
15897 case OMPC_message:
15898 default:
15899 llvm_unreachable("Clause is not allowed.");
15900 }
15901 return Res;
15902}
15903
15904static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First,
15905 unsigned Last,
15906 ArrayRef<unsigned> Exclude = {}) {
15907 SmallString<256> Buffer;
15908 llvm::raw_svector_ostream Out(Buffer);
15909 unsigned Skipped = Exclude.size();
15910 for (unsigned I = First; I < Last; ++I) {
15911 if (llvm::is_contained(Exclude, I)) {
15912 --Skipped;
15913 continue;
15914 }
15915 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
15916 if (I + Skipped + 2 == Last)
15917 Out << " or ";
15918 else if (I + Skipped + 1 != Last)
15919 Out << ", ";
15920 }
15921 return std::string(Out.str());
15922}
15923
15925 SourceLocation KindKwLoc,
15926 SourceLocation StartLoc,
15927 SourceLocation LParenLoc,
15928 SourceLocation EndLoc) {
15929 if (Kind == OMP_DEFAULT_unknown) {
15930 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15931 << getListOfPossibleValues(OMPC_default, /*First=*/0,
15932 /*Last=*/unsigned(OMP_DEFAULT_unknown))
15933 << getOpenMPClauseName(OMPC_default);
15934 return nullptr;
15935 }
15936
15937 switch (Kind) {
15938 case OMP_DEFAULT_none:
15939 DSAStack->setDefaultDSANone(KindKwLoc);
15940 break;
15941 case OMP_DEFAULT_shared:
15942 DSAStack->setDefaultDSAShared(KindKwLoc);
15943 break;
15944 case OMP_DEFAULT_firstprivate:
15945 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
15946 break;
15947 case OMP_DEFAULT_private:
15948 DSAStack->setDefaultDSAPrivate(KindKwLoc);
15949 break;
15950 default:
15951 llvm_unreachable("DSA unexpected in OpenMP default clause");
15952 }
15953
15954 return new (getASTContext())
15955 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15956}
15957
15959 SourceLocation KindKwLoc,
15960 SourceLocation StartLoc,
15961 SourceLocation LParenLoc,
15962 SourceLocation EndLoc) {
15963 if (Kind == OMP_PROC_BIND_unknown) {
15964 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15965 << getListOfPossibleValues(OMPC_proc_bind,
15966 /*First=*/unsigned(OMP_PROC_BIND_master),
15967 /*Last=*/
15968 unsigned(getLangOpts().OpenMP > 50
15969 ? OMP_PROC_BIND_primary
15970 : OMP_PROC_BIND_spread) +
15971 1)
15972 << getOpenMPClauseName(OMPC_proc_bind);
15973 return nullptr;
15974 }
15975 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
15976 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15977 << getListOfPossibleValues(OMPC_proc_bind,
15978 /*First=*/unsigned(OMP_PROC_BIND_master),
15979 /*Last=*/
15980 unsigned(OMP_PROC_BIND_spread) + 1)
15981 << getOpenMPClauseName(OMPC_proc_bind);
15982 return new (getASTContext())
15983 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15984}
15985
15988 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
15990 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15992 OMPC_atomic_default_mem_order, /*First=*/0,
15994 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
15995 return nullptr;
15996 }
15998 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15999}
16000
16002 SourceLocation KindKwLoc,
16003 SourceLocation StartLoc,
16004 SourceLocation LParenLoc,
16005 SourceLocation EndLoc) {
16006 if (Kind == OMPC_AT_unknown) {
16007 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16008 << getListOfPossibleValues(OMPC_at, /*First=*/0,
16009 /*Last=*/OMPC_AT_unknown)
16010 << getOpenMPClauseName(OMPC_at);
16011 return nullptr;
16012 }
16013 return new (getASTContext())
16014 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16015}
16016
16018 SourceLocation KindKwLoc,
16019 SourceLocation StartLoc,
16020 SourceLocation LParenLoc,
16021 SourceLocation EndLoc) {
16022 if (Kind == OMPC_SEVERITY_unknown) {
16023 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16024 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
16025 /*Last=*/OMPC_SEVERITY_unknown)
16026 << getOpenMPClauseName(OMPC_severity);
16027 return nullptr;
16028 }
16029 return new (getASTContext())
16030 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16031}
16032
16034 SourceLocation StartLoc,
16035 SourceLocation LParenLoc,
16036 SourceLocation EndLoc) {
16037 assert(ME && "NULL expr in Message clause");
16038 if (!isa<StringLiteral>(ME)) {
16039 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
16040 << getOpenMPClauseName(OMPC_message);
16041 return nullptr;
16042 }
16043 return new (getASTContext())
16044 OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc);
16045}
16046
16049 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
16050 SourceLocation KindLoc, SourceLocation EndLoc) {
16051 if (Kind != OMPC_ORDER_concurrent ||
16052 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
16053 // Kind should be concurrent,
16054 // Modifiers introduced in OpenMP 5.1
16055 static_assert(OMPC_ORDER_unknown > 0,
16056 "OMPC_ORDER_unknown not greater than 0");
16057
16058 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16059 << getListOfPossibleValues(OMPC_order,
16060 /*First=*/0,
16061 /*Last=*/OMPC_ORDER_unknown)
16062 << getOpenMPClauseName(OMPC_order);
16063 return nullptr;
16064 }
16065 if (getLangOpts().OpenMP >= 51) {
16066 if (Modifier == OMPC_ORDER_MODIFIER_unknown && MLoc.isValid()) {
16067 Diag(MLoc, diag::err_omp_unexpected_clause_value)
16068 << getListOfPossibleValues(OMPC_order,
16069 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
16070 /*Last=*/OMPC_ORDER_MODIFIER_last)
16071 << getOpenMPClauseName(OMPC_order);
16072 } else {
16073 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
16074 if (DSAStack->getCurScope()) {
16075 // mark the current scope with 'order' flag
16076 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
16077 DSAStack->getCurScope()->setFlags(existingFlags |
16079 }
16080 }
16081 }
16082 return new (getASTContext()) OMPOrderClause(
16083 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
16084}
16085
16087 SourceLocation KindKwLoc,
16088 SourceLocation StartLoc,
16089 SourceLocation LParenLoc,
16090 SourceLocation EndLoc) {
16091 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
16092 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
16093 SmallVector<unsigned> Except = {
16094 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
16095 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
16096 if (getLangOpts().OpenMP < 51)
16097 Except.push_back(OMPC_DEPEND_inoutset);
16098 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16099 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
16100 /*Last=*/OMPC_DEPEND_unknown, Except)
16101 << getOpenMPClauseName(OMPC_update);
16102 return nullptr;
16103 }
16104 return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc,
16105 KindKwLoc, Kind, EndLoc);
16106}
16107
16109 SourceLocation StartLoc,
16110 SourceLocation LParenLoc,
16111 SourceLocation EndLoc) {
16112 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
16113
16114 for (Expr *&SizeExpr : SanitizedSizeExprs) {
16115 // Skip if already sanitized, e.g. during a partial template instantiation.
16116 if (!SizeExpr)
16117 continue;
16118
16119 bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes,
16120 /*StrictlyPositive=*/true);
16121
16122 // isNonNegativeIntegerValue returns true for non-integral types (but still
16123 // emits error diagnostic), so check for the expected type explicitly.
16124 QualType SizeTy = SizeExpr->getType();
16125 if (!SizeTy->isIntegerType())
16126 IsValid = false;
16127
16128 // Handling in templates is tricky. There are four possibilities to
16129 // consider:
16130 //
16131 // 1a. The expression is valid and we are in a instantiated template or not
16132 // in a template:
16133 // Pass valid expression to be further analysed later in Sema.
16134 // 1b. The expression is valid and we are in a template (including partial
16135 // instantiation):
16136 // isNonNegativeIntegerValue skipped any checks so there is no
16137 // guarantee it will be correct after instantiation.
16138 // ActOnOpenMPSizesClause will be called again at instantiation when
16139 // it is not in a dependent context anymore. This may cause warnings
16140 // to be emitted multiple times.
16141 // 2a. The expression is invalid and we are in an instantiated template or
16142 // not in a template:
16143 // Invalidate the expression with a clearly wrong value (nullptr) so
16144 // later in Sema we do not have to do the same validity analysis again
16145 // or crash from unexpected data. Error diagnostics have already been
16146 // emitted.
16147 // 2b. The expression is invalid and we are in a template (including partial
16148 // instantiation):
16149 // Pass the invalid expression as-is, template instantiation may
16150 // replace unexpected types/values with valid ones. The directives
16151 // with this clause must not try to use these expressions in dependent
16152 // contexts, but delay analysis until full instantiation.
16153 if (!SizeExpr->isInstantiationDependent() && !IsValid)
16154 SizeExpr = nullptr;
16155 }
16156
16157 return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
16158 SanitizedSizeExprs);
16159}
16160
16162 SourceLocation StartLoc,
16163 SourceLocation LParenLoc,
16164 SourceLocation EndLoc) {
16165 size_t NumLoops = PermExprs.size();
16166 SmallVector<Expr *> SanitizedPermExprs;
16167 llvm::append_range(SanitizedPermExprs, PermExprs);
16168
16169 for (Expr *&PermExpr : SanitizedPermExprs) {
16170 // Skip if template-dependent or already sanitized, e.g. during a partial
16171 // template instantiation.
16172 if (!PermExpr || PermExpr->isInstantiationDependent())
16173 continue;
16174
16175 llvm::APSInt PermVal;
16177 PermExpr, &PermVal, Sema::AllowFold);
16178 bool IsValid = PermEvalExpr.isUsable();
16179 if (IsValid)
16180 PermExpr = PermEvalExpr.get();
16181
16182 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
16183 SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
16184 PermEvalExpr.get()->getEndLoc());
16185 Diag(PermEvalExpr.get()->getExprLoc(),
16186 diag::err_omp_interchange_permutation_value_range)
16187 << NumLoops << ExprRange;
16188 IsValid = false;
16189 }
16190
16191 if (!PermExpr->isInstantiationDependent() && !IsValid)
16192 PermExpr = nullptr;
16193 }
16194
16195 return OMPPermutationClause::Create(getASTContext(), StartLoc, LParenLoc,
16196 EndLoc, SanitizedPermExprs);
16197}
16198
16200 SourceLocation EndLoc) {
16201 return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc);
16202}
16203
16205 SourceLocation StartLoc,
16206 SourceLocation LParenLoc,
16207 SourceLocation EndLoc) {
16208 if (FactorExpr) {
16209 // If an argument is specified, it must be a constant (or an unevaluated
16210 // template expression).
16212 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
16213 if (FactorResult.isInvalid())
16214 return nullptr;
16215 FactorExpr = FactorResult.get();
16216 }
16217
16218 return OMPPartialClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
16219 FactorExpr);
16220}
16221
16223 SourceLocation LParenLoc,
16224 SourceLocation EndLoc) {
16225 ExprResult AlignVal;
16226 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
16227 if (AlignVal.isInvalid())
16228 return nullptr;
16229 return OMPAlignClause::Create(getASTContext(), AlignVal.get(), StartLoc,
16230 LParenLoc, EndLoc);
16231}
16232
16235 SourceLocation StartLoc, SourceLocation LParenLoc,
16236 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
16237 SourceLocation EndLoc) {
16238 OMPClause *Res = nullptr;
16239 switch (Kind) {
16240 case OMPC_schedule:
16241 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
16242 assert(Argument.size() == NumberOfElements &&
16243 ArgumentLoc.size() == NumberOfElements);
16245 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
16246 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
16247 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
16248 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
16249 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
16250 break;
16251 case OMPC_if:
16252 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16253 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
16254 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
16255 DelimLoc, EndLoc);
16256 break;
16257 case OMPC_dist_schedule:
16259 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
16260 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
16261 break;
16262 case OMPC_defaultmap:
16263 enum { Modifier, DefaultmapKind };
16265 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
16266 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
16267 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
16268 EndLoc);
16269 break;
16270 case OMPC_order:
16271 enum { OrderModifier, OrderKind };
16273 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
16274 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
16275 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
16276 break;
16277 case OMPC_device:
16278 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16280 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
16281 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16282 break;
16283 case OMPC_grainsize:
16284 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16285 "Modifier for grainsize clause and its location are expected.");
16287 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
16288 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16289 break;
16290 case OMPC_num_tasks:
16291 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16292 "Modifier for num_tasks clause and its location are expected.");
16294 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
16295 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16296 break;
16297 case OMPC_final:
16298 case OMPC_num_threads:
16299 case OMPC_safelen:
16300 case OMPC_simdlen:
16301 case OMPC_sizes:
16302 case OMPC_allocator:
16303 case OMPC_collapse:
16304 case OMPC_default:
16305 case OMPC_proc_bind:
16306 case OMPC_private:
16307 case OMPC_firstprivate:
16308 case OMPC_lastprivate:
16309 case OMPC_shared:
16310 case OMPC_reduction:
16311 case OMPC_task_reduction:
16312 case OMPC_in_reduction:
16313 case OMPC_linear:
16314 case OMPC_aligned:
16315 case OMPC_copyin:
16316 case OMPC_copyprivate:
16317 case OMPC_ordered:
16318 case OMPC_nowait:
16319 case OMPC_untied:
16320 case OMPC_mergeable:
16321 case OMPC_threadprivate:
16322 case OMPC_allocate:
16323 case OMPC_flush:
16324 case OMPC_depobj:
16325 case OMPC_read:
16326 case OMPC_write:
16327 case OMPC_update:
16328 case OMPC_capture:
16329 case OMPC_compare:
16330 case OMPC_seq_cst:
16331 case OMPC_acq_rel:
16332 case OMPC_acquire:
16333 case OMPC_release:
16334 case OMPC_relaxed:
16335 case OMPC_depend:
16336 case OMPC_threads:
16337 case OMPC_simd:
16338 case OMPC_map:
16339 case OMPC_num_teams:
16340 case OMPC_thread_limit:
16341 case OMPC_priority:
16342 case OMPC_nogroup:
16343 case OMPC_hint:
16344 case OMPC_unknown:
16345 case OMPC_uniform:
16346 case OMPC_to:
16347 case OMPC_from:
16348 case OMPC_use_device_ptr:
16349 case OMPC_use_device_addr:
16350 case OMPC_is_device_ptr:
16351 case OMPC_has_device_addr:
16352 case OMPC_unified_address:
16353 case OMPC_unified_shared_memory:
16354 case OMPC_reverse_offload:
16355 case OMPC_dynamic_allocators:
16356 case OMPC_atomic_default_mem_order:
16357 case OMPC_device_type:
16358 case OMPC_match:
16359 case OMPC_nontemporal:
16360 case OMPC_at:
16361 case OMPC_severity:
16362 case OMPC_message:
16363 case OMPC_destroy:
16364 case OMPC_novariants:
16365 case OMPC_nocontext:
16366 case OMPC_detach:
16367 case OMPC_inclusive:
16368 case OMPC_exclusive:
16369 case OMPC_uses_allocators:
16370 case OMPC_affinity:
16371 case OMPC_when:
16372 case OMPC_bind:
16373 default:
16374 llvm_unreachable("Clause is not allowed.");
16375 }
16376 return Res;
16377}
16378
16381 SourceLocation M1Loc, SourceLocation M2Loc) {
16382 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
16383 SmallVector<unsigned, 2> Excluded;
16385 Excluded.push_back(M2);
16386 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
16387 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
16388 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
16389 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
16390 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
16391 << getListOfPossibleValues(OMPC_schedule,
16392 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
16394 Excluded)
16395 << getOpenMPClauseName(OMPC_schedule);
16396 return true;
16397 }
16398 return false;
16399}
16400
16403 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
16404 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
16405 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
16406 if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) ||
16407 checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc))
16408 return nullptr;
16409 // OpenMP, 2.7.1, Loop Construct, Restrictions
16410 // Either the monotonic modifier or the nonmonotonic modifier can be specified
16411 // but not both.
16412 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
16413 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
16414 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
16415 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
16416 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
16417 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
16418 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
16419 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
16420 return nullptr;
16421 }
16422 if (Kind == OMPC_SCHEDULE_unknown) {
16423 std::string Values;
16424 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
16425 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
16426 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16428 Exclude);
16429 } else {
16430 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16431 /*Last=*/OMPC_SCHEDULE_unknown);
16432 }
16433 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16434 << Values << getOpenMPClauseName(OMPC_schedule);
16435 return nullptr;
16436 }
16437 // OpenMP, 2.7.1, Loop Construct, Restrictions
16438 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
16439 // schedule(guided).
16440 // OpenMP 5.0 does not have this restriction.
16441 if (getLangOpts().OpenMP < 50 &&
16442 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
16443 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
16444 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
16445 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
16446 diag::err_omp_schedule_nonmonotonic_static);
16447 return nullptr;
16448 }
16449 Expr *ValExpr = ChunkSize;
16450 Stmt *HelperValStmt = nullptr;
16451 if (ChunkSize) {
16452 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
16453 !ChunkSize->isInstantiationDependent() &&
16454 !ChunkSize->containsUnexpandedParameterPack()) {
16455 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
16456 ExprResult Val =
16457 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
16458 if (Val.isInvalid())
16459 return nullptr;
16460
16461 ValExpr = Val.get();
16462
16463 // OpenMP [2.7.1, Restrictions]
16464 // chunk_size must be a loop invariant integer expression with a positive
16465 // value.
16466 if (std::optional<llvm::APSInt> Result =
16468 if (Result->isSigned() && !Result->isStrictlyPositive()) {
16469 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
16470 << "schedule" << 1 << ChunkSize->getSourceRange();
16471 return nullptr;
16472 }
16474 DSAStack->getCurrentDirective(), OMPC_schedule,
16475 getLangOpts().OpenMP) != OMPD_unknown &&
16477 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16478 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16479 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16480 HelperValStmt = buildPreInits(getASTContext(), Captures);
16481 }
16482 }
16483 }
16484
16485 return new (getASTContext())
16486 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
16487 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
16488}
16489
16491 SourceLocation StartLoc,
16492 SourceLocation EndLoc) {
16493 OMPClause *Res = nullptr;
16494 switch (Kind) {
16495 case OMPC_ordered:
16496 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
16497 break;
16498 case OMPC_nowait:
16499 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
16500 break;
16501 case OMPC_untied:
16502 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
16503 break;
16504 case OMPC_mergeable:
16505 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
16506 break;
16507 case OMPC_read:
16508 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
16509 break;
16510 case OMPC_write:
16511 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
16512 break;
16513 case OMPC_update:
16514 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
16515 break;
16516 case OMPC_capture:
16517 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
16518 break;
16519 case OMPC_compare:
16520 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
16521 break;
16522 case OMPC_fail:
16523 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
16524 break;
16525 case OMPC_seq_cst:
16526 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
16527 break;
16528 case OMPC_acq_rel:
16529 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
16530 break;
16531 case OMPC_acquire:
16532 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
16533 break;
16534 case OMPC_release:
16535 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
16536 break;
16537 case OMPC_relaxed:
16538 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
16539 break;
16540 case OMPC_weak:
16541 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
16542 break;
16543 case OMPC_threads:
16544 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
16545 break;
16546 case OMPC_simd:
16547 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
16548 break;
16549 case OMPC_nogroup:
16550 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
16551 break;
16552 case OMPC_unified_address:
16553 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
16554 break;
16555 case OMPC_unified_shared_memory:
16556 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
16557 break;
16558 case OMPC_reverse_offload:
16559 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
16560 break;
16561 case OMPC_dynamic_allocators:
16562 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
16563 break;
16564 case OMPC_destroy:
16565 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
16566 /*LParenLoc=*/SourceLocation(),
16567 /*VarLoc=*/SourceLocation(), EndLoc);
16568 break;
16569 case OMPC_full:
16570 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
16571 break;
16572 case OMPC_partial:
16573 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
16574 break;
16575 case OMPC_ompx_bare:
16576 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
16577 break;
16578 case OMPC_if:
16579 case OMPC_final:
16580 case OMPC_num_threads:
16581 case OMPC_safelen:
16582 case OMPC_simdlen:
16583 case OMPC_sizes:
16584 case OMPC_allocator:
16585 case OMPC_collapse:
16586 case OMPC_schedule:
16587 case OMPC_private:
16588 case OMPC_firstprivate:
16589 case OMPC_lastprivate:
16590 case OMPC_shared:
16591 case OMPC_reduction:
16592 case OMPC_task_reduction:
16593 case OMPC_in_reduction:
16594 case OMPC_linear:
16595 case OMPC_aligned:
16596 case OMPC_copyin:
16597 case OMPC_copyprivate:
16598 case OMPC_default:
16599 case OMPC_proc_bind:
16600 case OMPC_threadprivate:
16601 case OMPC_allocate:
16602 case OMPC_flush:
16603 case OMPC_depobj:
16604 case OMPC_depend:
16605 case OMPC_device:
16606 case OMPC_map:
16607 case OMPC_num_teams:
16608 case OMPC_thread_limit:
16609 case OMPC_priority:
16610 case OMPC_grainsize:
16611 case OMPC_num_tasks:
16612 case OMPC_hint:
16613 case OMPC_dist_schedule:
16614 case OMPC_defaultmap:
16615 case OMPC_unknown:
16616 case OMPC_uniform:
16617 case OMPC_to:
16618 case OMPC_from:
16619 case OMPC_use_device_ptr:
16620 case OMPC_use_device_addr:
16621 case OMPC_is_device_ptr:
16622 case OMPC_has_device_addr:
16623 case OMPC_atomic_default_mem_order:
16624 case OMPC_device_type:
16625 case OMPC_match:
16626 case OMPC_nontemporal:
16627 case OMPC_order:
16628 case OMPC_at:
16629 case OMPC_severity:
16630 case OMPC_message:
16631 case OMPC_novariants:
16632 case OMPC_nocontext:
16633 case OMPC_detach:
16634 case OMPC_inclusive:
16635 case OMPC_exclusive:
16636 case OMPC_uses_allocators:
16637 case OMPC_affinity:
16638 case OMPC_when:
16639 case OMPC_ompx_dyn_cgroup_mem:
16640 default:
16641 llvm_unreachable("Clause is not allowed.");
16642 }
16643 return Res;
16644}
16645
16647 SourceLocation EndLoc) {
16648 DSAStack->setNowaitRegion();
16649 return new (getASTContext()) OMPNowaitClause(StartLoc, EndLoc);
16650}
16651
16653 SourceLocation EndLoc) {
16654 DSAStack->setUntiedRegion();
16655 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
16656}
16657
16659 SourceLocation EndLoc) {
16660 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
16661}
16662
16664 SourceLocation EndLoc) {
16665 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
16666}
16667
16669 SourceLocation EndLoc) {
16670 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
16671}
16672
16674 SourceLocation EndLoc) {
16675 return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc);
16676}
16677
16679 SourceLocation EndLoc) {
16680 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
16681}
16682
16684 SourceLocation EndLoc) {
16685 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
16686}
16687
16689 SourceLocation EndLoc) {
16690 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
16691}
16692
16694 SourceLocation KindLoc,
16695 SourceLocation StartLoc,
16696 SourceLocation LParenLoc,
16697 SourceLocation EndLoc) {
16698
16700 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
16701 return nullptr;
16702 }
16703 return new (getASTContext())
16704 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
16705}
16706
16708 SourceLocation EndLoc) {
16709 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
16710}
16711
16713 SourceLocation EndLoc) {
16714 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
16715}
16716
16718 SourceLocation EndLoc) {
16719 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
16720}
16721
16723 SourceLocation EndLoc) {
16724 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
16725}
16726
16728 SourceLocation EndLoc) {
16729 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
16730}
16731
16733 SourceLocation EndLoc) {
16734 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
16735}
16736
16738 SourceLocation EndLoc) {
16739 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
16740}
16741
16743 SourceLocation EndLoc) {
16744 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
16745}
16746
16748 SourceLocation EndLoc) {
16749 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
16750}
16751
16753 SourceLocation EndLoc) {
16754 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
16755}
16756
16757OMPClause *
16759 SourceLocation EndLoc) {
16760 return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
16761}
16762
16764 SourceLocation EndLoc) {
16765 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
16766}
16767
16768OMPClause *
16770 SourceLocation EndLoc) {
16771 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
16772}
16773
16776 SourceLocation StartLoc,
16777 SourceLocation EndLoc) {
16778
16779 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16780 // At least one action-clause must appear on a directive.
16781 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
16782 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
16783 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
16784 << Expected << getOpenMPDirectiveName(OMPD_interop);
16785 return StmtError();
16786 }
16787
16788 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16789 // A depend clause can only appear on the directive if a targetsync
16790 // interop-type is present or the interop-var was initialized with
16791 // the targetsync interop-type.
16792
16793 // If there is any 'init' clause diagnose if there is no 'init' clause with
16794 // interop-type of 'targetsync'. Cases involving other directives cannot be
16795 // diagnosed.
16796 const OMPDependClause *DependClause = nullptr;
16797 bool HasInitClause = false;
16798 bool IsTargetSync = false;
16799 for (const OMPClause *C : Clauses) {
16800 if (IsTargetSync)
16801 break;
16802 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
16803 HasInitClause = true;
16804 if (InitClause->getIsTargetSync())
16805 IsTargetSync = true;
16806 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
16807 DependClause = DC;
16808 }
16809 }
16810 if (DependClause && HasInitClause && !IsTargetSync) {
16811 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
16812 return StmtError();
16813 }
16814
16815 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16816 // Each interop-var may be specified for at most one action-clause of each
16817 // interop construct.
16819 for (OMPClause *C : Clauses) {
16820 OpenMPClauseKind ClauseKind = C->getClauseKind();
16821 std::pair<ValueDecl *, bool> DeclResult;
16822 SourceLocation ELoc;
16823 SourceRange ERange;
16824
16825 if (ClauseKind == OMPC_init) {
16826 auto *E = cast<OMPInitClause>(C)->getInteropVar();
16827 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
16828 } else if (ClauseKind == OMPC_use) {
16829 auto *E = cast<OMPUseClause>(C)->getInteropVar();
16830 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
16831 } else if (ClauseKind == OMPC_destroy) {
16832 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
16833 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
16834 }
16835
16836 if (DeclResult.first) {
16837 if (!InteropVars.insert(DeclResult.first).second) {
16838 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
16839 << DeclResult.first;
16840 return StmtError();
16841 }
16842 }
16843 }
16844
16845 return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc,
16846 Clauses);
16847}
16848
16849static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
16850 SourceLocation VarLoc,
16851 OpenMPClauseKind Kind) {
16852 SourceLocation ELoc;
16853 SourceRange ERange;
16854 Expr *RefExpr = InteropVarExpr;
16855 auto Res =
16856 getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
16857 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
16858
16859 if (Res.second) {
16860 // It will be analyzed later.
16861 return true;
16862 }
16863
16864 if (!Res.first)
16865 return false;
16866
16867 // Interop variable should be of type omp_interop_t.
16868 bool HasError = false;
16869 QualType InteropType;
16870 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
16871 VarLoc, Sema::LookupOrdinaryName);
16872 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
16873 NamedDecl *ND = Result.getFoundDecl();
16874 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
16875 InteropType = QualType(TD->getTypeForDecl(), 0);
16876 } else {
16877 HasError = true;
16878 }
16879 } else {
16880 HasError = true;
16881 }
16882
16883 if (HasError) {
16884 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
16885 << "omp_interop_t";
16886 return false;
16887 }
16888
16889 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
16890 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
16891 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
16892 return false;
16893 }
16894
16895 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16896 // The interop-var passed to init or destroy must be non-const.
16897 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
16898 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
16899 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
16900 << /*non-const*/ 1;
16901 return false;
16902 }
16903 return true;
16904}
16905
16907 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
16908 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
16909
16910 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init))
16911 return nullptr;
16912
16913 // Check prefer_type values. These foreign-runtime-id values are either
16914 // string literals or constant integral expressions.
16915 for (const Expr *E : InteropInfo.PreferTypes) {
16916 if (E->isValueDependent() || E->isTypeDependent() ||
16918 continue;
16920 continue;
16921 if (isa<StringLiteral>(E))
16922 continue;
16923 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
16924 return nullptr;
16925 }
16926
16927 return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo,
16928 StartLoc, LParenLoc, VarLoc, EndLoc);
16929}
16930
16932 SourceLocation StartLoc,
16933 SourceLocation LParenLoc,
16934 SourceLocation VarLoc,
16935 SourceLocation EndLoc) {
16936
16937 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use))
16938 return nullptr;
16939
16940 return new (getASTContext())
16941 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
16942}
16943
16945 SourceLocation StartLoc,
16946 SourceLocation LParenLoc,
16947 SourceLocation VarLoc,
16948 SourceLocation EndLoc) {
16949 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
16950 DSAStack->getCurrentDirective() == OMPD_depobj) {
16951 Diag(StartLoc, diag::err_omp_expected_clause_argument)
16952 << getOpenMPClauseName(OMPC_destroy)
16953 << getOpenMPDirectiveName(OMPD_depobj);
16954 return nullptr;
16955 }
16956 if (InteropVar &&
16957 !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy))
16958 return nullptr;
16959
16960 return new (getASTContext())
16961 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
16962}
16963
16965 SourceLocation StartLoc,
16966 SourceLocation LParenLoc,
16967 SourceLocation EndLoc) {
16968 Expr *ValExpr = Condition;
16969 Stmt *HelperValStmt = nullptr;
16970 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16971 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16972 !Condition->isInstantiationDependent() &&
16973 !Condition->containsUnexpandedParameterPack()) {
16975 if (Val.isInvalid())
16976 return nullptr;
16977
16978 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
16979
16980 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16981 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
16982 getLangOpts().OpenMP);
16983 if (CaptureRegion != OMPD_unknown &&
16985 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16986 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16987 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16988 HelperValStmt = buildPreInits(getASTContext(), Captures);
16989 }
16990 }
16991
16992 return new (getASTContext()) OMPNovariantsClause(
16993 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16994}
16995
16997 SourceLocation StartLoc,
16998 SourceLocation LParenLoc,
16999 SourceLocation EndLoc) {
17000 Expr *ValExpr = Condition;
17001 Stmt *HelperValStmt = nullptr;
17002 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17003 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17004 !Condition->isInstantiationDependent() &&
17005 !Condition->containsUnexpandedParameterPack()) {
17007 if (Val.isInvalid())
17008 return nullptr;
17009
17010 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
17011
17012 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17013 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext,
17014 getLangOpts().OpenMP);
17015 if (CaptureRegion != OMPD_unknown &&
17017 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17018 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17019 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17020 HelperValStmt = buildPreInits(getASTContext(), Captures);
17021 }
17022 }
17023
17024 return new (getASTContext()) OMPNocontextClause(
17025 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17026}
17027
17029 SourceLocation StartLoc,
17030 SourceLocation LParenLoc,
17031 SourceLocation EndLoc) {
17032 Expr *ValExpr = ThreadID;
17033 Stmt *HelperValStmt = nullptr;
17034
17035 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17036 OpenMPDirectiveKind CaptureRegion =
17037 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP);
17038 if (CaptureRegion != OMPD_unknown &&
17040 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17041 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17042 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17043 HelperValStmt = buildPreInits(getASTContext(), Captures);
17044 }
17045
17046 return new (getASTContext()) OMPFilterClause(
17047 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17048}
17049
17051 ArrayRef<Expr *> VarList,
17052 const OMPVarListLocTy &Locs,
17054 SourceLocation StartLoc = Locs.StartLoc;
17055 SourceLocation LParenLoc = Locs.LParenLoc;
17056 SourceLocation EndLoc = Locs.EndLoc;
17057 OMPClause *Res = nullptr;
17058 int ExtraModifier = Data.ExtraModifier;
17059 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
17060 SourceLocation ColonLoc = Data.ColonLoc;
17061 switch (Kind) {
17062 case OMPC_private:
17063 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17064 break;
17065 case OMPC_firstprivate:
17066 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17067 break;
17068 case OMPC_lastprivate:
17069 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
17070 "Unexpected lastprivate modifier.");
17072 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
17073 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
17074 break;
17075 case OMPC_shared:
17076 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
17077 break;
17078 case OMPC_reduction:
17079 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
17080 "Unexpected lastprivate modifier.");
17082 VarList, static_cast<OpenMPReductionClauseModifier>(ExtraModifier),
17083 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
17084 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17085 break;
17086 case OMPC_task_reduction:
17088 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17089 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17090 break;
17091 case OMPC_in_reduction:
17093 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17094 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17095 break;
17096 case OMPC_linear:
17097 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
17098 "Unexpected linear modifier.");
17100 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
17101 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
17102 ColonLoc, Data.StepModifierLoc, EndLoc);
17103 break;
17104 case OMPC_aligned:
17105 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
17106 LParenLoc, ColonLoc, EndLoc);
17107 break;
17108 case OMPC_copyin:
17109 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
17110 break;
17111 case OMPC_copyprivate:
17112 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17113 break;
17114 case OMPC_flush:
17115 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
17116 break;
17117 case OMPC_depend:
17118 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
17119 "Unexpected depend modifier.");
17121 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
17122 ColonLoc, Data.OmpAllMemoryLoc},
17123 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
17124 break;
17125 case OMPC_map:
17126 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
17127 "Unexpected map modifier.");
17129 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
17130 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
17131 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
17132 ExtraModifierLoc, ColonLoc, VarList, Locs);
17133 break;
17134 case OMPC_to:
17135 Res =
17136 ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc,
17137 Data.ReductionOrMapperIdScopeSpec,
17138 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
17139 break;
17140 case OMPC_from:
17141 Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc,
17142 Data.ReductionOrMapperIdScopeSpec,
17143 Data.ReductionOrMapperId, ColonLoc, VarList,
17144 Locs);
17145 break;
17146 case OMPC_use_device_ptr:
17147 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
17148 break;
17149 case OMPC_use_device_addr:
17150 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
17151 break;
17152 case OMPC_is_device_ptr:
17153 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
17154 break;
17155 case OMPC_has_device_addr:
17156 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
17157 break;
17158 case OMPC_allocate: {
17161 SourceLocation Modifier1Loc, Modifier2Loc;
17162 if (!Data.AllocClauseModifiers.empty()) {
17163 assert(Data.AllocClauseModifiers.size() <= 2 &&
17164 "More allocate modifiers than expected");
17165 Modifier1 = Data.AllocClauseModifiers[0];
17166 Modifier1Loc = Data.AllocClauseModifiersLoc[0];
17167 if (Data.AllocClauseModifiers.size() == 2) {
17168 Modifier2 = Data.AllocClauseModifiers[1];
17169 Modifier2Loc = Data.AllocClauseModifiersLoc[1];
17170 }
17171 }
17173 Data.DepModOrTailExpr, Data.AllocateAlignment, Modifier1, Modifier1Loc,
17174 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
17175 EndLoc);
17176 break;
17177 }
17178 case OMPC_nontemporal:
17179 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
17180 break;
17181 case OMPC_inclusive:
17182 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17183 break;
17184 case OMPC_exclusive:
17185 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17186 break;
17187 case OMPC_affinity:
17188 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
17189 Data.DepModOrTailExpr, VarList);
17190 break;
17191 case OMPC_doacross:
17193 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
17194 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
17195 break;
17196 case OMPC_num_teams:
17197 Res = ActOnOpenMPNumTeamsClause(VarList, StartLoc, LParenLoc, EndLoc);
17198 break;
17199 case OMPC_thread_limit:
17200 Res = ActOnOpenMPThreadLimitClause(VarList, StartLoc, LParenLoc, EndLoc);
17201 break;
17202 case OMPC_if:
17203 case OMPC_depobj:
17204 case OMPC_final:
17205 case OMPC_num_threads:
17206 case OMPC_safelen:
17207 case OMPC_simdlen:
17208 case OMPC_sizes:
17209 case OMPC_allocator:
17210 case OMPC_collapse:
17211 case OMPC_default:
17212 case OMPC_proc_bind:
17213 case OMPC_schedule:
17214 case OMPC_ordered:
17215 case OMPC_nowait:
17216 case OMPC_untied:
17217 case OMPC_mergeable:
17218 case OMPC_threadprivate:
17219 case OMPC_read:
17220 case OMPC_write:
17221 case OMPC_update:
17222 case OMPC_capture:
17223 case OMPC_compare:
17224 case OMPC_seq_cst:
17225 case OMPC_acq_rel:
17226 case OMPC_acquire:
17227 case OMPC_release:
17228 case OMPC_relaxed:
17229 case OMPC_device:
17230 case OMPC_threads:
17231 case OMPC_simd:
17232 case OMPC_priority:
17233 case OMPC_grainsize:
17234 case OMPC_nogroup:
17235 case OMPC_num_tasks:
17236 case OMPC_hint:
17237 case OMPC_dist_schedule:
17238 case OMPC_defaultmap:
17239 case OMPC_unknown:
17240 case OMPC_uniform:
17241 case OMPC_unified_address:
17242 case OMPC_unified_shared_memory:
17243 case OMPC_reverse_offload:
17244 case OMPC_dynamic_allocators:
17245 case OMPC_atomic_default_mem_order:
17246 case OMPC_device_type:
17247 case OMPC_match:
17248 case OMPC_order:
17249 case OMPC_at:
17250 case OMPC_severity:
17251 case OMPC_message:
17252 case OMPC_destroy:
17253 case OMPC_novariants:
17254 case OMPC_nocontext:
17255 case OMPC_detach:
17256 case OMPC_uses_allocators:
17257 case OMPC_when:
17258 case OMPC_bind:
17259 default:
17260 llvm_unreachable("Clause is not allowed.");
17261 }
17262 return Res;
17263}
17264
17266 ExprObjectKind OK,
17269 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
17270 if (!Res.isUsable())
17271 return ExprError();
17272 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
17273 Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
17274 if (!Res.isUsable())
17275 return ExprError();
17276 }
17277 if (VK != VK_LValue && Res.get()->isGLValue()) {
17278 Res = SemaRef.DefaultLvalueConversion(Res.get());
17279 if (!Res.isUsable())
17280 return ExprError();
17281 }
17282 return Res;
17283}
17284
17286 SourceLocation StartLoc,
17287 SourceLocation LParenLoc,
17288 SourceLocation EndLoc) {
17290 SmallVector<Expr *, 8> PrivateCopies;
17291 bool IsImplicitClause =
17292 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17293 for (Expr *RefExpr : VarList) {
17294 assert(RefExpr && "NULL expr in OpenMP private clause.");
17295 SourceLocation ELoc;
17296 SourceRange ERange;
17297 Expr *SimpleRefExpr = RefExpr;
17298 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17299 if (Res.second) {
17300 // It will be analyzed later.
17301 Vars.push_back(RefExpr);
17302 PrivateCopies.push_back(nullptr);
17303 }
17304 ValueDecl *D = Res.first;
17305 if (!D)
17306 continue;
17307
17308 QualType Type = D->getType();
17309 auto *VD = dyn_cast<VarDecl>(D);
17310
17311 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17312 // A variable that appears in a private clause must not have an incomplete
17313 // type or a reference type.
17315 diag::err_omp_private_incomplete_type))
17316 continue;
17317 Type = Type.getNonReferenceType();
17318
17319 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
17320 // A variable that is privatized must not have a const-qualified type
17321 // unless it is of class type with a mutable member. This restriction does
17322 // not apply to the firstprivate clause.
17323 //
17324 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
17325 // A variable that appears in a private clause must not have a
17326 // const-qualified type unless it is of class type with a mutable member.
17327 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc))
17328 continue;
17329
17330 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17331 // in a Construct]
17332 // Variables with the predetermined data-sharing attributes may not be
17333 // listed in data-sharing attributes clauses, except for the cases
17334 // listed below. For these exceptions only, listing a predetermined
17335 // variable in a data-sharing attribute clause is allowed and overrides
17336 // the variable's predetermined data-sharing attributes.
17337 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17338 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
17339 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17340 << getOpenMPClauseName(OMPC_private);
17342 continue;
17343 }
17344
17345 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17346 // Variably modified types are not supported for tasks.
17348 isOpenMPTaskingDirective(CurrDir)) {
17349 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17350 << getOpenMPClauseName(OMPC_private) << Type
17351 << getOpenMPDirectiveName(CurrDir);
17352 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17354 Diag(D->getLocation(),
17355 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17356 << D;
17357 continue;
17358 }
17359
17360 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17361 // A list item cannot appear in both a map clause and a data-sharing
17362 // attribute clause on the same construct
17363 //
17364 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17365 // A list item cannot appear in both a map clause and a data-sharing
17366 // attribute clause on the same construct unless the construct is a
17367 // combined construct.
17368 if ((getLangOpts().OpenMP <= 45 &&
17370 CurrDir == OMPD_target) {
17371 OpenMPClauseKind ConflictKind;
17372 if (DSAStack->checkMappableExprComponentListsForDecl(
17373 VD, /*CurrentRegionOnly=*/true,
17375 OpenMPClauseKind WhereFoundClauseKind) -> bool {
17376 ConflictKind = WhereFoundClauseKind;
17377 return true;
17378 })) {
17379 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17380 << getOpenMPClauseName(OMPC_private)
17381 << getOpenMPClauseName(ConflictKind)
17382 << getOpenMPDirectiveName(CurrDir);
17384 continue;
17385 }
17386 }
17387
17388 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
17389 // A variable of class type (or array thereof) that appears in a private
17390 // clause requires an accessible, unambiguous default constructor for the
17391 // class type.
17392 // Generate helper private variable and initialize it with the default
17393 // value. The address of the original variable is replaced by the address of
17394 // the new private variable in CodeGen. This new variable is not added to
17395 // IdResolver, so the code in the OpenMP region uses original variable for
17396 // proper diagnostics.
17397 Type = Type.getUnqualifiedType();
17398 VarDecl *VDPrivate =
17399 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
17400 D->hasAttrs() ? &D->getAttrs() : nullptr,
17401 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
17403 if (VDPrivate->isInvalidDecl())
17404 continue;
17405 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
17406 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
17407
17408 DeclRefExpr *Ref = nullptr;
17409 if (!VD && !SemaRef.CurContext->isDependentContext()) {
17410 auto *FD = dyn_cast<FieldDecl>(D);
17411 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
17412 if (VD)
17414 RefExpr->getExprLoc());
17415 else
17416 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
17417 }
17418 if (!IsImplicitClause)
17419 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
17420 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17421 ? RefExpr->IgnoreParens()
17422 : Ref);
17423 PrivateCopies.push_back(VDPrivateRefExpr);
17424 }
17425
17426 if (Vars.empty())
17427 return nullptr;
17428
17429 return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17430 Vars, PrivateCopies);
17431}
17432
17434 SourceLocation StartLoc,
17435 SourceLocation LParenLoc,
17436 SourceLocation EndLoc) {
17438 SmallVector<Expr *, 8> PrivateCopies;
17440 SmallVector<Decl *, 4> ExprCaptures;
17441 bool IsImplicitClause =
17442 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17443 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
17444
17445 for (Expr *RefExpr : VarList) {
17446 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
17447 SourceLocation ELoc;
17448 SourceRange ERange;
17449 Expr *SimpleRefExpr = RefExpr;
17450 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17451 if (Res.second) {
17452 // It will be analyzed later.
17453 Vars.push_back(RefExpr);
17454 PrivateCopies.push_back(nullptr);
17455 Inits.push_back(nullptr);
17456 }
17457 ValueDecl *D = Res.first;
17458 if (!D)
17459 continue;
17460
17461 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
17462 QualType Type = D->getType();
17463 auto *VD = dyn_cast<VarDecl>(D);
17464
17465 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17466 // A variable that appears in a private clause must not have an incomplete
17467 // type or a reference type.
17469 diag::err_omp_firstprivate_incomplete_type))
17470 continue;
17471 Type = Type.getNonReferenceType();
17472
17473 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
17474 // A variable of class type (or array thereof) that appears in a private
17475 // clause requires an accessible, unambiguous copy constructor for the
17476 // class type.
17477 QualType ElemType =
17479
17480 // If an implicit firstprivate variable found it was checked already.
17481 DSAStackTy::DSAVarData TopDVar;
17482 if (!IsImplicitClause) {
17483 DSAStackTy::DSAVarData DVar =
17484 DSAStack->getTopDSA(D, /*FromParent=*/false);
17485 TopDVar = DVar;
17486 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17487 bool IsConstant = ElemType.isConstant(getASTContext());
17488 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
17489 // A list item that specifies a given variable may not appear in more
17490 // than one clause on the same directive, except that a variable may be
17491 // specified in both firstprivate and lastprivate clauses.
17492 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
17493 // A list item may appear in a firstprivate or lastprivate clause but not
17494 // both.
17495 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
17496 (isOpenMPDistributeDirective(CurrDir) ||
17497 DVar.CKind != OMPC_lastprivate) &&
17498 DVar.RefExpr) {
17499 Diag(ELoc, diag::err_omp_wrong_dsa)
17500 << getOpenMPClauseName(DVar.CKind)
17501 << getOpenMPClauseName(OMPC_firstprivate);
17503 continue;
17504 }
17505
17506 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17507 // in a Construct]
17508 // Variables with the predetermined data-sharing attributes may not be
17509 // listed in data-sharing attributes clauses, except for the cases
17510 // listed below. For these exceptions only, listing a predetermined
17511 // variable in a data-sharing attribute clause is allowed and overrides
17512 // the variable's predetermined data-sharing attributes.
17513 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17514 // in a Construct, C/C++, p.2]
17515 // Variables with const-qualified type having no mutable member may be
17516 // listed in a firstprivate clause, even if they are static data members.
17517 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
17518 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
17519 Diag(ELoc, diag::err_omp_wrong_dsa)
17520 << getOpenMPClauseName(DVar.CKind)
17521 << getOpenMPClauseName(OMPC_firstprivate);
17523 continue;
17524 }
17525
17526 // OpenMP [2.9.3.4, Restrictions, p.2]
17527 // A list item that is private within a parallel region must not appear
17528 // in a firstprivate clause on a worksharing construct if any of the
17529 // worksharing regions arising from the worksharing construct ever bind
17530 // to any of the parallel regions arising from the parallel construct.
17531 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17532 // A list item that is private within a teams region must not appear in a
17533 // firstprivate clause on a distribute construct if any of the distribute
17534 // regions arising from the distribute construct ever bind to any of the
17535 // teams regions arising from the teams construct.
17536 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17537 // A list item that appears in a reduction clause of a teams construct
17538 // must not appear in a firstprivate clause on a distribute construct if
17539 // any of the distribute regions arising from the distribute construct
17540 // ever bind to any of the teams regions arising from the teams construct.
17541 if ((isOpenMPWorksharingDirective(CurrDir) ||
17542 isOpenMPDistributeDirective(CurrDir)) &&
17543 !isOpenMPParallelDirective(CurrDir) &&
17544 !isOpenMPTeamsDirective(CurrDir)) {
17545 DVar = DSAStack->getImplicitDSA(D, true);
17546 if (DVar.CKind != OMPC_shared &&
17547 (isOpenMPParallelDirective(DVar.DKind) ||
17548 isOpenMPTeamsDirective(DVar.DKind) ||
17549 DVar.DKind == OMPD_unknown)) {
17550 Diag(ELoc, diag::err_omp_required_access)
17551 << getOpenMPClauseName(OMPC_firstprivate)
17552 << getOpenMPClauseName(OMPC_shared);
17554 continue;
17555 }
17556 }
17557 // OpenMP [2.9.3.4, Restrictions, p.3]
17558 // A list item that appears in a reduction clause of a parallel construct
17559 // must not appear in a firstprivate clause on a worksharing or task
17560 // construct if any of the worksharing or task regions arising from the
17561 // worksharing or task construct ever bind to any of the parallel regions
17562 // arising from the parallel construct.
17563 // OpenMP [2.9.3.4, Restrictions, p.4]
17564 // A list item that appears in a reduction clause in worksharing
17565 // construct must not appear in a firstprivate clause in a task construct
17566 // encountered during execution of any of the worksharing regions arising
17567 // from the worksharing construct.
17568 if (isOpenMPTaskingDirective(CurrDir)) {
17569 DVar = DSAStack->hasInnermostDSA(
17570 D,
17571 [](OpenMPClauseKind C, bool AppliedToPointee) {
17572 return C == OMPC_reduction && !AppliedToPointee;
17573 },
17574 [](OpenMPDirectiveKind K) {
17575 return isOpenMPParallelDirective(K) ||
17578 },
17579 /*FromParent=*/true);
17580 if (DVar.CKind == OMPC_reduction &&
17581 (isOpenMPParallelDirective(DVar.DKind) ||
17582 isOpenMPWorksharingDirective(DVar.DKind) ||
17583 isOpenMPTeamsDirective(DVar.DKind))) {
17584 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
17585 << getOpenMPDirectiveName(DVar.DKind);
17587 continue;
17588 }
17589 }
17590
17591 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17592 // A list item cannot appear in both a map clause and a data-sharing
17593 // attribute clause on the same construct
17594 //
17595 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17596 // A list item cannot appear in both a map clause and a data-sharing
17597 // attribute clause on the same construct unless the construct is a
17598 // combined construct.
17599 if ((getLangOpts().OpenMP <= 45 &&
17601 CurrDir == OMPD_target) {
17602 OpenMPClauseKind ConflictKind;
17603 if (DSAStack->checkMappableExprComponentListsForDecl(
17604 VD, /*CurrentRegionOnly=*/true,
17605 [&ConflictKind](
17607 OpenMPClauseKind WhereFoundClauseKind) {
17608 ConflictKind = WhereFoundClauseKind;
17609 return true;
17610 })) {
17611 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17612 << getOpenMPClauseName(OMPC_firstprivate)
17613 << getOpenMPClauseName(ConflictKind)
17614 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
17616 continue;
17617 }
17618 }
17619 }
17620
17621 // Variably modified types are not supported for tasks.
17623 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
17624 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17625 << getOpenMPClauseName(OMPC_firstprivate) << Type
17626 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
17627 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17629 Diag(D->getLocation(),
17630 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17631 << D;
17632 continue;
17633 }
17634
17635 Type = Type.getUnqualifiedType();
17636 VarDecl *VDPrivate =
17637 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
17638 D->hasAttrs() ? &D->getAttrs() : nullptr,
17639 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
17640 // Generate helper private variable and initialize it with the value of the
17641 // original variable. The address of the original variable is replaced by
17642 // the address of the new private variable in the CodeGen. This new variable
17643 // is not added to IdResolver, so the code in the OpenMP region uses
17644 // original variable for proper diagnostics and variable capturing.
17645 Expr *VDInitRefExpr = nullptr;
17646 // For arrays generate initializer for single element and replace it by the
17647 // original array element in CodeGen.
17648 if (Type->isArrayType()) {
17649 VarDecl *VDInit =
17650 buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName());
17651 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc);
17652 Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get();
17653 ElemType = ElemType.getUnqualifiedType();
17654 VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(),
17655 ElemType, ".firstprivate.temp");
17656 InitializedEntity Entity =
17659
17660 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
17661 ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init);
17662 if (Result.isInvalid())
17663 VDPrivate->setInvalidDecl();
17664 else
17665 VDPrivate->setInit(Result.getAs<Expr>());
17666 // Remove temp variable declaration.
17667 getASTContext().Deallocate(VDInitTemp);
17668 } else {
17669 VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type,
17670 ".firstprivate.temp");
17671 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(),
17672 RefExpr->getExprLoc());
17674 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
17675 /*DirectInit=*/false);
17676 }
17677 if (VDPrivate->isInvalidDecl()) {
17678 if (IsImplicitClause) {
17679 Diag(RefExpr->getExprLoc(),
17680 diag::note_omp_task_predetermined_firstprivate_here);
17681 }
17682 continue;
17683 }
17684 SemaRef.CurContext->addDecl(VDPrivate);
17685 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
17686 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(),
17687 RefExpr->getExprLoc());
17688 DeclRefExpr *Ref = nullptr;
17689 if (!VD && !SemaRef.CurContext->isDependentContext()) {
17690 if (TopDVar.CKind == OMPC_lastprivate) {
17691 Ref = TopDVar.PrivateCopy;
17692 } else {
17693 auto *FD = dyn_cast<FieldDecl>(D);
17694 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
17695 if (VD)
17696 Ref =
17698 RefExpr->getExprLoc());
17699 else
17700 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
17701 if (VD || !isOpenMPCapturedDecl(D))
17702 ExprCaptures.push_back(Ref->getDecl());
17703 }
17704 }
17705 if (!IsImplicitClause)
17706 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
17707 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17708 ? RefExpr->IgnoreParens()
17709 : Ref);
17710 PrivateCopies.push_back(VDPrivateRefExpr);
17711 Inits.push_back(VDInitRefExpr);
17712 }
17713
17714 if (Vars.empty())
17715 return nullptr;
17716
17718 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
17719 buildPreInits(getASTContext(), ExprCaptures));
17720}
17721
17724 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
17725 SourceLocation LParenLoc, SourceLocation EndLoc) {
17726 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
17727 assert(ColonLoc.isValid() && "Colon location must be valid.");
17728 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
17729 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
17730 /*Last=*/OMPC_LASTPRIVATE_unknown)
17731 << getOpenMPClauseName(OMPC_lastprivate);
17732 return nullptr;
17733 }
17734
17736 SmallVector<Expr *, 8> SrcExprs;
17737 SmallVector<Expr *, 8> DstExprs;
17738 SmallVector<Expr *, 8> AssignmentOps;
17739 SmallVector<Decl *, 4> ExprCaptures;
17740 SmallVector<Expr *, 4> ExprPostUpdates;
17741 for (Expr *RefExpr : VarList) {
17742 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
17743 SourceLocation ELoc;
17744 SourceRange ERange;
17745 Expr *SimpleRefExpr = RefExpr;
17746 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17747 if (Res.second) {
17748 // It will be analyzed later.
17749 Vars.push_back(RefExpr);
17750 SrcExprs.push_back(nullptr);
17751 DstExprs.push_back(nullptr);
17752 AssignmentOps.push_back(nullptr);
17753 }
17754 ValueDecl *D = Res.first;
17755 if (!D)
17756 continue;
17757
17758 QualType Type = D->getType();
17759 auto *VD = dyn_cast<VarDecl>(D);
17760
17761 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
17762 // A variable that appears in a lastprivate clause must not have an
17763 // incomplete type or a reference type.
17765 diag::err_omp_lastprivate_incomplete_type))
17766 continue;
17767 Type = Type.getNonReferenceType();
17768
17769 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
17770 // A variable that is privatized must not have a const-qualified type
17771 // unless it is of class type with a mutable member. This restriction does
17772 // not apply to the firstprivate clause.
17773 //
17774 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
17775 // A variable that appears in a lastprivate clause must not have a
17776 // const-qualified type unless it is of class type with a mutable member.
17777 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc))
17778 continue;
17779
17780 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
17781 // A list item that appears in a lastprivate clause with the conditional
17782 // modifier must be a scalar variable.
17783 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
17784 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
17785 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17787 Diag(D->getLocation(),
17788 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17789 << D;
17790 continue;
17791 }
17792
17793 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17794 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
17795 // in a Construct]
17796 // Variables with the predetermined data-sharing attributes may not be
17797 // listed in data-sharing attributes clauses, except for the cases
17798 // listed below.
17799 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
17800 // A list item may appear in a firstprivate or lastprivate clause but not
17801 // both.
17802 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17803 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
17804 (isOpenMPDistributeDirective(CurrDir) ||
17805 DVar.CKind != OMPC_firstprivate) &&
17806 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
17807 Diag(ELoc, diag::err_omp_wrong_dsa)
17808 << getOpenMPClauseName(DVar.CKind)
17809 << getOpenMPClauseName(OMPC_lastprivate);
17811 continue;
17812 }
17813
17814 // OpenMP [2.14.3.5, Restrictions, p.2]
17815 // A list item that is private within a parallel region, or that appears in
17816 // the reduction clause of a parallel construct, must not appear in a
17817 // lastprivate clause on a worksharing construct if any of the corresponding
17818 // worksharing regions ever binds to any of the corresponding parallel
17819 // regions.
17820 DSAStackTy::DSAVarData TopDVar = DVar;
17821 if (isOpenMPWorksharingDirective(CurrDir) &&
17822 !isOpenMPParallelDirective(CurrDir) &&
17823 !isOpenMPTeamsDirective(CurrDir)) {
17824 DVar = DSAStack->getImplicitDSA(D, true);
17825 if (DVar.CKind != OMPC_shared) {
17826 Diag(ELoc, diag::err_omp_required_access)
17827 << getOpenMPClauseName(OMPC_lastprivate)
17828 << getOpenMPClauseName(OMPC_shared);
17830 continue;
17831 }
17832 }
17833
17834 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
17835 // A variable of class type (or array thereof) that appears in a
17836 // lastprivate clause requires an accessible, unambiguous default
17837 // constructor for the class type, unless the list item is also specified
17838 // in a firstprivate clause.
17839 // A variable of class type (or array thereof) that appears in a
17840 // lastprivate clause requires an accessible, unambiguous copy assignment
17841 // operator for the class type.
17843 VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(),
17844 Type.getUnqualifiedType(), ".lastprivate.src",
17845 D->hasAttrs() ? &D->getAttrs() : nullptr);
17846 DeclRefExpr *PseudoSrcExpr =
17847 buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc);
17848 VarDecl *DstVD =
17849 buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst",
17850 D->hasAttrs() ? &D->getAttrs() : nullptr);
17851 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
17852 // For arrays generate assignment operation for single element and replace
17853 // it by the original array element in CodeGen.
17854 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
17855 PseudoDstExpr, PseudoSrcExpr);
17856 if (AssignmentOp.isInvalid())
17857 continue;
17858 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
17859 /*DiscardedValue=*/false);
17860 if (AssignmentOp.isInvalid())
17861 continue;
17862
17863 DeclRefExpr *Ref = nullptr;
17864 if (!VD && !SemaRef.CurContext->isDependentContext()) {
17865 if (TopDVar.CKind == OMPC_firstprivate) {
17866 Ref = TopDVar.PrivateCopy;
17867 } else {
17868 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
17869 if (!isOpenMPCapturedDecl(D))
17870 ExprCaptures.push_back(Ref->getDecl());
17871 }
17872 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
17874 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
17876 if (!RefRes.isUsable())
17877 continue;
17878 ExprResult PostUpdateRes =
17879 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
17880 SimpleRefExpr, RefRes.get());
17881 if (!PostUpdateRes.isUsable())
17882 continue;
17883 ExprPostUpdates.push_back(
17884 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
17885 }
17886 }
17887 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
17888 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17889 ? RefExpr->IgnoreParens()
17890 : Ref);
17891 SrcExprs.push_back(PseudoSrcExpr);
17892 DstExprs.push_back(PseudoDstExpr);
17893 AssignmentOps.push_back(AssignmentOp.get());
17894 }
17895
17896 if (Vars.empty())
17897 return nullptr;
17898
17900 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
17901 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
17902 buildPreInits(getASTContext(), ExprCaptures),
17903 buildPostUpdate(SemaRef, ExprPostUpdates));
17904}
17905
17907 SourceLocation StartLoc,
17908 SourceLocation LParenLoc,
17909 SourceLocation EndLoc) {
17911 for (Expr *RefExpr : VarList) {
17912 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
17913 SourceLocation ELoc;
17914 SourceRange ERange;
17915 Expr *SimpleRefExpr = RefExpr;
17916 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17917 if (Res.second) {
17918 // It will be analyzed later.
17919 Vars.push_back(RefExpr);
17920 }
17921 ValueDecl *D = Res.first;
17922 if (!D)
17923 continue;
17924
17925 auto *VD = dyn_cast<VarDecl>(D);
17926 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17927 // in a Construct]
17928 // Variables with the predetermined data-sharing attributes may not be
17929 // listed in data-sharing attributes clauses, except for the cases
17930 // listed below. For these exceptions only, listing a predetermined
17931 // variable in a data-sharing attribute clause is allowed and overrides
17932 // the variable's predetermined data-sharing attributes.
17933 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17934 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
17935 DVar.RefExpr) {
17936 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17937 << getOpenMPClauseName(OMPC_shared);
17939 continue;
17940 }
17941
17942 DeclRefExpr *Ref = nullptr;
17943 if (!VD && isOpenMPCapturedDecl(D) &&
17945 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
17946 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
17947 Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext())
17948 ? RefExpr->IgnoreParens()
17949 : Ref);
17950 }
17951
17952 if (Vars.empty())
17953 return nullptr;
17954
17955 return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17956 Vars);
17957}
17958
17959namespace {
17960class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
17961 DSAStackTy *Stack;
17962
17963public:
17964 bool VisitDeclRefExpr(DeclRefExpr *E) {
17965 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
17966 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
17967 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
17968 return false;
17969 if (DVar.CKind != OMPC_unknown)
17970 return true;
17971 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
17972 VD,
17973 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
17974 return isOpenMPPrivate(C) && !AppliedToPointee;
17975 },
17976 [](OpenMPDirectiveKind) { return true; },
17977 /*FromParent=*/true);
17978 return DVarPrivate.CKind != OMPC_unknown;
17979 }
17980 return false;
17981 }
17982 bool VisitStmt(Stmt *S) {
17983 for (Stmt *Child : S->children()) {
17984 if (Child && Visit(Child))
17985 return true;
17986 }
17987 return false;
17988 }
17989 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
17990};
17991} // namespace
17992
17993namespace {
17994// Transform MemberExpression for specified FieldDecl of current class to
17995// DeclRefExpr to specified OMPCapturedExprDecl.
17996class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
17997 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
17998 ValueDecl *Field = nullptr;
17999 DeclRefExpr *CapturedExpr = nullptr;
18000
18001public:
18002 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
18003 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
18004
18005 ExprResult TransformMemberExpr(MemberExpr *E) {
18006 if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
18007 E->getMemberDecl() == Field) {
18008 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
18009 return CapturedExpr;
18010 }
18011 return BaseTransform::TransformMemberExpr(E);
18012 }
18013 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
18014};
18015} // namespace
18016
18017template <typename T, typename U>
18019 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
18020 for (U &Set : Lookups) {
18021 for (auto *D : Set) {
18022 if (T Res = Gen(cast<ValueDecl>(D)))
18023 return Res;
18024 }
18025 }
18026 return T();
18027}
18028
18030 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
18031
18032 for (auto *RD : D->redecls()) {
18033 // Don't bother with extra checks if we already know this one isn't visible.
18034 if (RD == D)
18035 continue;
18036
18037 auto ND = cast<NamedDecl>(RD);
18038 if (LookupResult::isVisible(SemaRef, ND))
18039 return ND;
18040 }
18041
18042 return nullptr;
18043}
18044
18045static void
18049 // Find all of the associated namespaces and classes based on the
18050 // arguments we have.
18051 Sema::AssociatedNamespaceSet AssociatedNamespaces;
18052 Sema::AssociatedClassSet AssociatedClasses;
18053 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
18054 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
18055 AssociatedClasses);
18056
18057 // C++ [basic.lookup.argdep]p3:
18058 // Let X be the lookup set produced by unqualified lookup (3.4.1)
18059 // and let Y be the lookup set produced by argument dependent
18060 // lookup (defined as follows). If X contains [...] then Y is
18061 // empty. Otherwise Y is the set of declarations found in the
18062 // namespaces associated with the argument types as described
18063 // below. The set of declarations found by the lookup of the name
18064 // is the union of X and Y.
18065 //
18066 // Here, we compute Y and add its members to the overloaded
18067 // candidate set.
18068 for (auto *NS : AssociatedNamespaces) {
18069 // When considering an associated namespace, the lookup is the
18070 // same as the lookup performed when the associated namespace is
18071 // used as a qualifier (3.4.3.2) except that:
18072 //
18073 // -- Any using-directives in the associated namespace are
18074 // ignored.
18075 //
18076 // -- Any namespace-scope friend functions declared in
18077 // associated classes are visible within their respective
18078 // namespaces even if they are not visible during an ordinary
18079 // lookup (11.4).
18080 DeclContext::lookup_result R = NS->lookup(Id.getName());
18081 for (auto *D : R) {
18082 auto *Underlying = D;
18083 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
18084 Underlying = USD->getTargetDecl();
18085
18086 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
18087 !isa<OMPDeclareMapperDecl>(Underlying))
18088 continue;
18089
18090 if (!SemaRef.isVisible(D)) {
18091 D = findAcceptableDecl(SemaRef, D);
18092 if (!D)
18093 continue;
18094 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
18095 Underlying = USD->getTargetDecl();
18096 }
18097 Lookups.emplace_back();
18098 Lookups.back().addDecl(Underlying);
18099 }
18100 }
18101}
18102
18103static ExprResult
18105 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
18106 const DeclarationNameInfo &ReductionId, QualType Ty,
18107 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
18108 if (ReductionIdScopeSpec.isInvalid())
18109 return ExprError();
18110 SmallVector<UnresolvedSet<8>, 4> Lookups;
18111 if (S) {
18112 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18113 Lookup.suppressDiagnostics();
18114 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec,
18115 /*ObjectType=*/QualType())) {
18116 NamedDecl *D = Lookup.getRepresentativeDecl();
18117 do {
18118 S = S->getParent();
18119 } while (S && !S->isDeclScope(D));
18120 if (S)
18121 S = S->getParent();
18122 Lookups.emplace_back();
18123 Lookups.back().append(Lookup.begin(), Lookup.end());
18124 Lookup.clear();
18125 }
18126 } else if (auto *ULE =
18127 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
18128 Lookups.push_back(UnresolvedSet<8>());
18129 Decl *PrevD = nullptr;
18130 for (NamedDecl *D : ULE->decls()) {
18131 if (D == PrevD)
18132 Lookups.push_back(UnresolvedSet<8>());
18133 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
18134 Lookups.back().addDecl(DRD);
18135 PrevD = D;
18136 }
18137 }
18138 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
18141 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
18142 return !D->isInvalidDecl() &&
18143 (D->getType()->isDependentType() ||
18144 D->getType()->isInstantiationDependentType() ||
18145 D->getType()->containsUnexpandedParameterPack());
18146 })) {
18147 UnresolvedSet<8> ResSet;
18148 for (const UnresolvedSet<8> &Set : Lookups) {
18149 if (Set.empty())
18150 continue;
18151 ResSet.append(Set.begin(), Set.end());
18152 // The last item marks the end of all declarations at the specified scope.
18153 ResSet.addDecl(Set[Set.size() - 1]);
18154 }
18156 SemaRef.Context, /*NamingClass=*/nullptr,
18157 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
18158 /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false,
18159 /*KnownInstantiationDependent=*/false);
18160 }
18161 // Lookup inside the classes.
18162 // C++ [over.match.oper]p3:
18163 // For a unary operator @ with an operand of a type whose
18164 // cv-unqualified version is T1, and for a binary operator @ with
18165 // a left operand of a type whose cv-unqualified version is T1 and
18166 // a right operand of a type whose cv-unqualified version is T2,
18167 // three sets of candidate functions, designated member
18168 // candidates, non-member candidates and built-in candidates, are
18169 // constructed as follows:
18170 // -- If T1 is a complete class type or a class currently being
18171 // defined, the set of member candidates is the result of the
18172 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
18173 // the set of member candidates is empty.
18174 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18175 Lookup.suppressDiagnostics();
18176 if (const auto *TyRec = Ty->getAs<RecordType>()) {
18177 // Complete the type if it can be completed.
18178 // If the type is neither complete nor being defined, bail out now.
18179 if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() ||
18180 TyRec->getDecl()->getDefinition()) {
18181 Lookup.clear();
18182 SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
18183 if (Lookup.empty()) {
18184 Lookups.emplace_back();
18185 Lookups.back().append(Lookup.begin(), Lookup.end());
18186 }
18187 }
18188 }
18189 // Perform ADL.
18190 if (SemaRef.getLangOpts().CPlusPlus)
18191 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
18192 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18193 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
18194 if (!D->isInvalidDecl() &&
18195 SemaRef.Context.hasSameType(D->getType(), Ty))
18196 return D;
18197 return nullptr;
18198 }))
18199 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
18200 VK_LValue, Loc);
18201 if (SemaRef.getLangOpts().CPlusPlus) {
18202 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18203 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
18204 if (!D->isInvalidDecl() &&
18205 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
18206 !Ty.isMoreQualifiedThan(D->getType(),
18207 SemaRef.getASTContext()))
18208 return D;
18209 return nullptr;
18210 })) {
18211 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
18212 /*DetectVirtual=*/false);
18213 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
18214 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
18215 VD->getType().getUnqualifiedType()))) {
18216 if (SemaRef.CheckBaseClassAccess(
18217 Loc, VD->getType(), Ty, Paths.front(),
18218 /*DiagID=*/0) != Sema::AR_inaccessible) {
18219 SemaRef.BuildBasePathArray(Paths, BasePath);
18220 return SemaRef.BuildDeclRefExpr(
18222 }
18223 }
18224 }
18225 }
18226 }
18227 if (ReductionIdScopeSpec.isSet()) {
18228 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
18229 << Ty << Range;
18230 return ExprError();
18231 }
18232 return ExprEmpty();
18233}
18234
18235namespace {
18236/// Data for the reduction-based clauses.
18237struct ReductionData {
18238 /// List of original reduction items.
18240 /// List of private copies of the reduction items.
18241 SmallVector<Expr *, 8> Privates;
18242 /// LHS expressions for the reduction_op expressions.
18244 /// RHS expressions for the reduction_op expressions.
18246 /// Reduction operation expression.
18247 SmallVector<Expr *, 8> ReductionOps;
18248 /// inscan copy operation expressions.
18249 SmallVector<Expr *, 8> InscanCopyOps;
18250 /// inscan copy temp array expressions for prefix sums.
18251 SmallVector<Expr *, 8> InscanCopyArrayTemps;
18252 /// inscan copy temp array element expressions for prefix sums.
18253 SmallVector<Expr *, 8> InscanCopyArrayElems;
18254 /// Taskgroup descriptors for the corresponding reduction items in
18255 /// in_reduction clauses.
18256 SmallVector<Expr *, 8> TaskgroupDescriptors;
18257 /// List of captures for clause.
18258 SmallVector<Decl *, 4> ExprCaptures;
18259 /// List of postupdate expressions.
18260 SmallVector<Expr *, 4> ExprPostUpdates;
18261 /// Reduction modifier.
18262 unsigned RedModifier = 0;
18263 ReductionData() = delete;
18264 /// Reserves required memory for the reduction data.
18265 ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
18266 Vars.reserve(Size);
18267 Privates.reserve(Size);
18268 LHSs.reserve(Size);
18269 RHSs.reserve(Size);
18270 ReductionOps.reserve(Size);
18271 if (RedModifier == OMPC_REDUCTION_inscan) {
18272 InscanCopyOps.reserve(Size);
18273 InscanCopyArrayTemps.reserve(Size);
18274 InscanCopyArrayElems.reserve(Size);
18275 }
18276 TaskgroupDescriptors.reserve(Size);
18277 ExprCaptures.reserve(Size);
18278 ExprPostUpdates.reserve(Size);
18279 }
18280 /// Stores reduction item and reduction operation only (required for dependent
18281 /// reduction item).
18282 void push(Expr *Item, Expr *ReductionOp) {
18283 Vars.emplace_back(Item);
18284 Privates.emplace_back(nullptr);
18285 LHSs.emplace_back(nullptr);
18286 RHSs.emplace_back(nullptr);
18287 ReductionOps.emplace_back(ReductionOp);
18288 TaskgroupDescriptors.emplace_back(nullptr);
18289 if (RedModifier == OMPC_REDUCTION_inscan) {
18290 InscanCopyOps.push_back(nullptr);
18291 InscanCopyArrayTemps.push_back(nullptr);
18292 InscanCopyArrayElems.push_back(nullptr);
18293 }
18294 }
18295 /// Stores reduction data.
18296 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
18297 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
18298 Expr *CopyArrayElem) {
18299 Vars.emplace_back(Item);
18300 Privates.emplace_back(Private);
18301 LHSs.emplace_back(LHS);
18302 RHSs.emplace_back(RHS);
18303 ReductionOps.emplace_back(ReductionOp);
18304 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
18305 if (RedModifier == OMPC_REDUCTION_inscan) {
18306 InscanCopyOps.push_back(CopyOp);
18307 InscanCopyArrayTemps.push_back(CopyArrayTemp);
18308 InscanCopyArrayElems.push_back(CopyArrayElem);
18309 } else {
18310 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
18311 CopyArrayElem == nullptr &&
18312 "Copy operation must be used for inscan reductions only.");
18313 }
18314 }
18315};
18316} // namespace
18317
18319 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
18320 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
18321 const Expr *Length = OASE->getLength();
18322 if (Length == nullptr) {
18323 // For array sections of the form [1:] or [:], we would need to analyze
18324 // the lower bound...
18325 if (OASE->getColonLocFirst().isValid())
18326 return false;
18327
18328 // This is an array subscript which has implicit length 1!
18329 SingleElement = true;
18330 ArraySizes.push_back(llvm::APSInt::get(1));
18331 } else {
18333 if (!Length->EvaluateAsInt(Result, Context))
18334 return false;
18335
18336 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18337 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
18338 ArraySizes.push_back(ConstantLengthValue);
18339 }
18340
18341 // Get the base of this array section and walk up from there.
18342 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
18343
18344 // We require length = 1 for all array sections except the right-most to
18345 // guarantee that the memory region is contiguous and has no holes in it.
18346 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) {
18347 Length = TempOASE->getLength();
18348 if (Length == nullptr) {
18349 // For array sections of the form [1:] or [:], we would need to analyze
18350 // the lower bound...
18351 if (OASE->getColonLocFirst().isValid())
18352 return false;
18353
18354 // This is an array subscript which has implicit length 1!
18355 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
18356 ArraySizes.push_back(ConstantOne);
18357 } else {
18359 if (!Length->EvaluateAsInt(Result, Context))
18360 return false;
18361
18362 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18363 if (ConstantLengthValue.getSExtValue() != 1)
18364 return false;
18365
18366 ArraySizes.push_back(ConstantLengthValue);
18367 }
18368 Base = TempOASE->getBase()->IgnoreParenImpCasts();
18369 }
18370
18371 // If we have a single element, we don't need to add the implicit lengths.
18372 if (!SingleElement) {
18373 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
18374 // Has implicit length 1!
18375 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
18376 ArraySizes.push_back(ConstantOne);
18377 Base = TempASE->getBase()->IgnoreParenImpCasts();
18378 }
18379 }
18380
18381 // This array section can be privatized as a single value or as a constant
18382 // sized array.
18383 return true;
18384}
18385
18386static BinaryOperatorKind
18388 if (BOK == BO_Add)
18389 return BO_AddAssign;
18390 if (BOK == BO_Mul)
18391 return BO_MulAssign;
18392 if (BOK == BO_And)
18393 return BO_AndAssign;
18394 if (BOK == BO_Or)
18395 return BO_OrAssign;
18396 if (BOK == BO_Xor)
18397 return BO_XorAssign;
18398 return BOK;
18399}
18400
18402 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
18403 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
18404 SourceLocation ColonLoc, SourceLocation EndLoc,
18405 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
18406 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
18407 DeclarationName DN = ReductionId.getName();
18409 BinaryOperatorKind BOK = BO_Comma;
18410
18411 ASTContext &Context = S.Context;
18412 // OpenMP [2.14.3.6, reduction clause]
18413 // C
18414 // reduction-identifier is either an identifier or one of the following
18415 // operators: +, -, *, &, |, ^, && and ||
18416 // C++
18417 // reduction-identifier is either an id-expression or one of the following
18418 // operators: +, -, *, &, |, ^, && and ||
18419 switch (OOK) {
18420 case OO_Plus:
18421 BOK = BO_Add;
18422 break;
18423 case OO_Minus:
18424 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
18425 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
18426 // reduction identifier.
18427 if (S.LangOpts.OpenMP > 52)
18428 BOK = BO_Comma;
18429 else
18430 BOK = BO_Add;
18431 break;
18432 case OO_Star:
18433 BOK = BO_Mul;
18434 break;
18435 case OO_Amp:
18436 BOK = BO_And;
18437 break;
18438 case OO_Pipe:
18439 BOK = BO_Or;
18440 break;
18441 case OO_Caret:
18442 BOK = BO_Xor;
18443 break;
18444 case OO_AmpAmp:
18445 BOK = BO_LAnd;
18446 break;
18447 case OO_PipePipe:
18448 BOK = BO_LOr;
18449 break;
18450 case OO_New:
18451 case OO_Delete:
18452 case OO_Array_New:
18453 case OO_Array_Delete:
18454 case OO_Slash:
18455 case OO_Percent:
18456 case OO_Tilde:
18457 case OO_Exclaim:
18458 case OO_Equal:
18459 case OO_Less:
18460 case OO_Greater:
18461 case OO_LessEqual:
18462 case OO_GreaterEqual:
18463 case OO_PlusEqual:
18464 case OO_MinusEqual:
18465 case OO_StarEqual:
18466 case OO_SlashEqual:
18467 case OO_PercentEqual:
18468 case OO_CaretEqual:
18469 case OO_AmpEqual:
18470 case OO_PipeEqual:
18471 case OO_LessLess:
18472 case OO_GreaterGreater:
18473 case OO_LessLessEqual:
18474 case OO_GreaterGreaterEqual:
18475 case OO_EqualEqual:
18476 case OO_ExclaimEqual:
18477 case OO_Spaceship:
18478 case OO_PlusPlus:
18479 case OO_MinusMinus:
18480 case OO_Comma:
18481 case OO_ArrowStar:
18482 case OO_Arrow:
18483 case OO_Call:
18484 case OO_Subscript:
18485 case OO_Conditional:
18486 case OO_Coawait:
18488 llvm_unreachable("Unexpected reduction identifier");
18489 case OO_None:
18490 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
18491 if (II->isStr("max"))
18492 BOK = BO_GT;
18493 else if (II->isStr("min"))
18494 BOK = BO_LT;
18495 }
18496 break;
18497 }
18498
18499 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
18500 // A reduction clause with the minus (-) operator was deprecated
18501 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
18502 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
18503
18504 SourceRange ReductionIdRange;
18505 if (ReductionIdScopeSpec.isValid())
18506 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
18507 else
18508 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
18509 ReductionIdRange.setEnd(ReductionId.getEndLoc());
18510
18511 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
18512 bool FirstIter = true;
18513 for (Expr *RefExpr : VarList) {
18514 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
18515 // OpenMP [2.1, C/C++]
18516 // A list item is a variable or array section, subject to the restrictions
18517 // specified in Section 2.4 on page 42 and in each of the sections
18518 // describing clauses and directives for which a list appears.
18519 // OpenMP [2.14.3.3, Restrictions, p.1]
18520 // A variable that is part of another variable (as an array or
18521 // structure element) cannot appear in a private clause.
18522 if (!FirstIter && IR != ER)
18523 ++IR;
18524 FirstIter = false;
18525 SourceLocation ELoc;
18526 SourceRange ERange;
18527 Expr *SimpleRefExpr = RefExpr;
18528 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
18529 /*AllowArraySection=*/true);
18530 if (Res.second) {
18531 // Try to find 'declare reduction' corresponding construct before using
18532 // builtin/overloaded operators.
18533 QualType Type = Context.DependentTy;
18534 CXXCastPath BasePath;
18535 ExprResult DeclareReductionRef = buildDeclareReductionRef(
18536 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18537 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
18538 Expr *ReductionOp = nullptr;
18539 if (S.CurContext->isDependentContext() &&
18540 (DeclareReductionRef.isUnset() ||
18541 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
18542 ReductionOp = DeclareReductionRef.get();
18543 // It will be analyzed later.
18544 RD.push(RefExpr, ReductionOp);
18545 }
18546 ValueDecl *D = Res.first;
18547 if (!D)
18548 continue;
18549
18550 Expr *TaskgroupDescriptor = nullptr;
18551 QualType Type;
18552 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
18553 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
18554 if (ASE) {
18555 Type = ASE->getType().getNonReferenceType();
18556 } else if (OASE) {
18557 QualType BaseType =
18559 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
18560 Type = ATy->getElementType();
18561 else
18562 Type = BaseType->getPointeeType();
18563 Type = Type.getNonReferenceType();
18564 } else {
18565 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
18566 }
18567 auto *VD = dyn_cast<VarDecl>(D);
18568
18569 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18570 // A variable that appears in a private clause must not have an incomplete
18571 // type or a reference type.
18572 if (S.RequireCompleteType(ELoc, D->getType(),
18573 diag::err_omp_reduction_incomplete_type))
18574 continue;
18575 // OpenMP [2.14.3.6, reduction clause, Restrictions]
18576 // A list item that appears in a reduction clause must not be
18577 // const-qualified.
18578 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
18579 /*AcceptIfMutable=*/false, ASE || OASE))
18580 continue;
18581
18582 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
18583 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
18584 // If a list-item is a reference type then it must bind to the same object
18585 // for all threads of the team.
18586 if (!ASE && !OASE) {
18587 if (VD) {
18588 VarDecl *VDDef = VD->getDefinition();
18589 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
18590 DSARefChecker Check(Stack);
18591 if (Check.Visit(VDDef->getInit())) {
18592 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
18593 << getOpenMPClauseName(ClauseKind) << ERange;
18594 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
18595 continue;
18596 }
18597 }
18598 }
18599
18600 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18601 // in a Construct]
18602 // Variables with the predetermined data-sharing attributes may not be
18603 // listed in data-sharing attributes clauses, except for the cases
18604 // listed below. For these exceptions only, listing a predetermined
18605 // variable in a data-sharing attribute clause is allowed and overrides
18606 // the variable's predetermined data-sharing attributes.
18607 // OpenMP [2.14.3.6, Restrictions, p.3]
18608 // Any number of reduction clauses can be specified on the directive,
18609 // but a list item can appear only once in the reduction clauses for that
18610 // directive.
18611 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
18612 if (DVar.CKind == OMPC_reduction) {
18613 S.Diag(ELoc, diag::err_omp_once_referenced)
18614 << getOpenMPClauseName(ClauseKind);
18615 if (DVar.RefExpr)
18616 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
18617 continue;
18618 }
18619 if (DVar.CKind != OMPC_unknown) {
18620 S.Diag(ELoc, diag::err_omp_wrong_dsa)
18621 << getOpenMPClauseName(DVar.CKind)
18622 << getOpenMPClauseName(OMPC_reduction);
18623 reportOriginalDsa(S, Stack, D, DVar);
18624 continue;
18625 }
18626
18627 // OpenMP [2.14.3.6, Restrictions, p.1]
18628 // A list item that appears in a reduction clause of a worksharing
18629 // construct must be shared in the parallel regions to which any of the
18630 // worksharing regions arising from the worksharing construct bind.
18631 if (isOpenMPWorksharingDirective(CurrDir) &&
18632 !isOpenMPParallelDirective(CurrDir) &&
18633 !isOpenMPTeamsDirective(CurrDir)) {
18634 DVar = Stack->getImplicitDSA(D, true);
18635 if (DVar.CKind != OMPC_shared) {
18636 S.Diag(ELoc, diag::err_omp_required_access)
18637 << getOpenMPClauseName(OMPC_reduction)
18638 << getOpenMPClauseName(OMPC_shared);
18639 reportOriginalDsa(S, Stack, D, DVar);
18640 continue;
18641 }
18642 }
18643 } else {
18644 // Threadprivates cannot be shared between threads, so dignose if the base
18645 // is a threadprivate variable.
18646 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
18647 if (DVar.CKind == OMPC_threadprivate) {
18648 S.Diag(ELoc, diag::err_omp_wrong_dsa)
18649 << getOpenMPClauseName(DVar.CKind)
18650 << getOpenMPClauseName(OMPC_reduction);
18651 reportOriginalDsa(S, Stack, D, DVar);
18652 continue;
18653 }
18654 }
18655
18656 // Try to find 'declare reduction' corresponding construct before using
18657 // builtin/overloaded operators.
18658 CXXCastPath BasePath;
18659 ExprResult DeclareReductionRef = buildDeclareReductionRef(
18660 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18661 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
18662 if (DeclareReductionRef.isInvalid())
18663 continue;
18664 if (S.CurContext->isDependentContext() &&
18665 (DeclareReductionRef.isUnset() ||
18666 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
18667 RD.push(RefExpr, DeclareReductionRef.get());
18668 continue;
18669 }
18670 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
18671 // Not allowed reduction identifier is found.
18672 if (S.LangOpts.OpenMP > 52)
18673 S.Diag(ReductionId.getBeginLoc(),
18674 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
18675 << Type << ReductionIdRange;
18676 else
18677 S.Diag(ReductionId.getBeginLoc(),
18678 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
18679 << Type << ReductionIdRange;
18680 continue;
18681 }
18682
18683 // OpenMP [2.14.3.6, reduction clause, Restrictions]
18684 // The type of a list item that appears in a reduction clause must be valid
18685 // for the reduction-identifier. For a max or min reduction in C, the type
18686 // of the list item must be an allowed arithmetic data type: char, int,
18687 // float, double, or _Bool, possibly modified with long, short, signed, or
18688 // unsigned. For a max or min reduction in C++, the type of the list item
18689 // must be an allowed arithmetic data type: char, wchar_t, int, float,
18690 // double, or bool, possibly modified with long, short, signed, or unsigned.
18691 if (DeclareReductionRef.isUnset()) {
18692 if ((BOK == BO_GT || BOK == BO_LT) &&
18693 !(Type->isScalarType() ||
18694 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
18695 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
18696 << getOpenMPClauseName(ClauseKind) << S.getLangOpts().CPlusPlus;
18697 if (!ASE && !OASE) {
18698 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18700 S.Diag(D->getLocation(),
18701 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18702 << D;
18703 }
18704 continue;
18705 }
18706 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
18707 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
18708 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
18709 << getOpenMPClauseName(ClauseKind);
18710 if (!ASE && !OASE) {
18711 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18713 S.Diag(D->getLocation(),
18714 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18715 << D;
18716 }
18717 continue;
18718 }
18719 }
18720
18721 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
18722 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
18723 D->hasAttrs() ? &D->getAttrs() : nullptr);
18724 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
18725 D->hasAttrs() ? &D->getAttrs() : nullptr);
18726 QualType PrivateTy = Type;
18727
18728 // Try if we can determine constant lengths for all array sections and avoid
18729 // the VLA.
18730 bool ConstantLengthOASE = false;
18731 if (OASE) {
18732 bool SingleElement;
18734 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
18735 Context, OASE, SingleElement, ArraySizes);
18736
18737 // If we don't have a single element, we must emit a constant array type.
18738 if (ConstantLengthOASE && !SingleElement) {
18739 for (llvm::APSInt &Size : ArraySizes)
18740 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
18742 /*IndexTypeQuals=*/0);
18743 }
18744 }
18745
18746 if ((OASE && !ConstantLengthOASE) ||
18747 (!OASE && !ASE &&
18748 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
18749 if (!Context.getTargetInfo().isVLASupported()) {
18750 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
18751 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18752 S.Diag(ELoc, diag::note_vla_unsupported);
18753 continue;
18754 } else {
18755 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18756 S.targetDiag(ELoc, diag::note_vla_unsupported);
18757 }
18758 }
18759 // For arrays/array sections only:
18760 // Create pseudo array type for private copy. The size for this array will
18761 // be generated during codegen.
18762 // For array subscripts or single variables Private Ty is the same as Type
18763 // (type of the variable or single array element).
18764 PrivateTy = Context.getVariableArrayType(
18765 Type,
18766 new (Context)
18767 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
18768 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0, SourceRange());
18769 } else if (!ASE && !OASE &&
18770 Context.getAsArrayType(D->getType().getNonReferenceType())) {
18771 PrivateTy = D->getType().getNonReferenceType();
18772 }
18773 // Private copy.
18774 VarDecl *PrivateVD =
18775 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
18776 D->hasAttrs() ? &D->getAttrs() : nullptr,
18777 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18778 // Add initializer for private variable.
18779 Expr *Init = nullptr;
18780 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
18781 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
18782 if (DeclareReductionRef.isUsable()) {
18783 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
18784 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
18785 if (DRD->getInitializer()) {
18786 Init = DRDRef;
18787 RHSVD->setInit(DRDRef);
18789 }
18790 } else {
18791 switch (BOK) {
18792 case BO_Add:
18793 case BO_Xor:
18794 case BO_Or:
18795 case BO_LOr:
18796 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
18798 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
18799 break;
18800 case BO_Mul:
18801 case BO_LAnd:
18802 if (Type->isScalarType() || Type->isAnyComplexType()) {
18803 // '*' and '&&' reduction ops - initializer is '1'.
18804 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
18805 }
18806 break;
18807 case BO_And: {
18808 // '&' reduction op - initializer is '~0'.
18809 QualType OrigType = Type;
18810 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
18811 Type = ComplexTy->getElementType();
18812 if (Type->isRealFloatingType()) {
18813 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
18814 Context.getFloatTypeSemantics(Type));
18815 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
18816 Type, ELoc);
18817 } else if (Type->isScalarType()) {
18818 uint64_t Size = Context.getTypeSize(Type);
18819 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
18820 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
18821 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
18822 }
18823 if (Init && OrigType->isAnyComplexType()) {
18824 // Init = 0xFFFF + 0xFFFFi;
18825 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
18826 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
18827 }
18828 Type = OrigType;
18829 break;
18830 }
18831 case BO_LT:
18832 case BO_GT: {
18833 // 'min' reduction op - initializer is 'Largest representable number in
18834 // the reduction list item type'.
18835 // 'max' reduction op - initializer is 'Least representable number in
18836 // the reduction list item type'.
18837 if (Type->isIntegerType() || Type->isPointerType()) {
18838 bool IsSigned = Type->hasSignedIntegerRepresentation();
18839 uint64_t Size = Context.getTypeSize(Type);
18840 QualType IntTy =
18841 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
18842 llvm::APInt InitValue =
18843 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
18844 : llvm::APInt::getMinValue(Size)
18845 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
18846 : llvm::APInt::getMaxValue(Size);
18847 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
18848 if (Type->isPointerType()) {
18849 // Cast to pointer type.
18851 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
18852 if (CastExpr.isInvalid())
18853 continue;
18854 Init = CastExpr.get();
18855 }
18856 } else if (Type->isRealFloatingType()) {
18857 llvm::APFloat InitValue = llvm::APFloat::getLargest(
18858 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
18859 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
18860 Type, ELoc);
18861 }
18862 break;
18863 }
18864 case BO_PtrMemD:
18865 case BO_PtrMemI:
18866 case BO_MulAssign:
18867 case BO_Div:
18868 case BO_Rem:
18869 case BO_Sub:
18870 case BO_Shl:
18871 case BO_Shr:
18872 case BO_LE:
18873 case BO_GE:
18874 case BO_EQ:
18875 case BO_NE:
18876 case BO_Cmp:
18877 case BO_AndAssign:
18878 case BO_XorAssign:
18879 case BO_OrAssign:
18880 case BO_Assign:
18881 case BO_AddAssign:
18882 case BO_SubAssign:
18883 case BO_DivAssign:
18884 case BO_RemAssign:
18885 case BO_ShlAssign:
18886 case BO_ShrAssign:
18887 case BO_Comma:
18888 llvm_unreachable("Unexpected reduction operation");
18889 }
18890 }
18891 if (Init && DeclareReductionRef.isUnset()) {
18892 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
18893 // Store initializer for single element in private copy. Will be used
18894 // during codegen.
18895 PrivateVD->setInit(RHSVD->getInit());
18896 PrivateVD->setInitStyle(RHSVD->getInitStyle());
18897 } else if (!Init) {
18898 S.ActOnUninitializedDecl(RHSVD);
18899 // Store initializer for single element in private copy. Will be used
18900 // during codegen.
18901 PrivateVD->setInit(RHSVD->getInit());
18902 PrivateVD->setInitStyle(RHSVD->getInitStyle());
18903 }
18904 if (RHSVD->isInvalidDecl())
18905 continue;
18906 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
18907 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
18908 << Type << ReductionIdRange;
18909 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18911 S.Diag(D->getLocation(),
18912 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18913 << D;
18914 continue;
18915 }
18916 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
18917 ExprResult ReductionOp;
18918 if (DeclareReductionRef.isUsable()) {
18919 QualType RedTy = DeclareReductionRef.get()->getType();
18920 QualType PtrRedTy = Context.getPointerType(RedTy);
18921 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
18922 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
18923 if (!BasePath.empty()) {
18924 LHS = S.DefaultLvalueConversion(LHS.get());
18925 RHS = S.DefaultLvalueConversion(RHS.get());
18927 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
18928 LHS.get()->getValueKind(), FPOptionsOverride());
18930 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
18931 RHS.get()->getValueKind(), FPOptionsOverride());
18932 }
18934 QualType Params[] = {PtrRedTy, PtrRedTy};
18935 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
18936 auto *OVE = new (Context) OpaqueValueExpr(
18937 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
18938 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
18939 Expr *Args[] = {LHS.get(), RHS.get()};
18940 ReductionOp =
18941 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
18943 } else {
18945 if (Type->isRecordType() && CombBOK != BOK) {
18947 ReductionOp =
18948 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
18949 CombBOK, LHSDRE, RHSDRE);
18950 }
18951 if (!ReductionOp.isUsable()) {
18952 ReductionOp =
18953 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
18954 LHSDRE, RHSDRE);
18955 if (ReductionOp.isUsable()) {
18956 if (BOK != BO_LT && BOK != BO_GT) {
18957 ReductionOp =
18958 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
18959 BO_Assign, LHSDRE, ReductionOp.get());
18960 } else {
18961 auto *ConditionalOp = new (Context)
18962 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
18963 RHSDRE, Type, VK_LValue, OK_Ordinary);
18964 ReductionOp =
18965 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
18966 BO_Assign, LHSDRE, ConditionalOp);
18967 }
18968 }
18969 }
18970 if (ReductionOp.isUsable())
18971 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
18972 /*DiscardedValue=*/false);
18973 if (!ReductionOp.isUsable())
18974 continue;
18975 }
18976
18977 // Add copy operations for inscan reductions.
18978 // LHS = RHS;
18979 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
18980 if (ClauseKind == OMPC_reduction &&
18981 RD.RedModifier == OMPC_REDUCTION_inscan) {
18982 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
18983 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
18984 RHS.get());
18985 if (!CopyOpRes.isUsable())
18986 continue;
18987 CopyOpRes =
18988 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
18989 if (!CopyOpRes.isUsable())
18990 continue;
18991 // For simd directive and simd-based directives in simd mode no need to
18992 // construct temp array, need just a single temp element.
18993 if (Stack->getCurrentDirective() == OMPD_simd ||
18994 (S.getLangOpts().OpenMPSimd &&
18995 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
18996 VarDecl *TempArrayVD =
18997 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
18998 D->hasAttrs() ? &D->getAttrs() : nullptr);
18999 // Add a constructor to the temp decl.
19000 S.ActOnUninitializedDecl(TempArrayVD);
19001 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
19002 } else {
19003 // Build temp array for prefix sum.
19004 auto *Dim = new (S.Context)
19007 PrivateTy, Dim, ArraySizeModifier::Normal,
19008 /*IndexTypeQuals=*/0, {ELoc, ELoc});
19009 VarDecl *TempArrayVD =
19010 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
19011 D->hasAttrs() ? &D->getAttrs() : nullptr);
19012 // Add a constructor to the temp decl.
19013 S.ActOnUninitializedDecl(TempArrayVD);
19014 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
19015 TempArrayElem =
19016 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
19017 auto *Idx = new (S.Context)
19019 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
19020 ELoc, Idx, ELoc);
19021 }
19022 }
19023
19024 // OpenMP [2.15.4.6, Restrictions, p.2]
19025 // A list item that appears in an in_reduction clause of a task construct
19026 // must appear in a task_reduction clause of a construct associated with a
19027 // taskgroup region that includes the participating task in its taskgroup
19028 // set. The construct associated with the innermost region that meets this
19029 // condition must specify the same reduction-identifier as the in_reduction
19030 // clause.
19031 if (ClauseKind == OMPC_in_reduction) {
19032 SourceRange ParentSR;
19033 BinaryOperatorKind ParentBOK;
19034 const Expr *ParentReductionOp = nullptr;
19035 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
19036 DSAStackTy::DSAVarData ParentBOKDSA =
19037 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
19038 ParentBOKTD);
19039 DSAStackTy::DSAVarData ParentReductionOpDSA =
19040 Stack->getTopMostTaskgroupReductionData(
19041 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
19042 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
19043 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
19044 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
19045 (DeclareReductionRef.isUsable() && IsParentBOK) ||
19046 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
19047 bool EmitError = true;
19048 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
19049 llvm::FoldingSetNodeID RedId, ParentRedId;
19050 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
19051 DeclareReductionRef.get()->Profile(RedId, Context,
19052 /*Canonical=*/true);
19053 EmitError = RedId != ParentRedId;
19054 }
19055 if (EmitError) {
19056 S.Diag(ReductionId.getBeginLoc(),
19057 diag::err_omp_reduction_identifier_mismatch)
19058 << ReductionIdRange << RefExpr->getSourceRange();
19059 S.Diag(ParentSR.getBegin(),
19060 diag::note_omp_previous_reduction_identifier)
19061 << ParentSR
19062 << (IsParentBOK ? ParentBOKDSA.RefExpr
19063 : ParentReductionOpDSA.RefExpr)
19064 ->getSourceRange();
19065 continue;
19066 }
19067 }
19068 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
19069 }
19070
19071 DeclRefExpr *Ref = nullptr;
19072 Expr *VarsExpr = RefExpr->IgnoreParens();
19073 if (!VD && !S.CurContext->isDependentContext()) {
19074 if (ASE || OASE) {
19075 TransformExprToCaptures RebuildToCapture(S, D);
19076 VarsExpr =
19077 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
19078 Ref = RebuildToCapture.getCapturedExpr();
19079 } else {
19080 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
19081 }
19082 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
19083 RD.ExprCaptures.emplace_back(Ref->getDecl());
19084 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19085 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
19086 if (!RefRes.isUsable())
19087 continue;
19088 ExprResult PostUpdateRes =
19089 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
19090 RefRes.get());
19091 if (!PostUpdateRes.isUsable())
19092 continue;
19093 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
19094 Stack->getCurrentDirective() == OMPD_taskgroup) {
19095 S.Diag(RefExpr->getExprLoc(),
19096 diag::err_omp_reduction_non_addressable_expression)
19097 << RefExpr->getSourceRange();
19098 continue;
19099 }
19100 RD.ExprPostUpdates.emplace_back(
19101 S.IgnoredValueConversions(PostUpdateRes.get()).get());
19102 }
19103 }
19104 }
19105 // All reduction items are still marked as reduction (to do not increase
19106 // code base size).
19107 unsigned Modifier = RD.RedModifier;
19108 // Consider task_reductions as reductions with task modifier. Required for
19109 // correct analysis of in_reduction clauses.
19110 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
19111 Modifier = OMPC_REDUCTION_task;
19112 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
19113 ASE || OASE);
19114 if (Modifier == OMPC_REDUCTION_task &&
19115 (CurrDir == OMPD_taskgroup ||
19116 ((isOpenMPParallelDirective(CurrDir) ||
19117 isOpenMPWorksharingDirective(CurrDir)) &&
19118 !isOpenMPSimdDirective(CurrDir)))) {
19119 if (DeclareReductionRef.isUsable())
19120 Stack->addTaskgroupReductionData(D, ReductionIdRange,
19121 DeclareReductionRef.get());
19122 else
19123 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
19124 }
19125 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
19126 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
19127 TempArrayElem.get());
19128 }
19129 return RD.Vars.empty();
19130}
19131
19134 SourceLocation StartLoc, SourceLocation LParenLoc,
19135 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
19136 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19137 ArrayRef<Expr *> UnresolvedReductions) {
19138 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
19139 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
19140 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
19141 /*Last=*/OMPC_REDUCTION_unknown)
19142 << getOpenMPClauseName(OMPC_reduction);
19143 return nullptr;
19144 }
19145 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
19146 // A reduction clause with the inscan reduction-modifier may only appear on a
19147 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
19148 // construct, a parallel worksharing-loop construct or a parallel
19149 // worksharing-loop SIMD construct.
19150 if (Modifier == OMPC_REDUCTION_inscan &&
19151 (DSAStack->getCurrentDirective() != OMPD_for &&
19152 DSAStack->getCurrentDirective() != OMPD_for_simd &&
19153 DSAStack->getCurrentDirective() != OMPD_simd &&
19154 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
19155 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
19156 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
19157 return nullptr;
19158 }
19159
19160 ReductionData RD(VarList.size(), Modifier);
19161 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
19162 StartLoc, LParenLoc, ColonLoc, EndLoc,
19163 ReductionIdScopeSpec, ReductionId,
19164 UnresolvedReductions, RD))
19165 return nullptr;
19166
19168 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
19169 Modifier, RD.Vars,
19170 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19171 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
19172 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
19173 buildPreInits(getASTContext(), RD.ExprCaptures),
19174 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
19175}
19176
19178 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19179 SourceLocation ColonLoc, SourceLocation EndLoc,
19180 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19181 ArrayRef<Expr *> UnresolvedReductions) {
19182 ReductionData RD(VarList.size());
19183 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction,
19184 VarList, StartLoc, LParenLoc, ColonLoc,
19185 EndLoc, ReductionIdScopeSpec, ReductionId,
19186 UnresolvedReductions, RD))
19187 return nullptr;
19188
19190 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19191 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19192 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
19193 buildPreInits(getASTContext(), RD.ExprCaptures),
19194 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
19195}
19196
19198 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19199 SourceLocation ColonLoc, SourceLocation EndLoc,
19200 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19201 ArrayRef<Expr *> UnresolvedReductions) {
19202 ReductionData RD(VarList.size());
19203 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList,
19204 StartLoc, LParenLoc, ColonLoc, EndLoc,
19205 ReductionIdScopeSpec, ReductionId,
19206 UnresolvedReductions, RD))
19207 return nullptr;
19208
19210 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19211 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19212 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
19213 buildPreInits(getASTContext(), RD.ExprCaptures),
19214 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
19215}
19216
19218 SourceLocation LinLoc) {
19219 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
19220 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
19221 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
19222 << getLangOpts().CPlusPlus;
19223 return true;
19224 }
19225 return false;
19226}
19227
19229 OpenMPLinearClauseKind LinKind,
19230 QualType Type, bool IsDeclareSimd) {
19231 const auto *VD = dyn_cast_or_null<VarDecl>(D);
19232 // A variable must not have an incomplete type or a reference type.
19234 diag::err_omp_linear_incomplete_type))
19235 return true;
19236 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
19237 !Type->isReferenceType()) {
19238 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
19239 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
19240 return true;
19241 }
19242 Type = Type.getNonReferenceType();
19243
19244 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19245 // A variable that is privatized must not have a const-qualified type
19246 // unless it is of class type with a mutable member. This restriction does
19247 // not apply to the firstprivate clause, nor to the linear clause on
19248 // declarative directives (like declare simd).
19249 if (!IsDeclareSimd &&
19250 rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc))
19251 return true;
19252
19253 // A list item must be of integral or pointer type.
19254 Type = Type.getUnqualifiedType().getCanonicalType();
19255 const auto *Ty = Type.getTypePtrOrNull();
19256 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
19257 !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) {
19258 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
19259 if (D) {
19260 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19262 Diag(D->getLocation(),
19263 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19264 << D;
19265 }
19266 return true;
19267 }
19268 return false;
19269}
19270
19272 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
19273 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
19274 SourceLocation LinLoc, SourceLocation ColonLoc,
19275 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
19277 SmallVector<Expr *, 8> Privates;
19279 SmallVector<Decl *, 4> ExprCaptures;
19280 SmallVector<Expr *, 4> ExprPostUpdates;
19281 // OpenMP 5.2 [Section 5.4.6, linear clause]
19282 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
19283 // 'ref'
19284 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
19285 getLangOpts().OpenMP >= 52)
19286 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
19287 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
19288 LinKind = OMPC_LINEAR_val;
19289 for (Expr *RefExpr : VarList) {
19290 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19291 SourceLocation ELoc;
19292 SourceRange ERange;
19293 Expr *SimpleRefExpr = RefExpr;
19294 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19295 if (Res.second) {
19296 // It will be analyzed later.
19297 Vars.push_back(RefExpr);
19298 Privates.push_back(nullptr);
19299 Inits.push_back(nullptr);
19300 }
19301 ValueDecl *D = Res.first;
19302 if (!D)
19303 continue;
19304
19305 QualType Type = D->getType();
19306 auto *VD = dyn_cast<VarDecl>(D);
19307
19308 // OpenMP [2.14.3.7, linear clause]
19309 // A list-item cannot appear in more than one linear clause.
19310 // A list-item that appears in a linear clause cannot appear in any
19311 // other data-sharing attribute clause.
19312 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19313 if (DVar.RefExpr) {
19314 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
19315 << getOpenMPClauseName(OMPC_linear);
19317 continue;
19318 }
19319
19320 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
19321 continue;
19322 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19323
19324 // Build private copy of original var.
19325 VarDecl *Private =
19326 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
19327 D->hasAttrs() ? &D->getAttrs() : nullptr,
19328 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19329 DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc);
19330 // Build var to save initial value.
19331 VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start");
19332 Expr *InitExpr;
19333 DeclRefExpr *Ref = nullptr;
19334 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19335 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19336 if (!isOpenMPCapturedDecl(D)) {
19337 ExprCaptures.push_back(Ref->getDecl());
19338 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19340 if (!RefRes.isUsable())
19341 continue;
19342 ExprResult PostUpdateRes =
19343 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
19344 SimpleRefExpr, RefRes.get());
19345 if (!PostUpdateRes.isUsable())
19346 continue;
19347 ExprPostUpdates.push_back(
19348 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
19349 }
19350 }
19351 }
19352 if (LinKind == OMPC_LINEAR_uval)
19353 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
19354 else
19355 InitExpr = VD ? SimpleRefExpr : Ref;
19358 /*DirectInit=*/false);
19359 DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc);
19360
19361 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
19362 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19363 ? RefExpr->IgnoreParens()
19364 : Ref);
19365 Privates.push_back(PrivateRef);
19366 Inits.push_back(InitRef);
19367 }
19368
19369 if (Vars.empty())
19370 return nullptr;
19371
19372 Expr *StepExpr = Step;
19373 Expr *CalcStepExpr = nullptr;
19374 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
19375 !Step->isInstantiationDependent() &&
19377 SourceLocation StepLoc = Step->getBeginLoc();
19379 if (Val.isInvalid())
19380 return nullptr;
19381 StepExpr = Val.get();
19382
19383 // Build var to save the step value.
19384 VarDecl *SaveVar =
19385 buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step");
19386 ExprResult SaveRef =
19387 buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc);
19388 ExprResult CalcStep = SemaRef.BuildBinOp(
19389 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr);
19390 CalcStep =
19391 SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue=*/false);
19392
19393 // Warn about zero linear step (it would be probably better specified as
19394 // making corresponding variables 'const').
19395 if (std::optional<llvm::APSInt> Result =
19397 if (!Result->isNegative() && !Result->isStrictlyPositive())
19398 Diag(StepLoc, diag::warn_omp_linear_step_zero)
19399 << Vars[0] << (Vars.size() > 1);
19400 } else if (CalcStep.isUsable()) {
19401 // Calculate the step beforehand instead of doing this on each iteration.
19402 // (This is not used if the number of iterations may be kfold-ed).
19403 CalcStepExpr = CalcStep.get();
19404 }
19405 }
19406
19407 return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind,
19408 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
19409 Vars, Privates, Inits, StepExpr, CalcStepExpr,
19410 buildPreInits(getASTContext(), ExprCaptures),
19411 buildPostUpdate(SemaRef, ExprPostUpdates));
19412}
19413
19415 Expr *NumIterations, Sema &SemaRef,
19416 Scope *S, DSAStackTy *Stack) {
19417 // Walk the vars and build update/final expressions for the CodeGen.
19418 SmallVector<Expr *, 8> Updates;
19420 SmallVector<Expr *, 8> UsedExprs;
19421 Expr *Step = Clause.getStep();
19422 Expr *CalcStep = Clause.getCalcStep();
19423 // OpenMP [2.14.3.7, linear clause]
19424 // If linear-step is not specified it is assumed to be 1.
19425 if (!Step)
19426 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
19427 else if (CalcStep)
19428 Step = cast<BinaryOperator>(CalcStep)->getLHS();
19429 bool HasErrors = false;
19430 auto CurInit = Clause.inits().begin();
19431 auto CurPrivate = Clause.privates().begin();
19432 OpenMPLinearClauseKind LinKind = Clause.getModifier();
19433 for (Expr *RefExpr : Clause.varlist()) {
19434 SourceLocation ELoc;
19435 SourceRange ERange;
19436 Expr *SimpleRefExpr = RefExpr;
19437 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19438 ValueDecl *D = Res.first;
19439 if (Res.second || !D) {
19440 Updates.push_back(nullptr);
19441 Finals.push_back(nullptr);
19442 HasErrors = true;
19443 continue;
19444 }
19445 auto &&Info = Stack->isLoopControlVariable(D);
19446 // OpenMP [2.15.11, distribute simd Construct]
19447 // A list item may not appear in a linear clause, unless it is the loop
19448 // iteration variable.
19449 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
19450 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
19451 SemaRef.Diag(ELoc,
19452 diag::err_omp_linear_distribute_var_non_loop_iteration);
19453 Updates.push_back(nullptr);
19454 Finals.push_back(nullptr);
19455 HasErrors = true;
19456 continue;
19457 }
19458 Expr *InitExpr = *CurInit;
19459
19460 // Build privatized reference to the current linear var.
19461 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
19462 Expr *CapturedRef;
19463 if (LinKind == OMPC_LINEAR_uval)
19464 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
19465 else
19466 CapturedRef =
19467 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
19468 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
19469 /*RefersToCapture=*/true);
19470
19471 // Build update: Var = InitExpr + IV * Step
19473 if (!Info.first)
19475 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
19476 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
19477 else
19478 Update = *CurPrivate;
19479 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
19480 /*DiscardedValue=*/false);
19481
19482 // Build final: Var = PrivCopy;
19483 ExprResult Final;
19484 if (!Info.first)
19485 Final = SemaRef.BuildBinOp(
19486 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
19487 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
19488 else
19489 Final = *CurPrivate;
19490 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
19491 /*DiscardedValue=*/false);
19492
19493 if (!Update.isUsable() || !Final.isUsable()) {
19494 Updates.push_back(nullptr);
19495 Finals.push_back(nullptr);
19496 UsedExprs.push_back(nullptr);
19497 HasErrors = true;
19498 } else {
19499 Updates.push_back(Update.get());
19500 Finals.push_back(Final.get());
19501 if (!Info.first)
19502 UsedExprs.push_back(SimpleRefExpr);
19503 }
19504 ++CurInit;
19505 ++CurPrivate;
19506 }
19507 if (Expr *S = Clause.getStep())
19508 UsedExprs.push_back(S);
19509 // Fill the remaining part with the nullptr.
19510 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
19511 Clause.setUpdates(Updates);
19512 Clause.setFinals(Finals);
19513 Clause.setUsedExprs(UsedExprs);
19514 return HasErrors;
19515}
19516
19518 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
19519 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
19521 for (Expr *RefExpr : VarList) {
19522 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19523 SourceLocation ELoc;
19524 SourceRange ERange;
19525 Expr *SimpleRefExpr = RefExpr;
19526 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19527 if (Res.second) {
19528 // It will be analyzed later.
19529 Vars.push_back(RefExpr);
19530 }
19531 ValueDecl *D = Res.first;
19532 if (!D)
19533 continue;
19534
19535 QualType QType = D->getType();
19536 auto *VD = dyn_cast<VarDecl>(D);
19537
19538 // OpenMP [2.8.1, simd construct, Restrictions]
19539 // The type of list items appearing in the aligned clause must be
19540 // array, pointer, reference to array, or reference to pointer.
19542 const Type *Ty = QType.getTypePtrOrNull();
19543 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
19544 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
19545 << QType << getLangOpts().CPlusPlus << ERange;
19546 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19548 Diag(D->getLocation(),
19549 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19550 << D;
19551 continue;
19552 }
19553
19554 // OpenMP [2.8.1, simd construct, Restrictions]
19555 // A list-item cannot appear in more than one aligned clause.
19556 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
19557 Diag(ELoc, diag::err_omp_used_in_clause_twice)
19558 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
19559 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
19560 << getOpenMPClauseName(OMPC_aligned);
19561 continue;
19562 }
19563
19564 DeclRefExpr *Ref = nullptr;
19565 if (!VD && isOpenMPCapturedDecl(D))
19566 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19567 Vars.push_back(SemaRef
19568 .DefaultFunctionArrayConversion(
19569 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
19570 .get());
19571 }
19572
19573 // OpenMP [2.8.1, simd construct, Description]
19574 // The parameter of the aligned clause, alignment, must be a constant
19575 // positive integer expression.
19576 // If no optional parameter is specified, implementation-defined default
19577 // alignments for SIMD instructions on the target platforms are assumed.
19578 if (Alignment != nullptr) {
19579 ExprResult AlignResult =
19580 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
19581 if (AlignResult.isInvalid())
19582 return nullptr;
19583 Alignment = AlignResult.get();
19584 }
19585 if (Vars.empty())
19586 return nullptr;
19587
19588 return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc,
19589 ColonLoc, EndLoc, Vars, Alignment);
19590}
19591
19593 SourceLocation StartLoc,
19594 SourceLocation LParenLoc,
19595 SourceLocation EndLoc) {
19597 SmallVector<Expr *, 8> SrcExprs;
19598 SmallVector<Expr *, 8> DstExprs;
19599 SmallVector<Expr *, 8> AssignmentOps;
19600 for (Expr *RefExpr : VarList) {
19601 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
19602 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19603 // It will be analyzed later.
19604 Vars.push_back(RefExpr);
19605 SrcExprs.push_back(nullptr);
19606 DstExprs.push_back(nullptr);
19607 AssignmentOps.push_back(nullptr);
19608 continue;
19609 }
19610
19611 SourceLocation ELoc = RefExpr->getExprLoc();
19612 // OpenMP [2.1, C/C++]
19613 // A list item is a variable name.
19614 // OpenMP [2.14.4.1, Restrictions, p.1]
19615 // A list item that appears in a copyin clause must be threadprivate.
19616 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
19617 if (!DE || !isa<VarDecl>(DE->getDecl())) {
19618 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
19619 << 0 << RefExpr->getSourceRange();
19620 continue;
19621 }
19622
19623 Decl *D = DE->getDecl();
19624 auto *VD = cast<VarDecl>(D);
19625
19626 QualType Type = VD->getType();
19628 // It will be analyzed later.
19629 Vars.push_back(DE);
19630 SrcExprs.push_back(nullptr);
19631 DstExprs.push_back(nullptr);
19632 AssignmentOps.push_back(nullptr);
19633 continue;
19634 }
19635
19636 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
19637 // A list item that appears in a copyin clause must be threadprivate.
19638 if (!DSAStack->isThreadPrivate(VD)) {
19639 Diag(ELoc, diag::err_omp_required_access)
19640 << getOpenMPClauseName(OMPC_copyin)
19641 << getOpenMPDirectiveName(OMPD_threadprivate);
19642 continue;
19643 }
19644
19645 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
19646 // A variable of class type (or array thereof) that appears in a
19647 // copyin clause requires an accessible, unambiguous copy assignment
19648 // operator for the class type.
19649 QualType ElemType =
19651 VarDecl *SrcVD =
19652 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
19653 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
19654 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
19655 SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
19656 VarDecl *DstVD =
19657 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst",
19658 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
19659 DeclRefExpr *PseudoDstExpr =
19660 buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc());
19661 // For arrays generate assignment operation for single element and replace
19662 // it by the original array element in CodeGen.
19663 ExprResult AssignmentOp =
19664 SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
19665 PseudoDstExpr, PseudoSrcExpr);
19666 if (AssignmentOp.isInvalid())
19667 continue;
19668 AssignmentOp =
19669 SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
19670 /*DiscardedValue=*/false);
19671 if (AssignmentOp.isInvalid())
19672 continue;
19673
19674 DSAStack->addDSA(VD, DE, OMPC_copyin);
19675 Vars.push_back(DE);
19676 SrcExprs.push_back(PseudoSrcExpr);
19677 DstExprs.push_back(PseudoDstExpr);
19678 AssignmentOps.push_back(AssignmentOp.get());
19679 }
19680
19681 if (Vars.empty())
19682 return nullptr;
19683
19684 return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19685 Vars, SrcExprs, DstExprs, AssignmentOps);
19686}
19687
19689 SourceLocation StartLoc,
19690 SourceLocation LParenLoc,
19691 SourceLocation EndLoc) {
19693 SmallVector<Expr *, 8> SrcExprs;
19694 SmallVector<Expr *, 8> DstExprs;
19695 SmallVector<Expr *, 8> AssignmentOps;
19696 for (Expr *RefExpr : VarList) {
19697 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19698 SourceLocation ELoc;
19699 SourceRange ERange;
19700 Expr *SimpleRefExpr = RefExpr;
19701 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19702 if (Res.second) {
19703 // It will be analyzed later.
19704 Vars.push_back(RefExpr);
19705 SrcExprs.push_back(nullptr);
19706 DstExprs.push_back(nullptr);
19707 AssignmentOps.push_back(nullptr);
19708 }
19709 ValueDecl *D = Res.first;
19710 if (!D)
19711 continue;
19712
19713 QualType Type = D->getType();
19714 auto *VD = dyn_cast<VarDecl>(D);
19715
19716 // OpenMP [2.14.4.2, Restrictions, p.2]
19717 // A list item that appears in a copyprivate clause may not appear in a
19718 // private or firstprivate clause on the single construct.
19719 if (!VD || !DSAStack->isThreadPrivate(VD)) {
19720 DSAStackTy::DSAVarData DVar =
19721 DSAStack->getTopDSA(D, /*FromParent=*/false);
19722 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
19723 DVar.RefExpr) {
19724 Diag(ELoc, diag::err_omp_wrong_dsa)
19725 << getOpenMPClauseName(DVar.CKind)
19726 << getOpenMPClauseName(OMPC_copyprivate);
19728 continue;
19729 }
19730
19731 // OpenMP [2.11.4.2, Restrictions, p.1]
19732 // All list items that appear in a copyprivate clause must be either
19733 // threadprivate or private in the enclosing context.
19734 if (DVar.CKind == OMPC_unknown) {
19735 DVar = DSAStack->getImplicitDSA(D, false);
19736 if (DVar.CKind == OMPC_shared) {
19737 Diag(ELoc, diag::err_omp_required_access)
19738 << getOpenMPClauseName(OMPC_copyprivate)
19739 << "threadprivate or private in the enclosing context";
19741 continue;
19742 }
19743 }
19744 }
19745
19746 // Variably modified types are not supported.
19748 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19749 << getOpenMPClauseName(OMPC_copyprivate) << Type
19750 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
19751 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19753 Diag(D->getLocation(),
19754 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19755 << D;
19756 continue;
19757 }
19758
19759 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
19760 // A variable of class type (or array thereof) that appears in a
19761 // copyin clause requires an accessible, unambiguous copy assignment
19762 // operator for the class type.
19764 .getBaseElementType(Type.getNonReferenceType())
19766 VarDecl *SrcVD =
19767 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
19768 D->hasAttrs() ? &D->getAttrs() : nullptr);
19769 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc);
19770 VarDecl *DstVD =
19771 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
19772 D->hasAttrs() ? &D->getAttrs() : nullptr);
19773 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
19774 ExprResult AssignmentOp = SemaRef.BuildBinOp(
19775 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
19776 if (AssignmentOp.isInvalid())
19777 continue;
19778 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
19779 /*DiscardedValue=*/false);
19780 if (AssignmentOp.isInvalid())
19781 continue;
19782
19783 // No need to mark vars as copyprivate, they are already threadprivate or
19784 // implicitly private.
19785 assert(VD || isOpenMPCapturedDecl(D));
19786 Vars.push_back(
19787 VD ? RefExpr->IgnoreParens()
19788 : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false));
19789 SrcExprs.push_back(PseudoSrcExpr);
19790 DstExprs.push_back(PseudoDstExpr);
19791 AssignmentOps.push_back(AssignmentOp.get());
19792 }
19793
19794 if (Vars.empty())
19795 return nullptr;
19796
19797 return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc,
19798 EndLoc, Vars, SrcExprs, DstExprs,
19799 AssignmentOps);
19800}
19801
19803 SourceLocation StartLoc,
19804 SourceLocation LParenLoc,
19805 SourceLocation EndLoc) {
19806 if (VarList.empty())
19807 return nullptr;
19808
19809 return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19810 VarList);
19811}
19812
19813/// Tries to find omp_depend_t. type.
19814static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
19815 bool Diagnose = true) {
19816 QualType OMPDependT = Stack->getOMPDependT();
19817 if (!OMPDependT.isNull())
19818 return true;
19819 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
19820 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
19821 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
19822 if (Diagnose)
19823 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
19824 return false;
19825 }
19826 Stack->setOMPDependT(PT.get());
19827 return true;
19828}
19829
19831 SourceLocation StartLoc,
19832 SourceLocation LParenLoc,
19833 SourceLocation EndLoc) {
19834 if (!Depobj)
19835 return nullptr;
19836
19837 bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack);
19838
19839 // OpenMP 5.0, 2.17.10.1 depobj Construct
19840 // depobj is an lvalue expression of type omp_depend_t.
19841 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
19842 !Depobj->isInstantiationDependent() &&
19844 (OMPDependTFound && !getASTContext().typesAreCompatible(
19845 DSAStack->getOMPDependT(), Depobj->getType(),
19846 /*CompareUnqualified=*/true))) {
19847 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19848 << 0 << Depobj->getType() << Depobj->getSourceRange();
19849 }
19850
19851 if (!Depobj->isLValue()) {
19852 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19853 << 1 << Depobj->getSourceRange();
19854 }
19855
19856 return OMPDepobjClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19857 Depobj);
19858}
19859
19860namespace {
19861// Utility struct that gathers the related info for doacross clause.
19862struct DoacrossDataInfoTy {
19863 // The list of expressions.
19865 // The OperatorOffset for doacross loop.
19867 // The depended loop count.
19868 llvm::APSInt TotalDepCount;
19869};
19870} // namespace
19871static DoacrossDataInfoTy
19873 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
19874 SourceLocation EndLoc) {
19875
19878 llvm::APSInt DepCounter(/*BitWidth=*/32);
19879 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
19880
19881 if (const Expr *OrderedCountExpr =
19882 Stack->getParentOrderedRegionParam().first) {
19883 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
19884 TotalDepCount.setIsUnsigned(/*Val=*/true);
19885 }
19886
19887 for (Expr *RefExpr : VarList) {
19888 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
19889 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19890 // It will be analyzed later.
19891 Vars.push_back(RefExpr);
19892 continue;
19893 }
19894
19895 SourceLocation ELoc = RefExpr->getExprLoc();
19896 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
19897 if (!IsSource) {
19898 if (Stack->getParentOrderedRegionParam().first &&
19899 DepCounter >= TotalDepCount) {
19900 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
19901 continue;
19902 }
19903 ++DepCounter;
19904 // OpenMP [2.13.9, Summary]
19905 // depend(dependence-type : vec), where dependence-type is:
19906 // 'sink' and where vec is the iteration vector, which has the form:
19907 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
19908 // where n is the value specified by the ordered clause in the loop
19909 // directive, xi denotes the loop iteration variable of the i-th nested
19910 // loop associated with the loop directive, and di is a constant
19911 // non-negative integer.
19912 if (SemaRef.CurContext->isDependentContext()) {
19913 // It will be analyzed later.
19914 Vars.push_back(RefExpr);
19915 continue;
19916 }
19917 SimpleExpr = SimpleExpr->IgnoreImplicit();
19919 SourceLocation OOLoc;
19920 Expr *LHS = SimpleExpr;
19921 Expr *RHS = nullptr;
19922 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
19923 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
19924 OOLoc = BO->getOperatorLoc();
19925 LHS = BO->getLHS()->IgnoreParenImpCasts();
19926 RHS = BO->getRHS()->IgnoreParenImpCasts();
19927 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
19928 OOK = OCE->getOperator();
19929 OOLoc = OCE->getOperatorLoc();
19930 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
19931 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
19932 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
19933 OOK = MCE->getMethodDecl()
19934 ->getNameInfo()
19935 .getName()
19936 .getCXXOverloadedOperator();
19937 OOLoc = MCE->getCallee()->getExprLoc();
19938 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
19939 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
19940 }
19941 SourceLocation ELoc;
19942 SourceRange ERange;
19943 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
19944 if (Res.second) {
19945 // It will be analyzed later.
19946 Vars.push_back(RefExpr);
19947 }
19948 ValueDecl *D = Res.first;
19949 if (!D)
19950 continue;
19951
19952 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
19953 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
19954 continue;
19955 }
19956 if (RHS) {
19957 ExprResult RHSRes =
19959 RHS, OMPC_depend, /*StrictlyPositive=*/false);
19960 if (RHSRes.isInvalid())
19961 continue;
19962 }
19963 if (!SemaRef.CurContext->isDependentContext() &&
19964 Stack->getParentOrderedRegionParam().first &&
19965 DepCounter != Stack->isParentLoopControlVariable(D).first) {
19966 const ValueDecl *VD =
19967 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
19968 if (VD)
19969 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19970 << 1 << VD;
19971 else
19972 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19973 << 0;
19974 continue;
19975 }
19976 OpsOffs.emplace_back(RHS, OOK);
19977 }
19978 Vars.push_back(RefExpr->IgnoreParenImpCasts());
19979 }
19980 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
19981 TotalDepCount > VarList.size() &&
19982 Stack->getParentOrderedRegionParam().first &&
19983 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
19984 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
19985 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
19986 }
19987 return {Vars, OpsOffs, TotalDepCount};
19988}
19989
19991 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
19992 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19993 SourceLocation EndLoc) {
19994 OpenMPDependClauseKind DepKind = Data.DepKind;
19995 SourceLocation DepLoc = Data.DepLoc;
19996 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
19997 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
19998 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
19999 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
20000 return nullptr;
20001 }
20002 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
20003 DepKind == OMPC_DEPEND_mutexinoutset) {
20004 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
20005 return nullptr;
20006 }
20007 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
20008 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20009 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
20010 DepKind == OMPC_DEPEND_sink ||
20011 ((getLangOpts().OpenMP < 50 ||
20012 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20013 DepKind == OMPC_DEPEND_depobj))) {
20014 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
20015 OMPC_DEPEND_outallmemory,
20016 OMPC_DEPEND_inoutallmemory};
20017 if (getLangOpts().OpenMP < 50 ||
20018 DSAStack->getCurrentDirective() == OMPD_depobj)
20019 Except.push_back(OMPC_DEPEND_depobj);
20020 if (getLangOpts().OpenMP < 51)
20021 Except.push_back(OMPC_DEPEND_inoutset);
20022 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
20023 ? "depend modifier(iterator) or "
20024 : "";
20025 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20026 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
20027 /*Last=*/OMPC_DEPEND_unknown,
20028 Except)
20029 << getOpenMPClauseName(OMPC_depend);
20030 return nullptr;
20031 }
20032 if (DepModifier &&
20033 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
20034 Diag(DepModifier->getExprLoc(),
20035 diag::err_omp_depend_sink_source_with_modifier);
20036 return nullptr;
20037 }
20038 if (DepModifier &&
20039 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
20040 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
20041
20044 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20045
20046 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
20047 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
20048 SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
20049 Vars = VarOffset.Vars;
20050 OpsOffs = VarOffset.OpsOffs;
20051 TotalDepCount = VarOffset.TotalDepCount;
20052 } else {
20053 for (Expr *RefExpr : VarList) {
20054 assert(RefExpr && "NULL expr in OpenMP shared clause.");
20055 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20056 // It will be analyzed later.
20057 Vars.push_back(RefExpr);
20058 continue;
20059 }
20060
20061 SourceLocation ELoc = RefExpr->getExprLoc();
20062 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20063 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
20064 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
20065 if (OMPDependTFound)
20066 OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack,
20067 DepKind == OMPC_DEPEND_depobj);
20068 if (DepKind == OMPC_DEPEND_depobj) {
20069 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20070 // List items used in depend clauses with the depobj dependence type
20071 // must be expressions of the omp_depend_t type.
20072 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20073 !RefExpr->isInstantiationDependent() &&
20074 !RefExpr->containsUnexpandedParameterPack() &&
20075 (OMPDependTFound &&
20076 !getASTContext().hasSameUnqualifiedType(
20077 DSAStack->getOMPDependT(), RefExpr->getType()))) {
20078 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20079 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
20080 continue;
20081 }
20082 if (!RefExpr->isLValue()) {
20083 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20084 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
20085 continue;
20086 }
20087 } else {
20088 // OpenMP 5.0 [2.17.11, Restrictions]
20089 // List items used in depend clauses cannot be zero-length array
20090 // sections.
20091 QualType ExprTy = RefExpr->getType().getNonReferenceType();
20092 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
20093 if (OASE) {
20094 QualType BaseType =
20096 if (BaseType.isNull())
20097 return nullptr;
20098 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20099 ExprTy = ATy->getElementType();
20100 else
20101 ExprTy = BaseType->getPointeeType();
20102 if (BaseType.isNull() || ExprTy.isNull())
20103 return nullptr;
20104 ExprTy = ExprTy.getNonReferenceType();
20105 const Expr *Length = OASE->getLength();
20107 if (Length && !Length->isValueDependent() &&
20108 Length->EvaluateAsInt(Result, getASTContext()) &&
20109 Result.Val.getInt().isZero()) {
20110 Diag(ELoc,
20111 diag::err_omp_depend_zero_length_array_section_not_allowed)
20112 << SimpleExpr->getSourceRange();
20113 continue;
20114 }
20115 }
20116
20117 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20118 // List items used in depend clauses with the in, out, inout,
20119 // inoutset, or mutexinoutset dependence types cannot be
20120 // expressions of the omp_depend_t type.
20121 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20122 !RefExpr->isInstantiationDependent() &&
20123 !RefExpr->containsUnexpandedParameterPack() &&
20124 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
20125 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
20126 ExprTy.getTypePtr()))) {
20127 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20128 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20129 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20130 << RefExpr->getSourceRange();
20131 continue;
20132 }
20133
20134 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
20135 if (ASE && !ASE->getBase()->isTypeDependent() &&
20136 !ASE->getBase()
20137 ->getType()
20138 .getNonReferenceType()
20139 ->isPointerType() &&
20140 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
20141 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20142 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20143 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20144 << RefExpr->getSourceRange();
20145 continue;
20146 }
20147
20148 ExprResult Res;
20149 {
20151 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
20152 RefExpr->IgnoreParenImpCasts());
20153 }
20154 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
20155 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
20156 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20157 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20158 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20159 << RefExpr->getSourceRange();
20160 continue;
20161 }
20162 }
20163 }
20164 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20165 }
20166 }
20167
20168 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
20169 DepKind != OMPC_DEPEND_outallmemory &&
20170 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
20171 return nullptr;
20172
20173 auto *C = OMPDependClause::Create(
20174 getASTContext(), StartLoc, LParenLoc, EndLoc,
20175 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
20176 TotalDepCount.getZExtValue());
20177 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
20178 DSAStack->isParentOrderedRegion())
20179 DSAStack->addDoacrossDependClause(C, OpsOffs);
20180 return C;
20181}
20182
20185 SourceLocation LParenLoc, SourceLocation ModifierLoc,
20186 SourceLocation EndLoc) {
20187 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
20188 "Unexpected device modifier in OpenMP < 50.");
20189
20190 bool ErrorFound = false;
20191 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
20192 std::string Values =
20193 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
20194 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
20195 << Values << getOpenMPClauseName(OMPC_device);
20196 ErrorFound = true;
20197 }
20198
20199 Expr *ValExpr = Device;
20200 Stmt *HelperValStmt = nullptr;
20201
20202 // OpenMP [2.9.1, Restrictions]
20203 // The device expression must evaluate to a non-negative integer value.
20204 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device,
20205 /*StrictlyPositive=*/false) ||
20206 ErrorFound;
20207 if (ErrorFound)
20208 return nullptr;
20209
20210 // OpenMP 5.0 [2.12.5, Restrictions]
20211 // In case of ancestor device-modifier, a requires directive with
20212 // the reverse_offload clause must be specified.
20213 if (Modifier == OMPC_DEVICE_ancestor) {
20214 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
20216 StartLoc,
20217 diag::err_omp_device_ancestor_without_requires_reverse_offload);
20218 ErrorFound = true;
20219 }
20220 }
20221
20222 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
20223 OpenMPDirectiveKind CaptureRegion =
20224 getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP);
20225 if (CaptureRegion != OMPD_unknown &&
20227 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
20228 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20229 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
20230 HelperValStmt = buildPreInits(getASTContext(), Captures);
20231 }
20232
20233 return new (getASTContext())
20234 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
20235 LParenLoc, ModifierLoc, EndLoc);
20236}
20237
20239 DSAStackTy *Stack, QualType QTy,
20240 bool FullCheck = true) {
20241 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
20242 return false;
20243 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
20244 !QTy.isTriviallyCopyableType(SemaRef.Context))
20245 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
20246 return true;
20247}
20248
20249/// Return true if it can be proven that the provided array expression
20250/// (array section or array subscript) does NOT specify the whole size of the
20251/// array whose base type is \a BaseQTy.
20253 const Expr *E,
20254 QualType BaseQTy) {
20255 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
20256
20257 // If this is an array subscript, it refers to the whole size if the size of
20258 // the dimension is constant and equals 1. Also, an array section assumes the
20259 // format of an array subscript if no colon is used.
20260 if (isa<ArraySubscriptExpr>(E) ||
20261 (OASE && OASE->getColonLocFirst().isInvalid())) {
20262 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20263 return ATy->getSExtSize() != 1;
20264 // Size can't be evaluated statically.
20265 return false;
20266 }
20267
20268 assert(OASE && "Expecting array section if not an array subscript.");
20269 const Expr *LowerBound = OASE->getLowerBound();
20270 const Expr *Length = OASE->getLength();
20271
20272 // If there is a lower bound that does not evaluates to zero, we are not
20273 // covering the whole dimension.
20274 if (LowerBound) {
20276 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
20277 return false; // Can't get the integer value as a constant.
20278
20279 llvm::APSInt ConstLowerBound = Result.Val.getInt();
20280 if (ConstLowerBound.getSExtValue())
20281 return true;
20282 }
20283
20284 // If we don't have a length we covering the whole dimension.
20285 if (!Length)
20286 return false;
20287
20288 // If the base is a pointer, we don't have a way to get the size of the
20289 // pointee.
20290 if (BaseQTy->isPointerType())
20291 return false;
20292
20293 // We can only check if the length is the same as the size of the dimension
20294 // if we have a constant array.
20295 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
20296 if (!CATy)
20297 return false;
20298
20300 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20301 return false; // Can't get the integer value as a constant.
20302
20303 llvm::APSInt ConstLength = Result.Val.getInt();
20304 return CATy->getSExtSize() != ConstLength.getSExtValue();
20305}
20306
20307// Return true if it can be proven that the provided array expression (array
20308// section or array subscript) does NOT specify a single element of the array
20309// whose base type is \a BaseQTy.
20311 const Expr *E,
20312 QualType BaseQTy) {
20313 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
20314
20315 // An array subscript always refer to a single element. Also, an array section
20316 // assumes the format of an array subscript if no colon is used.
20317 if (isa<ArraySubscriptExpr>(E) ||
20318 (OASE && OASE->getColonLocFirst().isInvalid()))
20319 return false;
20320
20321 assert(OASE && "Expecting array section if not an array subscript.");
20322 const Expr *Length = OASE->getLength();
20323
20324 // If we don't have a length we have to check if the array has unitary size
20325 // for this dimension. Also, we should always expect a length if the base type
20326 // is pointer.
20327 if (!Length) {
20328 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20329 return ATy->getSExtSize() != 1;
20330 // We cannot assume anything.
20331 return false;
20332 }
20333
20334 // Check if the length evaluates to 1.
20336 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20337 return false; // Can't get the integer value as a constant.
20338
20339 llvm::APSInt ConstLength = Result.Val.getInt();
20340 return ConstLength.getSExtValue() != 1;
20341}
20342
20343// The base of elements of list in a map clause have to be either:
20344// - a reference to variable or field.
20345// - a member expression.
20346// - an array expression.
20347//
20348// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
20349// reference to 'r'.
20350//
20351// If we have:
20352//
20353// struct SS {
20354// Bla S;
20355// foo() {
20356// #pragma omp target map (S.Arr[:12]);
20357// }
20358// }
20359//
20360// We want to retrieve the member expression 'this->S';
20361
20362// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
20363// If a list item is an array section, it must specify contiguous storage.
20364//
20365// For this restriction it is sufficient that we make sure only references
20366// to variables or fields and array expressions, and that no array sections
20367// exist except in the rightmost expression (unless they cover the whole
20368// dimension of the array). E.g. these would be invalid:
20369//
20370// r.ArrS[3:5].Arr[6:7]
20371//
20372// r.ArrS[3:5].x
20373//
20374// but these would be valid:
20375// r.ArrS[3].Arr[6:7]
20376//
20377// r.ArrS[3].x
20378namespace {
20379class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
20380 Sema &SemaRef;
20381 OpenMPClauseKind CKind = OMPC_unknown;
20382 OpenMPDirectiveKind DKind = OMPD_unknown;
20384 bool IsNonContiguous = false;
20385 bool NoDiagnose = false;
20386 const Expr *RelevantExpr = nullptr;
20387 bool AllowUnitySizeArraySection = true;
20388 bool AllowWholeSizeArraySection = true;
20389 bool AllowAnotherPtr = true;
20390 SourceLocation ELoc;
20391 SourceRange ERange;
20392
20393 void emitErrorMsg() {
20394 // If nothing else worked, this is not a valid map clause expression.
20395 if (SemaRef.getLangOpts().OpenMP < 50) {
20396 SemaRef.Diag(ELoc,
20397 diag::err_omp_expected_named_var_member_or_array_expression)
20398 << ERange;
20399 } else {
20400 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20401 << getOpenMPClauseName(CKind) << ERange;
20402 }
20403 }
20404
20405public:
20406 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
20407 if (!isa<VarDecl>(DRE->getDecl())) {
20408 emitErrorMsg();
20409 return false;
20410 }
20411 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20412 RelevantExpr = DRE;
20413 // Record the component.
20414 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
20415 return true;
20416 }
20417
20418 bool VisitMemberExpr(MemberExpr *ME) {
20419 Expr *E = ME;
20420 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
20421
20422 if (isa<CXXThisExpr>(BaseE)) {
20423 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20424 // We found a base expression: this->Val.
20425 RelevantExpr = ME;
20426 } else {
20427 E = BaseE;
20428 }
20429
20430 if (!isa<FieldDecl>(ME->getMemberDecl())) {
20431 if (!NoDiagnose) {
20432 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
20433 << ME->getSourceRange();
20434 return false;
20435 }
20436 if (RelevantExpr)
20437 return false;
20438 return Visit(E);
20439 }
20440
20441 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
20442
20443 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
20444 // A bit-field cannot appear in a map clause.
20445 //
20446 if (FD->isBitField()) {
20447 if (!NoDiagnose) {
20448 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
20449 << ME->getSourceRange() << getOpenMPClauseName(CKind);
20450 return false;
20451 }
20452 if (RelevantExpr)
20453 return false;
20454 return Visit(E);
20455 }
20456
20457 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20458 // If the type of a list item is a reference to a type T then the type
20459 // will be considered to be T for all purposes of this clause.
20460 QualType CurType = BaseE->getType().getNonReferenceType();
20461
20462 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
20463 // A list item cannot be a variable that is a member of a structure with
20464 // a union type.
20465 //
20466 if (CurType->isUnionType()) {
20467 if (!NoDiagnose) {
20468 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
20469 << ME->getSourceRange();
20470 return false;
20471 }
20472 return RelevantExpr || Visit(E);
20473 }
20474
20475 // If we got a member expression, we should not expect any array section
20476 // before that:
20477 //
20478 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
20479 // If a list item is an element of a structure, only the rightmost symbol
20480 // of the variable reference can be an array section.
20481 //
20482 AllowUnitySizeArraySection = false;
20483 AllowWholeSizeArraySection = false;
20484
20485 // Record the component.
20486 Components.emplace_back(ME, FD, IsNonContiguous);
20487 return RelevantExpr || Visit(E);
20488 }
20489
20490 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
20491 Expr *E = AE->getBase()->IgnoreParenImpCasts();
20492
20493 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
20494 if (!NoDiagnose) {
20495 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20496 << 0 << AE->getSourceRange();
20497 return false;
20498 }
20499 return RelevantExpr || Visit(E);
20500 }
20501
20502 // If we got an array subscript that express the whole dimension we
20503 // can have any array expressions before. If it only expressing part of
20504 // the dimension, we can only have unitary-size array expressions.
20506 AllowWholeSizeArraySection = false;
20507
20508 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
20509 Expr::EvalResult Result;
20510 if (!AE->getIdx()->isValueDependent() &&
20511 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
20512 !Result.Val.getInt().isZero()) {
20513 SemaRef.Diag(AE->getIdx()->getExprLoc(),
20514 diag::err_omp_invalid_map_this_expr);
20515 SemaRef.Diag(AE->getIdx()->getExprLoc(),
20516 diag::note_omp_invalid_subscript_on_this_ptr_map);
20517 }
20518 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20519 RelevantExpr = TE;
20520 }
20521
20522 // Record the component - we don't have any declaration associated.
20523 Components.emplace_back(AE, nullptr, IsNonContiguous);
20524
20525 return RelevantExpr || Visit(E);
20526 }
20527
20528 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
20529 // After OMP 5.0 Array section in reduction clause will be implicitly
20530 // mapped
20531 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
20532 "Array sections cannot be implicitly mapped.");
20533 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20534 QualType CurType =
20536
20537 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20538 // If the type of a list item is a reference to a type T then the type
20539 // will be considered to be T for all purposes of this clause.
20540 if (CurType->isReferenceType())
20541 CurType = CurType->getPointeeType();
20542
20543 bool IsPointer = CurType->isAnyPointerType();
20544
20545 if (!IsPointer && !CurType->isArrayType()) {
20546 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20547 << 0 << OASE->getSourceRange();
20548 return false;
20549 }
20550
20551 bool NotWhole =
20552 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
20553 bool NotUnity =
20554 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
20555
20556 if (AllowWholeSizeArraySection) {
20557 // Any array section is currently allowed. Allowing a whole size array
20558 // section implies allowing a unity array section as well.
20559 //
20560 // If this array section refers to the whole dimension we can still
20561 // accept other array sections before this one, except if the base is a
20562 // pointer. Otherwise, only unitary sections are accepted.
20563 if (NotWhole || IsPointer)
20564 AllowWholeSizeArraySection = false;
20565 } else if (DKind == OMPD_target_update &&
20566 SemaRef.getLangOpts().OpenMP >= 50) {
20567 if (IsPointer && !AllowAnotherPtr)
20568 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
20569 << /*array of unknown bound */ 1;
20570 else
20571 IsNonContiguous = true;
20572 } else if (AllowUnitySizeArraySection && NotUnity) {
20573 // A unity or whole array section is not allowed and that is not
20574 // compatible with the properties of the current array section.
20575 if (NoDiagnose)
20576 return false;
20577 SemaRef.Diag(ELoc,
20578 diag::err_array_section_does_not_specify_contiguous_storage)
20579 << OASE->getSourceRange();
20580 return false;
20581 }
20582
20583 if (IsPointer)
20584 AllowAnotherPtr = false;
20585
20586 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
20587 Expr::EvalResult ResultR;
20588 Expr::EvalResult ResultL;
20589 if (!OASE->getLength()->isValueDependent() &&
20590 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
20591 !ResultR.Val.getInt().isOne()) {
20592 SemaRef.Diag(OASE->getLength()->getExprLoc(),
20593 diag::err_omp_invalid_map_this_expr);
20594 SemaRef.Diag(OASE->getLength()->getExprLoc(),
20595 diag::note_omp_invalid_length_on_this_ptr_mapping);
20596 }
20597 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
20598 OASE->getLowerBound()->EvaluateAsInt(ResultL,
20599 SemaRef.getASTContext()) &&
20600 !ResultL.Val.getInt().isZero()) {
20601 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
20602 diag::err_omp_invalid_map_this_expr);
20603 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
20604 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
20605 }
20606 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20607 RelevantExpr = TE;
20608 }
20609
20610 // Record the component - we don't have any declaration associated.
20611 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
20612 return RelevantExpr || Visit(E);
20613 }
20614 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
20615 Expr *Base = E->getBase();
20616
20617 // Record the component - we don't have any declaration associated.
20618 Components.emplace_back(E, nullptr, IsNonContiguous);
20619
20620 return Visit(Base->IgnoreParenImpCasts());
20621 }
20622
20623 bool VisitUnaryOperator(UnaryOperator *UO) {
20624 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
20625 UO->getOpcode() != UO_Deref) {
20626 emitErrorMsg();
20627 return false;
20628 }
20629 if (!RelevantExpr) {
20630 // Record the component if haven't found base decl.
20631 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
20632 }
20633 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
20634 }
20635 bool VisitBinaryOperator(BinaryOperator *BO) {
20636 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
20637 emitErrorMsg();
20638 return false;
20639 }
20640
20641 // Pointer arithmetic is the only thing we expect to happen here so after we
20642 // make sure the binary operator is a pointer type, the only thing we need
20643 // to do is to visit the subtree that has the same type as root (so that we
20644 // know the other subtree is just an offset)
20645 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
20646 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
20647 Components.emplace_back(BO, nullptr, false);
20648 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
20649 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
20650 "Either LHS or RHS have base decl inside");
20651 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
20652 return RelevantExpr || Visit(LE);
20653 return RelevantExpr || Visit(RE);
20654 }
20655 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
20656 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20657 RelevantExpr = CTE;
20658 Components.emplace_back(CTE, nullptr, IsNonContiguous);
20659 return true;
20660 }
20661 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
20662 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20663 Components.emplace_back(COCE, nullptr, IsNonContiguous);
20664 return true;
20665 }
20666 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
20667 Expr *Source = E->getSourceExpr();
20668 if (!Source) {
20669 emitErrorMsg();
20670 return false;
20671 }
20672 return Visit(Source);
20673 }
20674 bool VisitStmt(Stmt *) {
20675 emitErrorMsg();
20676 return false;
20677 }
20678 const Expr *getFoundBase() const { return RelevantExpr; }
20679 explicit MapBaseChecker(
20680 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
20682 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
20683 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
20684 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
20685};
20686} // namespace
20687
20688/// Return the expression of the base of the mappable expression or null if it
20689/// cannot be determined and do all the necessary checks to see if the
20690/// expression is valid as a standalone mappable expression. In the process,
20691/// record all the components of the expression.
20693 Sema &SemaRef, Expr *E,
20695 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
20696 SourceLocation ELoc = E->getExprLoc();
20697 SourceRange ERange = E->getSourceRange();
20698 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
20699 ERange);
20700 if (Checker.Visit(E->IgnoreParens())) {
20701 // Check if the highest dimension array section has length specified
20702 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
20703 (CKind == OMPC_to || CKind == OMPC_from)) {
20704 auto CI = CurComponents.rbegin();
20705 auto CE = CurComponents.rend();
20706 for (; CI != CE; ++CI) {
20707 const auto *OASE =
20708 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
20709 if (!OASE)
20710 continue;
20711 if (OASE && OASE->getLength())
20712 break;
20713 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
20714 << ERange;
20715 }
20716 }
20717 return Checker.getFoundBase();
20718 }
20719 return nullptr;
20720}
20721
20722// Return true if expression E associated with value VD has conflicts with other
20723// map information.
20725 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
20726 bool CurrentRegionOnly,
20728 OpenMPClauseKind CKind) {
20729 assert(VD && E);
20730 SourceLocation ELoc = E->getExprLoc();
20731 SourceRange ERange = E->getSourceRange();
20732
20733 // In order to easily check the conflicts we need to match each component of
20734 // the expression under test with the components of the expressions that are
20735 // already in the stack.
20736
20737 assert(!CurComponents.empty() && "Map clause expression with no components!");
20738 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
20739 "Map clause expression with unexpected base!");
20740
20741 // Variables to help detecting enclosing problems in data environment nests.
20742 bool IsEnclosedByDataEnvironmentExpr = false;
20743 const Expr *EnclosingExpr = nullptr;
20744
20745 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
20746 VD, CurrentRegionOnly,
20747 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
20748 ERange, CKind, &EnclosingExpr,
20750 StackComponents,
20751 OpenMPClauseKind Kind) {
20752 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
20753 return false;
20754 assert(!StackComponents.empty() &&
20755 "Map clause expression with no components!");
20756 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
20757 "Map clause expression with unexpected base!");
20758 (void)VD;
20759
20760 // The whole expression in the stack.
20761 const Expr *RE = StackComponents.front().getAssociatedExpression();
20762
20763 // Expressions must start from the same base. Here we detect at which
20764 // point both expressions diverge from each other and see if we can
20765 // detect if the memory referred to both expressions is contiguous and
20766 // do not overlap.
20767 auto CI = CurComponents.rbegin();
20768 auto CE = CurComponents.rend();
20769 auto SI = StackComponents.rbegin();
20770 auto SE = StackComponents.rend();
20771 for (; CI != CE && SI != SE; ++CI, ++SI) {
20772
20773 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
20774 // At most one list item can be an array item derived from a given
20775 // variable in map clauses of the same construct.
20776 if (CurrentRegionOnly &&
20777 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
20778 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
20779 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
20780 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
20781 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
20782 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
20783 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
20784 diag::err_omp_multiple_array_items_in_map_clause)
20785 << CI->getAssociatedExpression()->getSourceRange();
20786 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
20787 diag::note_used_here)
20788 << SI->getAssociatedExpression()->getSourceRange();
20789 return true;
20790 }
20791
20792 // Do both expressions have the same kind?
20793 if (CI->getAssociatedExpression()->getStmtClass() !=
20794 SI->getAssociatedExpression()->getStmtClass())
20795 break;
20796
20797 // Are we dealing with different variables/fields?
20798 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
20799 break;
20800 }
20801 // Check if the extra components of the expressions in the enclosing
20802 // data environment are redundant for the current base declaration.
20803 // If they are, the maps completely overlap, which is legal.
20804 for (; SI != SE; ++SI) {
20805 QualType Type;
20806 if (const auto *ASE =
20807 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
20808 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
20809 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
20810 SI->getAssociatedExpression())) {
20811 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20812 Type = ArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
20813 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
20814 SI->getAssociatedExpression())) {
20815 Type = OASE->getBase()->getType()->getPointeeType();
20816 }
20817 if (Type.isNull() || Type->isAnyPointerType() ||
20819 SemaRef, SI->getAssociatedExpression(), Type))
20820 break;
20821 }
20822
20823 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
20824 // List items of map clauses in the same construct must not share
20825 // original storage.
20826 //
20827 // If the expressions are exactly the same or one is a subset of the
20828 // other, it means they are sharing storage.
20829 if (CI == CE && SI == SE) {
20830 if (CurrentRegionOnly) {
20831 if (CKind == OMPC_map) {
20832 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20833 } else {
20834 assert(CKind == OMPC_to || CKind == OMPC_from);
20835 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20836 << ERange;
20837 }
20838 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20839 << RE->getSourceRange();
20840 return true;
20841 }
20842 // If we find the same expression in the enclosing data environment,
20843 // that is legal.
20844 IsEnclosedByDataEnvironmentExpr = true;
20845 return false;
20846 }
20847
20848 QualType DerivedType =
20849 std::prev(CI)->getAssociatedDeclaration()->getType();
20850 SourceLocation DerivedLoc =
20851 std::prev(CI)->getAssociatedExpression()->getExprLoc();
20852
20853 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20854 // If the type of a list item is a reference to a type T then the type
20855 // will be considered to be T for all purposes of this clause.
20856 DerivedType = DerivedType.getNonReferenceType();
20857
20858 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
20859 // A variable for which the type is pointer and an array section
20860 // derived from that variable must not appear as list items of map
20861 // clauses of the same construct.
20862 //
20863 // Also, cover one of the cases in:
20864 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
20865 // If any part of the original storage of a list item has corresponding
20866 // storage in the device data environment, all of the original storage
20867 // must have corresponding storage in the device data environment.
20868 //
20869 if (DerivedType->isAnyPointerType()) {
20870 if (CI == CE || SI == SE) {
20871 SemaRef.Diag(
20872 DerivedLoc,
20873 diag::err_omp_pointer_mapped_along_with_derived_section)
20874 << DerivedLoc;
20875 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20876 << RE->getSourceRange();
20877 return true;
20878 }
20879 if (CI->getAssociatedExpression()->getStmtClass() !=
20880 SI->getAssociatedExpression()->getStmtClass() ||
20881 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
20882 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
20883 assert(CI != CE && SI != SE);
20884 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
20885 << DerivedLoc;
20886 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20887 << RE->getSourceRange();
20888 return true;
20889 }
20890 }
20891
20892 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
20893 // List items of map clauses in the same construct must not share
20894 // original storage.
20895 //
20896 // An expression is a subset of the other.
20897 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
20898 if (CKind == OMPC_map) {
20899 if (CI != CE || SI != SE) {
20900 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
20901 // a pointer.
20902 auto Begin =
20903 CI != CE ? CurComponents.begin() : StackComponents.begin();
20904 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
20905 auto It = Begin;
20906 while (It != End && !It->getAssociatedDeclaration())
20907 std::advance(It, 1);
20908 assert(It != End &&
20909 "Expected at least one component with the declaration.");
20910 if (It != Begin && It->getAssociatedDeclaration()
20911 ->getType()
20912 .getCanonicalType()
20913 ->isAnyPointerType()) {
20914 IsEnclosedByDataEnvironmentExpr = false;
20915 EnclosingExpr = nullptr;
20916 return false;
20917 }
20918 }
20919 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20920 } else {
20921 assert(CKind == OMPC_to || CKind == OMPC_from);
20922 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20923 << ERange;
20924 }
20925 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20926 << RE->getSourceRange();
20927 return true;
20928 }
20929
20930 // The current expression uses the same base as other expression in the
20931 // data environment but does not contain it completely.
20932 if (!CurrentRegionOnly && SI != SE)
20933 EnclosingExpr = RE;
20934
20935 // The current expression is a subset of the expression in the data
20936 // environment.
20937 IsEnclosedByDataEnvironmentExpr |=
20938 (!CurrentRegionOnly && CI != CE && SI == SE);
20939
20940 return false;
20941 });
20942
20943 if (CurrentRegionOnly)
20944 return FoundError;
20945
20946 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
20947 // If any part of the original storage of a list item has corresponding
20948 // storage in the device data environment, all of the original storage must
20949 // have corresponding storage in the device data environment.
20950 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
20951 // If a list item is an element of a structure, and a different element of
20952 // the structure has a corresponding list item in the device data environment
20953 // prior to a task encountering the construct associated with the map clause,
20954 // then the list item must also have a corresponding list item in the device
20955 // data environment prior to the task encountering the construct.
20956 //
20957 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
20958 SemaRef.Diag(ELoc,
20959 diag::err_omp_original_storage_is_shared_and_does_not_contain)
20960 << ERange;
20961 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
20962 << EnclosingExpr->getSourceRange();
20963 return true;
20964 }
20965
20966 return FoundError;
20967}
20968
20969// Look up the user-defined mapper given the mapper name and mapped type, and
20970// build a reference to it.
20972 CXXScopeSpec &MapperIdScopeSpec,
20973 const DeclarationNameInfo &MapperId,
20974 QualType Type,
20975 Expr *UnresolvedMapper) {
20976 if (MapperIdScopeSpec.isInvalid())
20977 return ExprError();
20978 // Get the actual type for the array type.
20979 if (Type->isArrayType()) {
20980 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
20982 }
20983 // Find all user-defined mappers with the given MapperId.
20984 SmallVector<UnresolvedSet<8>, 4> Lookups;
20985 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
20986 Lookup.suppressDiagnostics();
20987 if (S) {
20988 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
20989 /*ObjectType=*/QualType())) {
20990 NamedDecl *D = Lookup.getRepresentativeDecl();
20991 while (S && !S->isDeclScope(D))
20992 S = S->getParent();
20993 if (S)
20994 S = S->getParent();
20995 Lookups.emplace_back();
20996 Lookups.back().append(Lookup.begin(), Lookup.end());
20997 Lookup.clear();
20998 }
20999 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
21000 // Extract the user-defined mappers with the given MapperId.
21001 Lookups.push_back(UnresolvedSet<8>());
21002 for (NamedDecl *D : ULE->decls()) {
21003 auto *DMD = cast<OMPDeclareMapperDecl>(D);
21004 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
21005 Lookups.back().addDecl(DMD);
21006 }
21007 }
21008 // Defer the lookup for dependent types. The results will be passed through
21009 // UnresolvedMapper on instantiation.
21010 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21013 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
21014 return !D->isInvalidDecl() &&
21015 (D->getType()->isDependentType() ||
21016 D->getType()->isInstantiationDependentType() ||
21017 D->getType()->containsUnexpandedParameterPack());
21018 })) {
21019 UnresolvedSet<8> URS;
21020 for (const UnresolvedSet<8> &Set : Lookups) {
21021 if (Set.empty())
21022 continue;
21023 URS.append(Set.begin(), Set.end());
21024 }
21026 SemaRef.Context, /*NamingClass=*/nullptr,
21027 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
21028 /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false,
21029 /*KnownInstantiationDependent=*/false);
21030 }
21031 SourceLocation Loc = MapperId.getLoc();
21032 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21033 // The type must be of struct, union or class type in C and C++
21035 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
21036 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
21037 return ExprError();
21038 }
21039 // Perform argument dependent lookup.
21040 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21041 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
21042 // Return the first user-defined mapper with the desired type.
21043 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21044 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21045 if (!D->isInvalidDecl() &&
21046 SemaRef.Context.hasSameType(D->getType(), Type))
21047 return D;
21048 return nullptr;
21049 }))
21050 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21051 // Find the first user-defined mapper with a type derived from the desired
21052 // type.
21053 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21054 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21055 if (!D->isInvalidDecl() &&
21056 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
21057 !Type.isMoreQualifiedThan(D->getType(),
21058 SemaRef.getASTContext()))
21059 return D;
21060 return nullptr;
21061 })) {
21062 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21063 /*DetectVirtual=*/false);
21064 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
21065 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
21066 VD->getType().getUnqualifiedType()))) {
21067 if (SemaRef.CheckBaseClassAccess(
21068 Loc, VD->getType(), Type, Paths.front(),
21069 /*DiagID=*/0) != Sema::AR_inaccessible) {
21070 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21071 }
21072 }
21073 }
21074 }
21075 // Report error if a mapper is specified, but cannot be found.
21076 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
21077 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
21078 << Type << MapperId.getName();
21079 return ExprError();
21080 }
21081 return ExprEmpty();
21082}
21083
21084namespace {
21085// Utility struct that gathers all the related lists associated with a mappable
21086// expression.
21087struct MappableVarListInfo {
21088 // The list of expressions.
21089 ArrayRef<Expr *> VarList;
21090 // The list of processed expressions.
21091 SmallVector<Expr *, 16> ProcessedVarList;
21092 // The mappble components for each expression.
21094 // The base declaration of the variable.
21095 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
21096 // The reference to the user-defined mapper associated with every expression.
21097 SmallVector<Expr *, 16> UDMapperList;
21098
21099 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
21100 // We have a list of components and base declarations for each entry in the
21101 // variable list.
21102 VarComponents.reserve(VarList.size());
21103 VarBaseDeclarations.reserve(VarList.size());
21104 }
21105};
21106} // namespace
21107
21109 DSAStackTy *Stack,
21111
21112 const RecordDecl *RD = BaseType->getAsRecordDecl();
21114 DeclarationNameInfo ImplicitName;
21115 // Dummy variable _s for Mapper.
21116 VarDecl *VD = buildVarDecl(S, Range.getEnd(), BaseType, "_s");
21117 DeclRefExpr *MapperVarRef =
21118 buildDeclRefExpr(S, VD, BaseType, SourceLocation());
21119
21120 // Create implicit map clause for mapper.
21122 for (auto *FD : RD->fields()) {
21123 Expr *BE = S.BuildMemberExpr(
21124 MapperVarRef, /*IsArrow=*/false, Range.getBegin(),
21127 /*HadMultipleCandidates=*/false,
21129 FD->getType(), VK_LValue, OK_Ordinary);
21130 SExprs.push_back(BE);
21131 }
21132 CXXScopeSpec MapperIdScopeSpec;
21133 DeclarationNameInfo MapperId;
21134 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
21135
21136 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
21137 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec,
21138 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
21139 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), SExprs,
21140 OMPVarListLocTy());
21141 Maps.push_back(MapClause);
21142 return MapperVarRef;
21143}
21144
21146 DSAStackTy *Stack) {
21147
21148 // Build impilicit map for mapper
21150 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
21151
21152 const RecordDecl *RD = BaseType->getAsRecordDecl();
21153 // AST context is RD's ParentASTContext().
21154 ASTContext &Ctx = RD->getParentASTContext();
21155 // DeclContext is RD's DeclContext.
21156 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
21157
21158 // Create implicit default mapper for "RD".
21159 DeclarationName MapperId;
21160 auto &DeclNames = Ctx.DeclarationNames;
21161 MapperId = DeclNames.getIdentifier(&Ctx.Idents.get("default"));
21162 auto *DMD = OMPDeclareMapperDecl::Create(Ctx, DCT, SourceLocation(), MapperId,
21163 BaseType, MapperId, Maps, nullptr);
21164 Scope *Scope = S.getScopeForContext(DCT);
21165 if (Scope)
21166 S.PushOnScopeChains(DMD, Scope, /*AddToContext=*/false);
21167 DCT->addDecl(DMD);
21168 DMD->setAccess(clang::AS_none);
21169 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
21170 VD->setDeclContext(DMD);
21171 VD->setLexicalDeclContext(DMD);
21172 DMD->addDecl(VD);
21173 DMD->setMapperVarRef(MapperVarRef);
21174 FieldDecl *FD = *RD->field_begin();
21175 // create mapper refence.
21177 DMD, false, SourceLocation(), BaseType, VK_LValue);
21178}
21179
21180// Look up the user-defined mapper given the mapper name and mapper type,
21181// return true if found one.
21182static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
21183 CXXScopeSpec &MapperIdScopeSpec,
21184 const DeclarationNameInfo &MapperId,
21185 QualType Type) {
21186 // Find all user-defined mappers with the given MapperId.
21187 SmallVector<UnresolvedSet<8>, 4> Lookups;
21188 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
21189 Lookup.suppressDiagnostics();
21190 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
21191 /*ObjectType=*/QualType())) {
21192 NamedDecl *D = Lookup.getRepresentativeDecl();
21193 while (S && !S->isDeclScope(D))
21194 S = S->getParent();
21195 if (S)
21196 S = S->getParent();
21197 Lookups.emplace_back();
21198 Lookups.back().append(Lookup.begin(), Lookup.end());
21199 Lookup.clear();
21200 }
21201 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21204 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
21205 return !D->isInvalidDecl() &&
21206 (D->getType()->isDependentType() ||
21207 D->getType()->isInstantiationDependentType() ||
21208 D->getType()->containsUnexpandedParameterPack());
21209 }))
21210 return false;
21211 // Perform argument dependent lookup.
21212 SourceLocation Loc = MapperId.getLoc();
21213 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21214 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
21215 if (filterLookupForUDReductionAndMapper<ValueDecl *>(
21216 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21217 if (!D->isInvalidDecl() &&
21218 SemaRef.Context.hasSameType(D->getType(), Type))
21219 return D;
21220 return nullptr;
21221 }))
21222 return true;
21223 // Find the first user-defined mapper with a type derived from the desired
21224 // type.
21225 auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21226 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21227 if (!D->isInvalidDecl() &&
21228 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
21229 !Type.isMoreQualifiedThan(D->getType(), SemaRef.getASTContext()))
21230 return D;
21231 return nullptr;
21232 });
21233 if (!VD)
21234 return false;
21235 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21236 /*DetectVirtual=*/false);
21237 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
21238 bool IsAmbiguous = !Paths.isAmbiguous(
21240 if (IsAmbiguous)
21241 return false;
21242 if (SemaRef.CheckBaseClassAccess(Loc, VD->getType(), Type, Paths.front(),
21243 /*DiagID=*/0) != Sema::AR_inaccessible)
21244 return true;
21245 }
21246 return false;
21247}
21248
21249static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
21250 QualType CanonType, const Expr *E) {
21251
21252 // DFS over data members in structures/classes.
21254 {CanonType, nullptr});
21255 llvm::DenseMap<const Type *, bool> Visited;
21256 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
21257 while (!Types.empty()) {
21258 auto [BaseType, CurFD] = Types.pop_back_val();
21259 while (ParentChain.back().second == 0)
21260 ParentChain.pop_back();
21261 --ParentChain.back().second;
21262 if (BaseType.isNull())
21263 continue;
21264 // Only structs/classes are allowed to have mappers.
21265 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
21266 if (!RD)
21267 continue;
21268 auto It = Visited.find(BaseType.getTypePtr());
21269 if (It == Visited.end()) {
21270 // Try to find the associated user-defined mapper.
21271 CXXScopeSpec MapperIdScopeSpec;
21272 DeclarationNameInfo DefaultMapperId;
21274 &S.Context.Idents.get("default")));
21275 DefaultMapperId.setLoc(E->getExprLoc());
21276 bool HasUDMapper =
21277 hasUserDefinedMapper(S, Stack->getCurScope(), MapperIdScopeSpec,
21278 DefaultMapperId, BaseType);
21279 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
21280 }
21281 // Found default mapper.
21282 if (It->second)
21283 return true;
21284 // Check for the "default" mapper for data members.
21285 bool FirstIter = true;
21286 for (FieldDecl *FD : RD->fields()) {
21287 if (!FD)
21288 continue;
21289 QualType FieldTy = FD->getType();
21290 if (FieldTy.isNull() ||
21291 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
21292 continue;
21293 if (FirstIter) {
21294 FirstIter = false;
21295 ParentChain.emplace_back(CurFD, 1);
21296 } else {
21297 ++ParentChain.back().second;
21298 }
21299 Types.emplace_back(FieldTy, FD);
21300 }
21301 }
21302 return false;
21303}
21304
21305// Check the validity of the provided variable list for the provided clause kind
21306// \a CKind. In the check process the valid expressions, mappable expression
21307// components, variables, and user-defined mappers are extracted and used to
21308// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
21309// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
21310// and \a MapperId are expected to be valid if the clause kind is 'map'.
21312 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
21313 MappableVarListInfo &MVLI, SourceLocation StartLoc,
21314 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
21315 ArrayRef<Expr *> UnresolvedMappers,
21317 ArrayRef<OpenMPMapModifierKind> Modifiers = {},
21318 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
21319 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
21320 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
21321 "Unexpected clause kind with mappable expressions!");
21322
21323 // If the identifier of user-defined mapper is not specified, it is "default".
21324 // We do not change the actual name in this clause to distinguish whether a
21325 // mapper is specified explicitly, i.e., it is not explicitly specified when
21326 // MapperId.getName() is empty.
21327 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
21328 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
21329 MapperId.setName(DeclNames.getIdentifier(
21330 &SemaRef.getASTContext().Idents.get("default")));
21331 MapperId.setLoc(StartLoc);
21332 }
21333
21334 // Iterators to find the current unresolved mapper expression.
21335 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
21336 bool UpdateUMIt = false;
21337 Expr *UnresolvedMapper = nullptr;
21338
21339 bool HasHoldModifier =
21340 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
21341
21342 // Keep track of the mappable components and base declarations in this clause.
21343 // Each entry in the list is going to have a list of components associated. We
21344 // record each set of the components so that we can build the clause later on.
21345 // In the end we should have the same amount of declarations and component
21346 // lists.
21347
21348 for (Expr *RE : MVLI.VarList) {
21349 assert(RE && "Null expr in omp to/from/map clause");
21350 SourceLocation ELoc = RE->getExprLoc();
21351
21352 // Find the current unresolved mapper expression.
21353 if (UpdateUMIt && UMIt != UMEnd) {
21354 UMIt++;
21355 assert(
21356 UMIt != UMEnd &&
21357 "Expect the size of UnresolvedMappers to match with that of VarList");
21358 }
21359 UpdateUMIt = true;
21360 if (UMIt != UMEnd)
21361 UnresolvedMapper = *UMIt;
21362
21363 const Expr *VE = RE->IgnoreParenLValueCasts();
21364
21365 if (VE->isValueDependent() || VE->isTypeDependent() ||
21368 // Try to find the associated user-defined mapper.
21370 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21371 VE->getType().getCanonicalType(), UnresolvedMapper);
21372 if (ER.isInvalid())
21373 continue;
21374 MVLI.UDMapperList.push_back(ER.get());
21375 // We can only analyze this information once the missing information is
21376 // resolved.
21377 MVLI.ProcessedVarList.push_back(RE);
21378 continue;
21379 }
21380
21381 Expr *SimpleExpr = RE->IgnoreParenCasts();
21382
21383 if (!RE->isLValue()) {
21384 if (SemaRef.getLangOpts().OpenMP < 50) {
21385 SemaRef.Diag(
21386 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
21387 << RE->getSourceRange();
21388 } else {
21389 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21390 << getOpenMPClauseName(CKind) << RE->getSourceRange();
21391 }
21392 continue;
21393 }
21394
21396 ValueDecl *CurDeclaration = nullptr;
21397
21398 // Obtain the array or member expression bases if required. Also, fill the
21399 // components array with all the components identified in the process.
21400 const Expr *BE =
21401 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
21402 DSAS->getCurrentDirective(), NoDiagnose);
21403 if (!BE)
21404 continue;
21405
21406 assert(!CurComponents.empty() &&
21407 "Invalid mappable expression information.");
21408
21409 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
21410 // Add store "this" pointer to class in DSAStackTy for future checking
21411 DSAS->addMappedClassesQualTypes(TE->getType());
21412 // Try to find the associated user-defined mapper.
21414 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21415 VE->getType().getCanonicalType(), UnresolvedMapper);
21416 if (ER.isInvalid())
21417 continue;
21418 MVLI.UDMapperList.push_back(ER.get());
21419 // Skip restriction checking for variable or field declarations
21420 MVLI.ProcessedVarList.push_back(RE);
21421 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21422 MVLI.VarComponents.back().append(CurComponents.begin(),
21423 CurComponents.end());
21424 MVLI.VarBaseDeclarations.push_back(nullptr);
21425 continue;
21426 }
21427
21428 // For the following checks, we rely on the base declaration which is
21429 // expected to be associated with the last component. The declaration is
21430 // expected to be a variable or a field (if 'this' is being mapped).
21431 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
21432 assert(CurDeclaration && "Null decl on map clause.");
21433 assert(
21434 CurDeclaration->isCanonicalDecl() &&
21435 "Expecting components to have associated only canonical declarations.");
21436
21437 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
21438 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
21439
21440 assert((VD || FD) && "Only variables or fields are expected here!");
21441 (void)FD;
21442
21443 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
21444 // threadprivate variables cannot appear in a map clause.
21445 // OpenMP 4.5 [2.10.5, target update Construct]
21446 // threadprivate variables cannot appear in a from clause.
21447 if (VD && DSAS->isThreadPrivate(VD)) {
21448 if (NoDiagnose)
21449 continue;
21450 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21451 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
21452 << getOpenMPClauseName(CKind);
21453 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
21454 continue;
21455 }
21456
21457 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21458 // A list item cannot appear in both a map clause and a data-sharing
21459 // attribute clause on the same construct.
21460
21461 // Check conflicts with other map clause expressions. We check the conflicts
21462 // with the current construct separately from the enclosing data
21463 // environment, because the restrictions are different. We only have to
21464 // check conflicts across regions for the map clauses.
21465 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21466 /*CurrentRegionOnly=*/true, CurComponents, CKind))
21467 break;
21468 if (CKind == OMPC_map &&
21469 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
21470 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21471 /*CurrentRegionOnly=*/false, CurComponents, CKind))
21472 break;
21473
21474 // OpenMP 4.5 [2.10.5, target update Construct]
21475 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21476 // If the type of a list item is a reference to a type T then the type will
21477 // be considered to be T for all purposes of this clause.
21478 auto I = llvm::find_if(
21479 CurComponents,
21481 return MC.getAssociatedDeclaration();
21482 });
21483 assert(I != CurComponents.end() && "Null decl on map clause.");
21484 (void)I;
21485 QualType Type;
21486 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
21487 auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens());
21488 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
21489 if (ASE) {
21490 Type = ASE->getType().getNonReferenceType();
21491 } else if (OASE) {
21492 QualType BaseType =
21494 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21495 Type = ATy->getElementType();
21496 else
21497 Type = BaseType->getPointeeType();
21498 Type = Type.getNonReferenceType();
21499 } else if (OAShE) {
21500 Type = OAShE->getBase()->getType()->getPointeeType();
21501 } else {
21502 Type = VE->getType();
21503 }
21504
21505 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
21506 // A list item in a to or from clause must have a mappable type.
21507 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21508 // A list item must have a mappable type.
21509 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
21510 DSAS, Type, /*FullCheck=*/true))
21511 continue;
21512
21513 if (CKind == OMPC_map) {
21514 // target enter data
21515 // OpenMP [2.10.2, Restrictions, p. 99]
21516 // A map-type must be specified in all map clauses and must be either
21517 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
21518 // no map type is present.
21519 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
21520 if (DKind == OMPD_target_enter_data &&
21521 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
21522 SemaRef.getLangOpts().OpenMP >= 52)) {
21523 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21524 << (IsMapTypeImplicit ? 1 : 0)
21525 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21526 << getOpenMPDirectiveName(DKind);
21527 continue;
21528 }
21529
21530 // target exit_data
21531 // OpenMP [2.10.3, Restrictions, p. 102]
21532 // A map-type must be specified in all map clauses and must be either
21533 // from, release, or delete. Starting with OpenMP 5.2 the default map
21534 // type is `from` if no map type is present.
21535 if (DKind == OMPD_target_exit_data &&
21536 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
21537 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
21538 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21539 << (IsMapTypeImplicit ? 1 : 0)
21540 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21541 << getOpenMPDirectiveName(DKind);
21542 continue;
21543 }
21544
21545 // The 'ompx_hold' modifier is specifically intended to be used on a
21546 // 'target' or 'target data' directive to prevent data from being unmapped
21547 // during the associated statement. It is not permitted on a 'target
21548 // enter data' or 'target exit data' directive, which have no associated
21549 // statement.
21550 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
21551 HasHoldModifier) {
21552 SemaRef.Diag(StartLoc,
21553 diag::err_omp_invalid_map_type_modifier_for_directive)
21555 OMPC_MAP_MODIFIER_ompx_hold)
21556 << getOpenMPDirectiveName(DKind);
21557 continue;
21558 }
21559
21560 // target, target data
21561 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
21562 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
21563 // A map-type in a map clause must be to, from, tofrom or alloc
21564 if ((DKind == OMPD_target_data ||
21566 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
21567 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
21568 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21569 << (IsMapTypeImplicit ? 1 : 0)
21570 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21571 << getOpenMPDirectiveName(DKind);
21572 continue;
21573 }
21574
21575 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
21576 // A list item cannot appear in both a map clause and a data-sharing
21577 // attribute clause on the same construct
21578 //
21579 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
21580 // A list item cannot appear in both a map clause and a data-sharing
21581 // attribute clause on the same construct unless the construct is a
21582 // combined construct.
21583 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
21585 DKind == OMPD_target)) {
21586 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21587 if (isOpenMPPrivate(DVar.CKind)) {
21588 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
21589 << getOpenMPClauseName(DVar.CKind)
21590 << getOpenMPClauseName(OMPC_map)
21591 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
21592 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
21593 continue;
21594 }
21595 }
21596 }
21597
21598 // Try to find the associated user-defined mapper.
21600 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21601 Type.getCanonicalType(), UnresolvedMapper);
21602 if (ER.isInvalid())
21603 continue;
21604 if (!ER.get() && isa<ArraySectionExpr>(VE)) {
21605 // Create implicit mapper as needed.
21606 QualType BaseType = VE->getType().getCanonicalType();
21607 if (BaseType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
21608 const auto *OASE = cast<ArraySectionExpr>(VE->IgnoreParenImpCasts());
21610 QualType ElemType;
21611 if (const auto *ATy = BType->getAsArrayTypeUnsafe())
21612 ElemType = ATy->getElementType();
21613 else
21614 ElemType = BType->getPointeeType();
21615 BaseType = ElemType.getCanonicalType();
21616 }
21617 if (BaseType->getAsRecordDecl() &&
21618 isImplicitMapperNeeded(SemaRef, DSAS, BaseType, VE)) {
21619 ER = buildImplicitMapper(SemaRef, BaseType, DSAS);
21620 }
21621 }
21622 MVLI.UDMapperList.push_back(ER.get());
21623
21624 // Save the current expression.
21625 MVLI.ProcessedVarList.push_back(RE);
21626
21627 // Store the components in the stack so that they can be used to check
21628 // against other clauses later on.
21629 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
21630 /*WhereFoundClauseKind=*/OMPC_map);
21631
21632 // Save the components and declaration to create the clause. For purposes of
21633 // the clause creation, any component list that has base 'this' uses
21634 // null as base declaration.
21635 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21636 MVLI.VarComponents.back().append(CurComponents.begin(),
21637 CurComponents.end());
21638 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
21639 : CurDeclaration);
21640 }
21641}
21642
21644 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
21645 ArrayRef<SourceLocation> MapTypeModifiersLoc,
21646 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
21647 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
21648 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
21649 const OMPVarListLocTy &Locs, bool NoDiagnose,
21650 ArrayRef<Expr *> UnresolvedMappers) {
21651 OpenMPMapModifierKind Modifiers[] = {
21656
21657 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
21658 BuiltinType::OMPIterator))
21659 Diag(IteratorModifier->getExprLoc(),
21660 diag::err_omp_map_modifier_not_iterator);
21661
21662 // Process map-type-modifiers, flag errors for duplicate modifiers.
21663 unsigned Count = 0;
21664 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
21665 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
21666 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
21667 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
21668 continue;
21669 }
21670 assert(Count < NumberOfOMPMapClauseModifiers &&
21671 "Modifiers exceed the allowed number of map type modifiers");
21672 Modifiers[Count] = MapTypeModifiers[I];
21673 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
21674 ++Count;
21675 }
21676
21677 MappableVarListInfo MVLI(VarList);
21679 MapperIdScopeSpec, MapperId, UnresolvedMappers,
21680 MapType, Modifiers, IsMapTypeImplicit,
21681 NoDiagnose);
21682
21683 // We need to produce a map clause even if we don't have variables so that
21684 // other diagnostics related with non-existing map clauses are accurate.
21685 return OMPMapClause::Create(
21686 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
21687 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
21688 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
21689 MapperId, MapType, IsMapTypeImplicit, MapLoc);
21690}
21691
21694 assert(ParsedType.isUsable());
21695
21696 QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get());
21697 if (ReductionType.isNull())
21698 return QualType();
21699
21700 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
21701 // A type name in a declare reduction directive cannot be a function type, an
21702 // array type, a reference type, or a type qualified with const, volatile or
21703 // restrict.
21704 if (ReductionType.hasQualifiers()) {
21705 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
21706 return QualType();
21707 }
21708
21709 if (ReductionType->isFunctionType()) {
21710 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
21711 return QualType();
21712 }
21713 if (ReductionType->isReferenceType()) {
21714 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
21715 return QualType();
21716 }
21717 if (ReductionType->isArrayType()) {
21718 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
21719 return QualType();
21720 }
21721 return ReductionType;
21722}
21723
21726 Scope *S, DeclContext *DC, DeclarationName Name,
21727 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
21728 AccessSpecifier AS, Decl *PrevDeclInScope) {
21730 Decls.reserve(ReductionTypes.size());
21731
21732 LookupResult Lookup(SemaRef, Name, SourceLocation(),
21735 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
21736 // A reduction-identifier may not be re-declared in the current scope for the
21737 // same type or for a type that is compatible according to the base language
21738 // rules.
21739 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21740 OMPDeclareReductionDecl *PrevDRD = nullptr;
21741 bool InCompoundScope = true;
21742 if (S != nullptr) {
21743 // Find previous declaration with the same name not referenced in other
21744 // declarations.
21746 InCompoundScope =
21747 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
21748 SemaRef.LookupName(Lookup, S);
21749 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
21750 /*AllowInlineNamespace=*/false);
21751 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
21752 LookupResult::Filter Filter = Lookup.makeFilter();
21753 while (Filter.hasNext()) {
21754 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
21755 if (InCompoundScope) {
21756 UsedAsPrevious.try_emplace(PrevDecl, false);
21757 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
21758 UsedAsPrevious[D] = true;
21759 }
21760 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21761 PrevDecl->getLocation();
21762 }
21763 Filter.done();
21764 if (InCompoundScope) {
21765 for (const auto &PrevData : UsedAsPrevious) {
21766 if (!PrevData.second) {
21767 PrevDRD = PrevData.first;
21768 break;
21769 }
21770 }
21771 }
21772 } else if (PrevDeclInScope != nullptr) {
21773 auto *PrevDRDInScope = PrevDRD =
21774 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
21775 do {
21776 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
21777 PrevDRDInScope->getLocation();
21778 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
21779 } while (PrevDRDInScope != nullptr);
21780 }
21781 for (const auto &TyData : ReductionTypes) {
21782 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
21783 bool Invalid = false;
21784 if (I != PreviousRedeclTypes.end()) {
21785 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
21786 << TyData.first;
21787 Diag(I->second, diag::note_previous_definition);
21788 Invalid = true;
21789 }
21790 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
21792 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
21793 DC->addDecl(DRD);
21794 DRD->setAccess(AS);
21795 Decls.push_back(DRD);
21796 if (Invalid)
21797 DRD->setInvalidDecl();
21798 else
21799 PrevDRD = DRD;
21800 }
21801
21802 return DeclGroupPtrTy::make(
21803 DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size()));
21804}
21805
21807 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21808
21809 // Enter new function scope.
21813
21814 if (S != nullptr)
21815 SemaRef.PushDeclContext(S, DRD);
21816 else
21817 SemaRef.CurContext = DRD;
21818
21821
21822 QualType ReductionType = DRD->getType();
21823 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
21824 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
21825 // uses semantics of argument handles by value, but it should be passed by
21826 // reference. C lang does not support references, so pass all parameters as
21827 // pointers.
21828 // Create 'T omp_in;' variable.
21829 VarDecl *OmpInParm =
21830 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in");
21831 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
21832 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
21833 // uses semantics of argument handles by value, but it should be passed by
21834 // reference. C lang does not support references, so pass all parameters as
21835 // pointers.
21836 // Create 'T omp_out;' variable.
21837 VarDecl *OmpOutParm =
21838 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out");
21839 if (S != nullptr) {
21840 SemaRef.PushOnScopeChains(OmpInParm, S);
21841 SemaRef.PushOnScopeChains(OmpOutParm, S);
21842 } else {
21843 DRD->addDecl(OmpInParm);
21844 DRD->addDecl(OmpOutParm);
21845 }
21846 Expr *InE =
21847 ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation());
21848 Expr *OutE =
21849 ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation());
21850 DRD->setCombinerData(InE, OutE);
21851}
21852
21854 Expr *Combiner) {
21855 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21858
21861
21862 if (Combiner != nullptr)
21863 DRD->setCombiner(Combiner);
21864 else
21865 DRD->setInvalidDecl();
21866}
21867
21869 Decl *D) {
21870 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21871
21872 // Enter new function scope.
21875
21876 if (S != nullptr)
21877 SemaRef.PushDeclContext(S, DRD);
21878 else
21879 SemaRef.CurContext = DRD;
21880
21883
21884 QualType ReductionType = DRD->getType();
21885 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
21886 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
21887 // uses semantics of argument handles by value, but it should be passed by
21888 // reference. C lang does not support references, so pass all parameters as
21889 // pointers.
21890 // Create 'T omp_priv;' variable.
21891 VarDecl *OmpPrivParm =
21892 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv");
21893 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
21894 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
21895 // uses semantics of argument handles by value, but it should be passed by
21896 // reference. C lang does not support references, so pass all parameters as
21897 // pointers.
21898 // Create 'T omp_orig;' variable.
21899 VarDecl *OmpOrigParm =
21900 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig");
21901 if (S != nullptr) {
21902 SemaRef.PushOnScopeChains(OmpPrivParm, S);
21903 SemaRef.PushOnScopeChains(OmpOrigParm, S);
21904 } else {
21905 DRD->addDecl(OmpPrivParm);
21906 DRD->addDecl(OmpOrigParm);
21907 }
21908 Expr *OrigE =
21909 ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation());
21910 Expr *PrivE =
21911 ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation());
21912 DRD->setInitializerData(OrigE, PrivE);
21913 return OmpPrivParm;
21914}
21915
21917 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
21918 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21921
21924
21925 if (Initializer != nullptr) {
21926 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
21927 } else if (OmpPrivParm->hasInit()) {
21928 DRD->setInitializer(OmpPrivParm->getInit(),
21929 OmpPrivParm->isDirectInit()
21932 } else {
21933 DRD->setInvalidDecl();
21934 }
21935}
21936
21938 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
21939 for (Decl *D : DeclReductions.get()) {
21940 if (IsValid) {
21941 if (S)
21942 SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
21943 /*AddToContext=*/false);
21944 } else {
21945 D->setInvalidDecl();
21946 }
21947 }
21948 return DeclReductions;
21949}
21950
21952 Declarator &D) {
21954 QualType T = TInfo->getType();
21955 if (D.isInvalidType())
21956 return true;
21957
21958 if (getLangOpts().CPlusPlus) {
21959 // Check that there are no default arguments (C++ only).
21961 }
21962
21963 return SemaRef.CreateParsedType(T, TInfo);
21964}
21965
21968 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
21969
21971 assert(!MapperType.isNull() && "Expect valid mapper type");
21972
21973 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21974 // The type must be of struct, union or class type in C and C++
21975 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
21976 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
21977 return QualType();
21978 }
21979 return MapperType;
21980}
21981
21983 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
21985 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
21986 LookupResult Lookup(SemaRef, Name, SourceLocation(),
21989 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21990 // A mapper-identifier may not be redeclared in the current scope for the
21991 // same type or for a type that is compatible according to the base language
21992 // rules.
21993 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21994 OMPDeclareMapperDecl *PrevDMD = nullptr;
21995 bool InCompoundScope = true;
21996 if (S != nullptr) {
21997 // Find previous declaration with the same name not referenced in other
21998 // declarations.
22000 InCompoundScope =
22001 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22002 SemaRef.LookupName(Lookup, S);
22003 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22004 /*AllowInlineNamespace=*/false);
22005 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
22006 LookupResult::Filter Filter = Lookup.makeFilter();
22007 while (Filter.hasNext()) {
22008 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
22009 if (InCompoundScope) {
22010 UsedAsPrevious.try_emplace(PrevDecl, false);
22011 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
22012 UsedAsPrevious[D] = true;
22013 }
22014 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22015 PrevDecl->getLocation();
22016 }
22017 Filter.done();
22018 if (InCompoundScope) {
22019 for (const auto &PrevData : UsedAsPrevious) {
22020 if (!PrevData.second) {
22021 PrevDMD = PrevData.first;
22022 break;
22023 }
22024 }
22025 }
22026 } else if (PrevDeclInScope) {
22027 auto *PrevDMDInScope = PrevDMD =
22028 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
22029 do {
22030 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
22031 PrevDMDInScope->getLocation();
22032 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
22033 } while (PrevDMDInScope != nullptr);
22034 }
22035 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
22036 bool Invalid = false;
22037 if (I != PreviousRedeclTypes.end()) {
22038 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
22039 << MapperType << Name;
22040 Diag(I->second, diag::note_previous_definition);
22041 Invalid = true;
22042 }
22043 // Build expressions for implicit maps of data members with 'default'
22044 // mappers.
22045 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
22046 if (getLangOpts().OpenMP >= 50)
22048 ClausesWithImplicit);
22049 auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name,
22050 MapperType, VN, ClausesWithImplicit,
22051 PrevDMD);
22052 if (S)
22053 SemaRef.PushOnScopeChains(DMD, S);
22054 else
22055 DC->addDecl(DMD);
22056 DMD->setAccess(AS);
22057 if (Invalid)
22058 DMD->setInvalidDecl();
22059
22060 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22061 VD->setDeclContext(DMD);
22062 VD->setLexicalDeclContext(DMD);
22063 DMD->addDecl(VD);
22064 DMD->setMapperVarRef(MapperVarRef);
22065
22067}
22068
22070 Scope *S, QualType MapperType, SourceLocation StartLoc,
22071 DeclarationName VN) {
22072 TypeSourceInfo *TInfo =
22073 getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc);
22074 auto *VD = VarDecl::Create(
22075 getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc,
22076 StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None);
22077 if (S)
22078 SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false);
22079 Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc);
22080 DSAStack->addDeclareMapperVarRef(E);
22081 return E;
22082}
22083
22085 if (DSAStack->getDeclareMapperVarRef())
22086 DSAStack->addIteratorVarDecl(VD);
22087}
22088
22090 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
22091 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
22092 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
22093 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
22094 return true;
22096 return true;
22097 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
22098 return true;
22099 return false;
22100 }
22101 return true;
22102}
22103
22105 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
22106 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
22107}
22108
22110 SourceLocation StartLoc,
22111 SourceLocation LParenLoc,
22112 SourceLocation EndLoc) {
22113 if (VarList.empty())
22114 return nullptr;
22115
22116 for (Expr *ValExpr : VarList) {
22117 // OpenMP [teams Constrcut, Restrictions]
22118 // The num_teams expression must evaluate to a positive integer value.
22119 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams,
22120 /*StrictlyPositive=*/true))
22121 return nullptr;
22122 }
22123
22124 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22126 DKind, OMPC_num_teams, getLangOpts().OpenMP);
22127 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
22128 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
22129 LParenLoc, EndLoc, VarList,
22130 /*PreInit=*/nullptr);
22131
22132 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22134 for (Expr *ValExpr : VarList) {
22135 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22136 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22137 Vars.push_back(ValExpr);
22138 }
22139
22140 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
22141 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
22142 LParenLoc, EndLoc, Vars, PreInit);
22143}
22144
22146 SourceLocation StartLoc,
22147 SourceLocation LParenLoc,
22148 SourceLocation EndLoc) {
22149 if (VarList.empty())
22150 return nullptr;
22151
22152 for (Expr *ValExpr : VarList) {
22153 // OpenMP [teams Constrcut, Restrictions]
22154 // The thread_limit expression must evaluate to a positive integer value.
22155 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit,
22156 /*StrictlyPositive=*/true))
22157 return nullptr;
22158 }
22159
22160 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22162 DKind, OMPC_thread_limit, getLangOpts().OpenMP);
22163 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
22164 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion,
22165 StartLoc, LParenLoc, EndLoc, VarList,
22166 /*PreInit=*/nullptr);
22167
22168 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22170 for (Expr *ValExpr : VarList) {
22171 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22172 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22173 Vars.push_back(ValExpr);
22174 }
22175
22176 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
22177 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion, StartLoc,
22178 LParenLoc, EndLoc, Vars, PreInit);
22179}
22180
22182 SourceLocation StartLoc,
22183 SourceLocation LParenLoc,
22184 SourceLocation EndLoc) {
22185 Expr *ValExpr = Priority;
22186 Stmt *HelperValStmt = nullptr;
22187 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22188
22189 // OpenMP [2.9.1, task Constrcut]
22190 // The priority-value is a non-negative numerical scalar expression.
22192 ValExpr, SemaRef, OMPC_priority,
22193 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
22194 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22195 return nullptr;
22196
22197 return new (getASTContext()) OMPPriorityClause(
22198 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22199}
22200
22202 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
22203 SourceLocation StartLoc, SourceLocation LParenLoc,
22204 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22205 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
22206 "Unexpected grainsize modifier in OpenMP < 51.");
22207
22208 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
22209 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
22211 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22212 << Values << getOpenMPClauseName(OMPC_grainsize);
22213 return nullptr;
22214 }
22215
22216 Expr *ValExpr = Grainsize;
22217 Stmt *HelperValStmt = nullptr;
22218 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22219
22220 // OpenMP [2.9.2, taskloop Constrcut]
22221 // The parameter of the grainsize clause must be a positive integer
22222 // expression.
22223 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize,
22224 /*StrictlyPositive=*/true,
22225 /*BuildCapture=*/true,
22226 DSAStack->getCurrentDirective(),
22227 &CaptureRegion, &HelperValStmt))
22228 return nullptr;
22229
22230 return new (getASTContext())
22231 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22232 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22233}
22234
22236 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
22237 SourceLocation StartLoc, SourceLocation LParenLoc,
22238 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22239 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
22240 "Unexpected num_tasks modifier in OpenMP < 51.");
22241
22242 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
22243 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
22245 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22246 << Values << getOpenMPClauseName(OMPC_num_tasks);
22247 return nullptr;
22248 }
22249
22250 Expr *ValExpr = NumTasks;
22251 Stmt *HelperValStmt = nullptr;
22252 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22253
22254 // OpenMP [2.9.2, taskloop Constrcut]
22255 // The parameter of the num_tasks clause must be a positive integer
22256 // expression.
22258 ValExpr, SemaRef, OMPC_num_tasks,
22259 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
22260 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22261 return nullptr;
22262
22263 return new (getASTContext())
22264 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22265 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22266}
22267
22269 SourceLocation StartLoc,
22270 SourceLocation LParenLoc,
22271 SourceLocation EndLoc) {
22272 // OpenMP [2.13.2, critical construct, Description]
22273 // ... where hint-expression is an integer constant expression that evaluates
22274 // to a valid lock hint.
22275 ExprResult HintExpr =
22276 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
22277 if (HintExpr.isInvalid())
22278 return nullptr;
22279 return new (getASTContext())
22280 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
22281}
22282
22283/// Tries to find omp_event_handle_t type.
22285 DSAStackTy *Stack) {
22286 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
22287 if (!OMPEventHandleT.isNull())
22288 return true;
22289 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
22290 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
22291 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
22292 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
22293 return false;
22294 }
22295 Stack->setOMPEventHandleT(PT.get());
22296 return true;
22297}
22298
22300 SourceLocation StartLoc,
22301 SourceLocation LParenLoc,
22302 SourceLocation EndLoc) {
22303 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
22304 !Evt->isInstantiationDependent() &&
22307 return nullptr;
22308 // OpenMP 5.0, 2.10.1 task Construct.
22309 // event-handle is a variable of the omp_event_handle_t type.
22310 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
22311 if (!Ref) {
22312 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22313 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22314 return nullptr;
22315 }
22316 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
22317 if (!VD) {
22318 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22319 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22320 return nullptr;
22321 }
22322 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
22323 VD->getType()) ||
22324 VD->getType().isConstant(getASTContext())) {
22325 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22326 << "omp_event_handle_t" << 1 << VD->getType()
22327 << Evt->getSourceRange();
22328 return nullptr;
22329 }
22330 // OpenMP 5.0, 2.10.1 task Construct
22331 // [detach clause]... The event-handle will be considered as if it was
22332 // specified on a firstprivate clause.
22333 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
22334 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
22335 DVar.RefExpr) {
22336 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
22337 << getOpenMPClauseName(DVar.CKind)
22338 << getOpenMPClauseName(OMPC_firstprivate);
22340 return nullptr;
22341 }
22342 }
22343
22344 return new (getASTContext())
22345 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
22346}
22347
22349 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
22350 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
22351 SourceLocation EndLoc) {
22352 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
22353 std::string Values;
22354 Values += "'";
22355 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
22356 Values += "'";
22357 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22358 << Values << getOpenMPClauseName(OMPC_dist_schedule);
22359 return nullptr;
22360 }
22361 Expr *ValExpr = ChunkSize;
22362 Stmt *HelperValStmt = nullptr;
22363 if (ChunkSize) {
22364 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
22365 !ChunkSize->isInstantiationDependent() &&
22366 !ChunkSize->containsUnexpandedParameterPack()) {
22367 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
22368 ExprResult Val =
22369 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
22370 if (Val.isInvalid())
22371 return nullptr;
22372
22373 ValExpr = Val.get();
22374
22375 // OpenMP [2.7.1, Restrictions]
22376 // chunk_size must be a loop invariant integer expression with a positive
22377 // value.
22378 if (std::optional<llvm::APSInt> Result =
22380 if (Result->isSigned() && !Result->isStrictlyPositive()) {
22381 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
22382 << "dist_schedule" << ChunkSize->getSourceRange();
22383 return nullptr;
22384 }
22386 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
22387 getLangOpts().OpenMP) != OMPD_unknown &&
22389 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22390 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22391 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22392 HelperValStmt = buildPreInits(getASTContext(), Captures);
22393 }
22394 }
22395 }
22396
22397 return new (getASTContext())
22398 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
22399 Kind, ValExpr, HelperValStmt);
22400}
22401
22404 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
22405 SourceLocation KindLoc, SourceLocation EndLoc) {
22406 if (getLangOpts().OpenMP < 50) {
22407 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
22408 Kind != OMPC_DEFAULTMAP_scalar) {
22409 std::string Value;
22411 Value += "'";
22412 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
22413 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22414 OMPC_DEFAULTMAP_MODIFIER_tofrom);
22415 Loc = MLoc;
22416 } else {
22417 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22418 OMPC_DEFAULTMAP_scalar);
22419 Loc = KindLoc;
22420 }
22421 Value += "'";
22422 Diag(Loc, diag::err_omp_unexpected_clause_value)
22423 << Value << getOpenMPClauseName(OMPC_defaultmap);
22424 return nullptr;
22425 }
22426 } else {
22427 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
22428 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
22429 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
22430 if (!isDefaultmapKind || !isDefaultmapModifier) {
22431 StringRef KindValue = getLangOpts().OpenMP < 52
22432 ? "'scalar', 'aggregate', 'pointer'"
22433 : "'scalar', 'aggregate', 'pointer', 'all'";
22434 if (getLangOpts().OpenMP == 50) {
22435 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
22436 "'firstprivate', 'none', 'default'";
22437 if (!isDefaultmapKind && isDefaultmapModifier) {
22438 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22439 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22440 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22441 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22442 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22443 } else {
22444 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22445 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22446 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22447 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22448 }
22449 } else {
22450 StringRef ModifierValue =
22451 "'alloc', 'from', 'to', 'tofrom', "
22452 "'firstprivate', 'none', 'default', 'present'";
22453 if (!isDefaultmapKind && isDefaultmapModifier) {
22454 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22455 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22456 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22457 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22458 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22459 } else {
22460 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22461 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22462 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22463 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22464 }
22465 }
22466 return nullptr;
22467 }
22468
22469 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
22470 // At most one defaultmap clause for each category can appear on the
22471 // directive.
22472 if (DSAStack->checkDefaultmapCategory(Kind)) {
22473 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
22474 return nullptr;
22475 }
22476 }
22477 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
22478 // Variable category is not specified - mark all categories.
22479 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
22480 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
22481 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
22482 } else {
22483 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
22484 }
22485
22486 return new (getASTContext())
22487 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
22488}
22489
22492 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
22493 if (!CurLexicalContext->isFileContext() &&
22494 !CurLexicalContext->isExternCContext() &&
22495 !CurLexicalContext->isExternCXXContext() &&
22496 !isa<CXXRecordDecl>(CurLexicalContext) &&
22497 !isa<ClassTemplateDecl>(CurLexicalContext) &&
22498 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
22499 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
22500 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
22501 return false;
22502 }
22503
22504 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
22505 if (getLangOpts().HIP)
22506 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
22507
22508 DeclareTargetNesting.push_back(DTCI);
22509 return true;
22510}
22511
22514 assert(!DeclareTargetNesting.empty() &&
22515 "check isInOpenMPDeclareTargetContext() first!");
22516 return DeclareTargetNesting.pop_back_val();
22517}
22518
22521 for (auto &It : DTCI.ExplicitlyMapped)
22522 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
22523}
22524
22526 if (DeclareTargetNesting.empty())
22527 return;
22528 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
22529 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
22530 << getOpenMPDirectiveName(DTCI.Kind);
22531}
22532
22534 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
22536 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
22537 /*ObjectType=*/QualType(),
22538 /*AllowBuiltinCreation=*/true);
22539
22540 if (Lookup.isAmbiguous())
22541 return nullptr;
22542 Lookup.suppressDiagnostics();
22543
22544 if (!Lookup.isSingleResult()) {
22545 VarOrFuncDeclFilterCCC CCC(SemaRef);
22546 if (TypoCorrection Corrected =
22547 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
22549 SemaRef.diagnoseTypo(Corrected,
22550 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
22551 << Id.getName());
22552 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
22553 return nullptr;
22554 }
22555
22556 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
22557 return nullptr;
22558 }
22559
22560 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
22561 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
22562 !isa<FunctionTemplateDecl>(ND)) {
22563 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
22564 return nullptr;
22565 }
22566 return ND;
22567}
22568
22570 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
22572 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
22573 isa<FunctionTemplateDecl>(ND)) &&
22574 "Expected variable, function or function template.");
22575
22576 if (auto *VD = dyn_cast<VarDecl>(ND)) {
22577 // Only global variables can be marked as declare target.
22578 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22579 !VD->isStaticDataMember()) {
22580 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
22581 << VD->getNameAsString();
22582 return;
22583 }
22584 }
22585 // Diagnose marking after use as it may lead to incorrect diagnosis and
22586 // codegen.
22587 if (getLangOpts().OpenMP >= 50 &&
22588 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
22589 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
22590
22591 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
22592 if (getLangOpts().HIP)
22593 Diag(Loc, diag::warn_hip_omp_target_directives);
22594
22595 // Explicit declare target lists have precedence.
22596 const unsigned Level = -1;
22597
22598 auto *VD = cast<ValueDecl>(ND);
22599 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22600 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22601 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
22602 (*ActiveAttr)->getLevel() == Level) {
22603 Diag(Loc, diag::err_omp_device_type_mismatch)
22604 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
22605 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
22606 (*ActiveAttr)->getDevType());
22607 return;
22608 }
22609 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
22610 (*ActiveAttr)->getLevel() == Level) {
22611 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
22612 return;
22613 }
22614
22615 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
22616 return;
22617
22618 Expr *IndirectE = nullptr;
22619 bool IsIndirect = false;
22620 if (DTCI.Indirect) {
22621 IndirectE = *DTCI.Indirect;
22622 if (!IndirectE)
22623 IsIndirect = true;
22624 }
22625 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22626 getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level,
22627 SourceRange(Loc, Loc));
22628 ND->addAttr(A);
22629 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
22630 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
22632 if (auto *VD = dyn_cast<VarDecl>(ND);
22633 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
22634 VD->hasGlobalStorage())
22636}
22637
22639 Sema &SemaRef, Decl *D) {
22640 if (!D || !isa<VarDecl>(D))
22641 return;
22642 auto *VD = cast<VarDecl>(D);
22643 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
22644 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
22645 if (SemaRef.LangOpts.OpenMP >= 50 &&
22646 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
22647 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
22648 VD->hasGlobalStorage()) {
22649 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
22650 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
22651 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
22652 // If a lambda declaration and definition appears between a
22653 // declare target directive and the matching end declare target
22654 // directive, all variables that are captured by the lambda
22655 // expression must also appear in a to clause.
22656 SemaRef.Diag(VD->getLocation(),
22657 diag::err_omp_lambda_capture_in_declare_target_not_to);
22658 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
22659 << VD << 0 << SR;
22660 return;
22661 }
22662 }
22663 if (MapTy)
22664 return;
22665 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
22666 SemaRef.Diag(SL, diag::note_used_here) << SR;
22667}
22668
22670 Sema &SemaRef, DSAStackTy *Stack,
22671 ValueDecl *VD) {
22672 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
22673 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
22674 /*FullCheck=*/false);
22675}
22676
22678 SourceLocation IdLoc) {
22679 if (!D || D->isInvalidDecl())
22680 return;
22682 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
22683 if (auto *VD = dyn_cast<VarDecl>(D)) {
22684 // Only global variables can be marked as declare target.
22685 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22686 !VD->isStaticDataMember())
22687 return;
22688 // 2.10.6: threadprivate variable cannot appear in a declare target
22689 // directive.
22690 if (DSAStack->isThreadPrivate(VD)) {
22691 Diag(SL, diag::err_omp_threadprivate_in_target);
22692 reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false));
22693 return;
22694 }
22695 }
22696 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
22697 D = FTD->getTemplatedDecl();
22698 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
22699 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
22700 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
22701 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
22702 Diag(IdLoc, diag::err_omp_function_in_link_clause);
22703 Diag(FD->getLocation(), diag::note_defined_here) << FD;
22704 return;
22705 }
22706 }
22707 if (auto *VD = dyn_cast<ValueDecl>(D)) {
22708 // Problem if any with var declared with incomplete type will be reported
22709 // as normal, so no need to check it here.
22710 if ((E || !VD->getType()->isIncompleteType()) &&
22712 return;
22714 // Checking declaration inside declare target region.
22715 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
22716 isa<FunctionTemplateDecl>(D)) {
22717 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22718 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22719 unsigned Level = DeclareTargetNesting.size();
22720 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
22721 return;
22722 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
22723 Expr *IndirectE = nullptr;
22724 bool IsIndirect = false;
22725 if (DTCI.Indirect) {
22726 IndirectE = *DTCI.Indirect;
22727 if (!IndirectE)
22728 IsIndirect = true;
22729 }
22730 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22731 getASTContext(),
22732 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
22733 : OMPDeclareTargetDeclAttr::MT_To,
22734 DTCI.DT, IndirectE, IsIndirect, Level,
22735 SourceRange(DTCI.Loc, DTCI.Loc));
22736 D->addAttr(A);
22737 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
22738 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
22739 }
22740 return;
22741 }
22742 }
22743 if (!E)
22744 return;
22746}
22747
22748/// This class visits every VarDecl that the initializer references and adds
22749/// OMPDeclareTargetDeclAttr to each of them.
22750class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
22751 SmallVector<VarDecl *> DeclVector;
22752 Attr *A;
22753
22754public:
22755 /// A StmtVisitor class function that visits all DeclRefExpr and adds
22756 /// OMPDeclareTargetDeclAttr to them.
22758 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
22759 VD->addAttr(A);
22760 DeclVector.push_back(VD);
22761 }
22762 }
22763 /// A function that iterates across each of the Expr's children.
22764 void VisitExpr(Expr *Ex) {
22765 for (auto *Child : Ex->children()) {
22766 Visit(Child);
22767 }
22768 }
22769 /// A function that keeps a record of all the Decls that are variables, has
22770 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
22771 /// each Decl one at a time and use the inherited 'visit' functions to look
22772 /// for DeclRefExpr.
22774 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
22775 DeclVector.push_back(cast<VarDecl>(TD));
22776 while (!DeclVector.empty()) {
22777 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
22778 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
22779 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
22780 if (Expr *Ex = TargetVarDecl->getInit())
22781 Visit(Ex);
22782 }
22783 }
22784 }
22785};
22786
22787/// Adding OMPDeclareTargetDeclAttr to variables with static storage
22788/// duration that are referenced in the initializer expression list of
22789/// variables with static storage duration in declare target directive.
22791 GlobalDeclRefChecker Checker;
22792 if (isa<VarDecl>(TargetDecl))
22793 Checker.declareTargetInitializer(TargetDecl);
22794}
22795
22797 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
22798 ArrayRef<SourceLocation> MotionModifiersLoc,
22799 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22800 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22801 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
22805
22806 // Process motion-modifiers, flag errors for duplicate modifiers.
22807 unsigned Count = 0;
22808 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
22809 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
22810 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22811 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22812 continue;
22813 }
22814 assert(Count < NumberOfOMPMotionModifiers &&
22815 "Modifiers exceed the allowed number of motion modifiers");
22816 Modifiers[Count] = MotionModifiers[I];
22817 ModifiersLoc[Count] = MotionModifiersLoc[I];
22818 ++Count;
22819 }
22820
22821 MappableVarListInfo MVLI(VarList);
22823 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22824 if (MVLI.ProcessedVarList.empty())
22825 return nullptr;
22826
22827 return OMPToClause::Create(
22828 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22829 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22830 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
22831}
22832
22834 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
22835 ArrayRef<SourceLocation> MotionModifiersLoc,
22836 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22837 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22838 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
22842
22843 // Process motion-modifiers, flag errors for duplicate modifiers.
22844 unsigned Count = 0;
22845 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
22846 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
22847 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22848 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22849 continue;
22850 }
22851 assert(Count < NumberOfOMPMotionModifiers &&
22852 "Modifiers exceed the allowed number of motion modifiers");
22853 Modifiers[Count] = MotionModifiers[I];
22854 ModifiersLoc[Count] = MotionModifiersLoc[I];
22855 ++Count;
22856 }
22857
22858 MappableVarListInfo MVLI(VarList);
22859 checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
22860 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22861 if (MVLI.ProcessedVarList.empty())
22862 return nullptr;
22863
22864 return OMPFromClause::Create(
22865 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22866 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22867 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
22868}
22869
22870OMPClause *
22872 const OMPVarListLocTy &Locs) {
22873 MappableVarListInfo MVLI(VarList);
22874 SmallVector<Expr *, 8> PrivateCopies;
22876
22877 for (Expr *RefExpr : VarList) {
22878 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
22879 SourceLocation ELoc;
22880 SourceRange ERange;
22881 Expr *SimpleRefExpr = RefExpr;
22882 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
22883 if (Res.second) {
22884 // It will be analyzed later.
22885 MVLI.ProcessedVarList.push_back(RefExpr);
22886 PrivateCopies.push_back(nullptr);
22887 Inits.push_back(nullptr);
22888 }
22889 ValueDecl *D = Res.first;
22890 if (!D)
22891 continue;
22892
22893 QualType Type = D->getType();
22894 Type = Type.getNonReferenceType().getUnqualifiedType();
22895
22896 auto *VD = dyn_cast<VarDecl>(D);
22897
22898 // Item should be a pointer or reference to pointer.
22899 if (!Type->isPointerType()) {
22900 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
22901 << 0 << RefExpr->getSourceRange();
22902 continue;
22903 }
22904
22905 // Build the private variable and the expression that refers to it.
22906 auto VDPrivate =
22907 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
22908 D->hasAttrs() ? &D->getAttrs() : nullptr,
22909 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
22910 if (VDPrivate->isInvalidDecl())
22911 continue;
22912
22913 SemaRef.CurContext->addDecl(VDPrivate);
22914 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
22915 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
22916
22917 // Add temporary variable to initialize the private copy of the pointer.
22918 VarDecl *VDInit =
22919 buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp");
22920 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
22921 SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
22923 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
22924 /*DirectInit=*/false);
22925
22926 // If required, build a capture to implement the privatization initialized
22927 // with the current list item value.
22928 DeclRefExpr *Ref = nullptr;
22929 if (!VD)
22930 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
22931 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22932 PrivateCopies.push_back(VDPrivateRefExpr);
22933 Inits.push_back(VDInitRefExpr);
22934
22935 // We need to add a data sharing attribute for this variable to make sure it
22936 // is correctly captured. A variable that shows up in a use_device_ptr has
22937 // similar properties of a first private variable.
22938 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22939
22940 // Create a mappable component for the list item. List items in this clause
22941 // only need a component.
22942 MVLI.VarBaseDeclarations.push_back(D);
22943 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22944 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
22945 /*IsNonContiguous=*/false);
22946 }
22947
22948 if (MVLI.ProcessedVarList.empty())
22949 return nullptr;
22950
22952 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
22953 MVLI.VarBaseDeclarations, MVLI.VarComponents);
22954}
22955
22956OMPClause *
22958 const OMPVarListLocTy &Locs) {
22959 MappableVarListInfo MVLI(VarList);
22960
22961 for (Expr *RefExpr : VarList) {
22962 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
22963 SourceLocation ELoc;
22964 SourceRange ERange;
22965 Expr *SimpleRefExpr = RefExpr;
22966 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
22967 /*AllowArraySection=*/true);
22968 if (Res.second) {
22969 // It will be analyzed later.
22970 MVLI.ProcessedVarList.push_back(RefExpr);
22971 }
22972 ValueDecl *D = Res.first;
22973 if (!D)
22974 continue;
22975 auto *VD = dyn_cast<VarDecl>(D);
22976
22977 // If required, build a capture to implement the privatization initialized
22978 // with the current list item value.
22979 DeclRefExpr *Ref = nullptr;
22980 if (!VD)
22981 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
22982 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22983
22984 // We need to add a data sharing attribute for this variable to make sure it
22985 // is correctly captured. A variable that shows up in a use_device_addr has
22986 // similar properties of a first private variable.
22987 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22988
22989 // Create a mappable component for the list item. List items in this clause
22990 // only need a component.
22991 MVLI.VarBaseDeclarations.push_back(D);
22992 MVLI.VarComponents.emplace_back();
22993 Expr *Component = SimpleRefExpr;
22994 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
22995 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
22996 Component =
22998 MVLI.VarComponents.back().emplace_back(Component, D,
22999 /*IsNonContiguous=*/false);
23000 }
23001
23002 if (MVLI.ProcessedVarList.empty())
23003 return nullptr;
23004
23006 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23007 MVLI.VarComponents);
23008}
23009
23010OMPClause *
23012 const OMPVarListLocTy &Locs) {
23013 MappableVarListInfo MVLI(VarList);
23014 for (Expr *RefExpr : VarList) {
23015 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
23016 SourceLocation ELoc;
23017 SourceRange ERange;
23018 Expr *SimpleRefExpr = RefExpr;
23019 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23020 if (Res.second) {
23021 // It will be analyzed later.
23022 MVLI.ProcessedVarList.push_back(RefExpr);
23023 }
23024 ValueDecl *D = Res.first;
23025 if (!D)
23026 continue;
23027
23028 QualType Type = D->getType();
23029 // item should be a pointer or array or reference to pointer or array
23030 if (!Type.getNonReferenceType()->isPointerType() &&
23031 !Type.getNonReferenceType()->isArrayType()) {
23032 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
23033 << 0 << RefExpr->getSourceRange();
23034 continue;
23035 }
23036
23037 // Check if the declaration in the clause does not show up in any data
23038 // sharing attribute.
23039 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23040 if (isOpenMPPrivate(DVar.CKind)) {
23041 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23042 << getOpenMPClauseName(DVar.CKind)
23043 << getOpenMPClauseName(OMPC_is_device_ptr)
23044 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
23046 continue;
23047 }
23048
23049 const Expr *ConflictExpr;
23050 if (DSAStack->checkMappableExprComponentListsForDecl(
23051 D, /*CurrentRegionOnly=*/true,
23052 [&ConflictExpr](
23054 OpenMPClauseKind) -> bool {
23055 ConflictExpr = R.front().getAssociatedExpression();
23056 return true;
23057 })) {
23058 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23059 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23060 << ConflictExpr->getSourceRange();
23061 continue;
23062 }
23063
23064 // Store the components in the stack so that they can be used to check
23065 // against other clauses later on.
23067 SimpleRefExpr, D, /*IsNonContiguous=*/false);
23068 DSAStack->addMappableExpressionComponents(
23069 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
23070
23071 // Record the expression we've just processed.
23072 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
23073
23074 // Create a mappable component for the list item. List items in this clause
23075 // only need a component. We use a null declaration to signal fields in
23076 // 'this'.
23077 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23078 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23079 "Unexpected device pointer expression!");
23080 MVLI.VarBaseDeclarations.push_back(
23081 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23082 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23083 MVLI.VarComponents.back().push_back(MC);
23084 }
23085
23086 if (MVLI.ProcessedVarList.empty())
23087 return nullptr;
23088
23090 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23091 MVLI.VarComponents);
23092}
23093
23094OMPClause *
23096 const OMPVarListLocTy &Locs) {
23097 MappableVarListInfo MVLI(VarList);
23098 for (Expr *RefExpr : VarList) {
23099 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
23100 SourceLocation ELoc;
23101 SourceRange ERange;
23102 Expr *SimpleRefExpr = RefExpr;
23103 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23104 /*AllowArraySection=*/true);
23105 if (Res.second) {
23106 // It will be analyzed later.
23107 MVLI.ProcessedVarList.push_back(RefExpr);
23108 }
23109 ValueDecl *D = Res.first;
23110 if (!D)
23111 continue;
23112
23113 // Check if the declaration in the clause does not show up in any data
23114 // sharing attribute.
23115 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23116 if (isOpenMPPrivate(DVar.CKind)) {
23117 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23118 << getOpenMPClauseName(DVar.CKind)
23119 << getOpenMPClauseName(OMPC_has_device_addr)
23120 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
23122 continue;
23123 }
23124
23125 const Expr *ConflictExpr;
23126 if (DSAStack->checkMappableExprComponentListsForDecl(
23127 D, /*CurrentRegionOnly=*/true,
23128 [&ConflictExpr](
23130 OpenMPClauseKind) -> bool {
23131 ConflictExpr = R.front().getAssociatedExpression();
23132 return true;
23133 })) {
23134 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23135 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23136 << ConflictExpr->getSourceRange();
23137 continue;
23138 }
23139
23140 // Store the components in the stack so that they can be used to check
23141 // against other clauses later on.
23142 Expr *Component = SimpleRefExpr;
23143 auto *VD = dyn_cast<VarDecl>(D);
23144 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23145 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23146 Component =
23149 Component, D, /*IsNonContiguous=*/false);
23150 DSAStack->addMappableExpressionComponents(
23151 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
23152
23153 // Record the expression we've just processed.
23154 if (!VD && !SemaRef.CurContext->isDependentContext()) {
23155 DeclRefExpr *Ref =
23156 buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
23157 assert(Ref && "has_device_addr capture failed");
23158 MVLI.ProcessedVarList.push_back(Ref);
23159 } else
23160 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
23161
23162 // Create a mappable component for the list item. List items in this clause
23163 // only need a component. We use a null declaration to signal fields in
23164 // 'this'.
23165 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23166 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23167 "Unexpected device pointer expression!");
23168 MVLI.VarBaseDeclarations.push_back(
23169 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23170 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23171 MVLI.VarComponents.back().push_back(MC);
23172 }
23173
23174 if (MVLI.ProcessedVarList.empty())
23175 return nullptr;
23176
23178 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23179 MVLI.VarComponents);
23180}
23181
23183 Expr *Allocator, Expr *Alignment,
23184 OpenMPAllocateClauseModifier FirstAllocateModifier,
23185 SourceLocation FirstAllocateModifierLoc,
23186 OpenMPAllocateClauseModifier SecondAllocateModifier,
23187 SourceLocation SecondAllocateModifierLoc, ArrayRef<Expr *> VarList,
23188 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
23189 SourceLocation EndLoc) {
23190 if (Allocator) {
23191 // Allocator expression is dependent - skip it for now and build the
23192 // allocator when instantiated.
23193 bool AllocDependent =
23194 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
23195 Allocator->isInstantiationDependent() ||
23196 Allocator->containsUnexpandedParameterPack());
23197 if (!AllocDependent) {
23198 // OpenMP [2.11.4 allocate Clause, Description]
23199 // allocator is an expression of omp_allocator_handle_t type.
23200 if (!findOMPAllocatorHandleT(SemaRef, Allocator->getExprLoc(), DSAStack))
23201 return nullptr;
23202
23203 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
23204 if (AllocatorRes.isInvalid())
23205 return nullptr;
23206 AllocatorRes = SemaRef.PerformImplicitConversion(
23207 AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
23209 /*AllowExplicit=*/true);
23210 if (AllocatorRes.isInvalid())
23211 return nullptr;
23212 Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr;
23213 }
23214 } else {
23215 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
23216 // allocate clauses that appear on a target construct or on constructs in a
23217 // target region must specify an allocator expression unless a requires
23218 // directive with the dynamic_allocators clause is present in the same
23219 // compilation unit.
23220 if (getLangOpts().OpenMPIsTargetDevice &&
23221 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
23222 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
23223 }
23224 if (Alignment) {
23225 bool AlignmentDependent = Alignment->isTypeDependent() ||
23226 Alignment->isValueDependent() ||
23227 Alignment->isInstantiationDependent() ||
23229 if (!AlignmentDependent) {
23230 ExprResult AlignResult =
23231 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_allocate);
23232 Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr;
23233 }
23234 }
23235 // Analyze and build list of variables.
23237 for (Expr *RefExpr : VarList) {
23238 assert(RefExpr && "NULL expr in OpenMP private clause.");
23239 SourceLocation ELoc;
23240 SourceRange ERange;
23241 Expr *SimpleRefExpr = RefExpr;
23242 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23243 if (Res.second) {
23244 // It will be analyzed later.
23245 Vars.push_back(RefExpr);
23246 }
23247 ValueDecl *D = Res.first;
23248 if (!D)
23249 continue;
23250
23251 auto *VD = dyn_cast<VarDecl>(D);
23252 DeclRefExpr *Ref = nullptr;
23253 if (!VD && !SemaRef.CurContext->isDependentContext())
23254 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
23255 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
23256 ? RefExpr->IgnoreParens()
23257 : Ref);
23258 }
23259
23260 if (Vars.empty())
23261 return nullptr;
23262
23263 if (Allocator)
23264 DSAStack->addInnerAllocatorExpr(Allocator);
23265
23267 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
23268 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
23269 SecondAllocateModifierLoc, EndLoc, Vars);
23270}
23271
23273 SourceLocation StartLoc,
23274 SourceLocation LParenLoc,
23275 SourceLocation EndLoc) {
23277 for (Expr *RefExpr : VarList) {
23278 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23279 SourceLocation ELoc;
23280 SourceRange ERange;
23281 Expr *SimpleRefExpr = RefExpr;
23282 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23283 if (Res.second)
23284 // It will be analyzed later.
23285 Vars.push_back(RefExpr);
23286 ValueDecl *D = Res.first;
23287 if (!D)
23288 continue;
23289
23290 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
23291 // A list-item cannot appear in more than one nontemporal clause.
23292 if (const Expr *PrevRef =
23293 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
23294 Diag(ELoc, diag::err_omp_used_in_clause_twice)
23295 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
23296 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23297 << getOpenMPClauseName(OMPC_nontemporal);
23298 continue;
23299 }
23300
23301 Vars.push_back(RefExpr);
23302 }
23303
23304 if (Vars.empty())
23305 return nullptr;
23306
23307 return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc,
23308 EndLoc, Vars);
23309}
23310
23312 Stmt *AStmt,
23313 SourceLocation StartLoc,
23314 SourceLocation EndLoc) {
23315 if (!AStmt)
23316 return StmtError();
23317
23319
23320 return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
23321 AStmt);
23322}
23323
23325 SourceLocation StartLoc,
23326 SourceLocation LParenLoc,
23327 SourceLocation EndLoc) {
23329 for (Expr *RefExpr : VarList) {
23330 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23331 SourceLocation ELoc;
23332 SourceRange ERange;
23333 Expr *SimpleRefExpr = RefExpr;
23334 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23335 /*AllowArraySection=*/true);
23336 if (Res.second)
23337 // It will be analyzed later.
23338 Vars.push_back(RefExpr);
23339 ValueDecl *D = Res.first;
23340 if (!D)
23341 continue;
23342
23343 const DSAStackTy::DSAVarData DVar =
23344 DSAStack->getTopDSA(D, /*FromParent=*/true);
23345 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23346 // A list item that appears in the inclusive or exclusive clause must appear
23347 // in a reduction clause with the inscan modifier on the enclosing
23348 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23349 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
23350 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23351 << RefExpr->getSourceRange();
23352
23353 if (DSAStack->getParentDirective() != OMPD_unknown)
23354 DSAStack->markDeclAsUsedInScanDirective(D);
23355 Vars.push_back(RefExpr);
23356 }
23357
23358 if (Vars.empty())
23359 return nullptr;
23360
23361 return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
23362 EndLoc, Vars);
23363}
23364
23366 SourceLocation StartLoc,
23367 SourceLocation LParenLoc,
23368 SourceLocation EndLoc) {
23370 for (Expr *RefExpr : VarList) {
23371 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23372 SourceLocation ELoc;
23373 SourceRange ERange;
23374 Expr *SimpleRefExpr = RefExpr;
23375 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23376 /*AllowArraySection=*/true);
23377 if (Res.second)
23378 // It will be analyzed later.
23379 Vars.push_back(RefExpr);
23380 ValueDecl *D = Res.first;
23381 if (!D)
23382 continue;
23383
23384 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
23385 DSAStackTy::DSAVarData DVar;
23386 if (ParentDirective != OMPD_unknown)
23387 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
23388 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23389 // A list item that appears in the inclusive or exclusive clause must appear
23390 // in a reduction clause with the inscan modifier on the enclosing
23391 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23392 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
23393 DVar.Modifier != OMPC_REDUCTION_inscan) {
23394 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23395 << RefExpr->getSourceRange();
23396 } else {
23397 DSAStack->markDeclAsUsedInScanDirective(D);
23398 }
23399 Vars.push_back(RefExpr);
23400 }
23401
23402 if (Vars.empty())
23403 return nullptr;
23404
23405 return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
23406 EndLoc, Vars);
23407}
23408
23409/// Tries to find omp_alloctrait_t type.
23410static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
23411 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
23412 if (!OMPAlloctraitT.isNull())
23413 return true;
23414 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
23415 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
23416 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23417 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
23418 return false;
23419 }
23420 Stack->setOMPAlloctraitT(PT.get());
23421 return true;
23422}
23423
23425 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
23427 ASTContext &Context = getASTContext();
23428 // OpenMP [2.12.5, target Construct]
23429 // allocator is an identifier of omp_allocator_handle_t type.
23430 if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack))
23431 return nullptr;
23432 // OpenMP [2.12.5, target Construct]
23433 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
23434 if (llvm::any_of(
23435 Data,
23436 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
23437 !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack))
23438 return nullptr;
23439 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
23440 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
23441 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
23442 StringRef Allocator =
23443 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
23444 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
23445 PredefinedAllocators.insert(SemaRef.LookupSingleName(
23446 SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
23447 }
23448
23450 for (const UsesAllocatorsData &D : Data) {
23451 Expr *AllocatorExpr = nullptr;
23452 // Check allocator expression.
23453 if (D.Allocator->isTypeDependent()) {
23454 AllocatorExpr = D.Allocator;
23455 } else {
23456 // Traits were specified - need to assign new allocator to the specified
23457 // allocator, so it must be an lvalue.
23458 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
23459 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
23460 bool IsPredefinedAllocator = false;
23461 if (DRE) {
23462 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
23463 getAllocatorKind(SemaRef, DSAStack, AllocatorExpr);
23464 IsPredefinedAllocator =
23465 AllocatorTy !=
23466 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
23467 }
23468 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
23469 QualType AllocatorExprType = AllocatorExpr->getType();
23470 bool IsTypeCompatible = IsPredefinedAllocator;
23471 IsTypeCompatible = IsTypeCompatible ||
23472 Context.hasSameUnqualifiedType(AllocatorExprType,
23473 OMPAllocatorHandleT);
23474 IsTypeCompatible =
23475 IsTypeCompatible ||
23476 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
23477 bool IsNonConstantLValue =
23478 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
23479 if (!DRE || !IsTypeCompatible ||
23480 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
23481 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
23482 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
23483 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
23484 continue;
23485 }
23486 // OpenMP [2.12.5, target Construct]
23487 // Predefined allocators appearing in a uses_allocators clause cannot have
23488 // traits specified.
23489 if (IsPredefinedAllocator && D.AllocatorTraits) {
23490 Diag(D.AllocatorTraits->getExprLoc(),
23491 diag::err_omp_predefined_allocator_with_traits)
23492 << D.AllocatorTraits->getSourceRange();
23493 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
23494 << cast<NamedDecl>(DRE->getDecl())->getName()
23495 << D.Allocator->getSourceRange();
23496 continue;
23497 }
23498 // OpenMP [2.12.5, target Construct]
23499 // Non-predefined allocators appearing in a uses_allocators clause must
23500 // have traits specified.
23501 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
23502 Diag(D.Allocator->getExprLoc(),
23503 diag::err_omp_nonpredefined_allocator_without_traits);
23504 continue;
23505 }
23506 // No allocator traits - just convert it to rvalue.
23507 if (!D.AllocatorTraits)
23508 AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
23509 DSAStack->addUsesAllocatorsDecl(
23510 DRE->getDecl(),
23511 IsPredefinedAllocator
23512 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
23513 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
23514 }
23515 Expr *AllocatorTraitsExpr = nullptr;
23516 if (D.AllocatorTraits) {
23517 if (D.AllocatorTraits->isTypeDependent()) {
23518 AllocatorTraitsExpr = D.AllocatorTraits;
23519 } else {
23520 // OpenMP [2.12.5, target Construct]
23521 // Arrays that contain allocator traits that appear in a uses_allocators
23522 // clause must be constant arrays, have constant values and be defined
23523 // in the same scope as the construct in which the clause appears.
23524 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
23525 // Check that traits expr is a constant array.
23526 QualType TraitTy;
23527 if (const ArrayType *Ty =
23528 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
23529 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
23530 TraitTy = ConstArrayTy->getElementType();
23531 if (TraitTy.isNull() ||
23532 !(Context.hasSameUnqualifiedType(TraitTy,
23533 DSAStack->getOMPAlloctraitT()) ||
23534 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
23535 /*CompareUnqualified=*/true))) {
23536 Diag(D.AllocatorTraits->getExprLoc(),
23537 diag::err_omp_expected_array_alloctraits)
23538 << AllocatorTraitsExpr->getType();
23539 continue;
23540 }
23541 // Do not map by default allocator traits if it is a standalone
23542 // variable.
23543 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
23544 DSAStack->addUsesAllocatorsDecl(
23545 DRE->getDecl(),
23546 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
23547 }
23548 }
23549 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
23550 NewD.Allocator = AllocatorExpr;
23551 NewD.AllocatorTraits = AllocatorTraitsExpr;
23552 NewD.LParenLoc = D.LParenLoc;
23553 NewD.RParenLoc = D.RParenLoc;
23554 }
23555 return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc,
23556 EndLoc, NewData);
23557}
23558
23560 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
23561 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
23563 for (Expr *RefExpr : Locators) {
23564 assert(RefExpr && "NULL expr in OpenMP shared clause.");
23565 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
23566 // It will be analyzed later.
23567 Vars.push_back(RefExpr);
23568 continue;
23569 }
23570
23571 SourceLocation ELoc = RefExpr->getExprLoc();
23572 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
23573
23574 if (!SimpleExpr->isLValue()) {
23575 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23576 << 1 << 0 << RefExpr->getSourceRange();
23577 continue;
23578 }
23579
23580 ExprResult Res;
23581 {
23583 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
23584 }
23585 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
23586 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
23587 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23588 << 1 << 0 << RefExpr->getSourceRange();
23589 continue;
23590 }
23591 Vars.push_back(SimpleExpr);
23592 }
23593
23594 return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc,
23595 ColonLoc, EndLoc, Modifier, Vars);
23596}
23597
23599 SourceLocation KindLoc,
23600 SourceLocation StartLoc,
23601 SourceLocation LParenLoc,
23602 SourceLocation EndLoc) {
23603 if (Kind == OMPC_BIND_unknown) {
23604 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23605 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
23606 /*Last=*/unsigned(OMPC_BIND_unknown))
23607 << getOpenMPClauseName(OMPC_bind);
23608 return nullptr;
23609 }
23610
23611 return OMPBindClause::Create(getASTContext(), Kind, KindLoc, StartLoc,
23612 LParenLoc, EndLoc);
23613}
23614
23616 SourceLocation StartLoc,
23617 SourceLocation LParenLoc,
23618 SourceLocation EndLoc) {
23619 Expr *ValExpr = Size;
23620 Stmt *HelperValStmt = nullptr;
23621
23622 // OpenMP [2.5, Restrictions]
23623 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
23624 // value.
23625 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem,
23626 /*StrictlyPositive=*/false))
23627 return nullptr;
23628
23629 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23631 DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP);
23632 if (CaptureRegion != OMPD_unknown &&
23634 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23635 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23636 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23637 HelperValStmt = buildPreInits(getASTContext(), Captures);
23638 }
23639
23641 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23642}
23643
23646 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
23647 SourceLocation LParenLoc, SourceLocation EndLoc) {
23648
23649 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
23650 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
23651 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
23652 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
23653 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
23654 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross);
23655 return nullptr;
23656 }
23657
23660 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
23661 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
23662 SemaRef,
23663 DepType == OMPC_DOACROSS_source ||
23664 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
23665 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
23666 VarList, DSAStack, EndLoc);
23667 Vars = VarOffset.Vars;
23668 OpsOffs = VarOffset.OpsOffs;
23669 TotalDepCount = VarOffset.TotalDepCount;
23670 auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc,
23671 EndLoc, DepType, DepLoc, ColonLoc, Vars,
23672 TotalDepCount.getZExtValue());
23673 if (DSAStack->isParentOrderedRegion())
23674 DSAStack->addDoacrossDependClause(C, OpsOffs);
23675 return C;
23676}
23677
23679 SourceLocation StartLoc,
23680 SourceLocation LParenLoc,
23681 SourceLocation EndLoc) {
23682 return new (getASTContext())
23683 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
23684}
23685
23687 SourceLocation EndLoc) {
23688 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
23689}
23690
23692 SourceLocation LParenLoc,
23693 SourceLocation EndLoc) {
23694 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
23695}
23696
23700 switch (CK) {
23701 case OMPC_absent:
23702 return OMPAbsentClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
23703 case OMPC_contains:
23704 return OMPContainsClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
23705 default:
23706 llvm_unreachable("Unexpected OpenMP clause");
23707 }
23708}
23709
23712 SourceLocation RLoc) {
23713 switch (CK) {
23714 case OMPC_no_openmp:
23715 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
23716 case OMPC_no_openmp_routines:
23717 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
23718 case OMPC_no_parallelism:
23719 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
23720 default:
23721 llvm_unreachable("Unexpected OpenMP clause");
23722 }
23723}
23724
23726 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
23727 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
23728 Expr *Stride, SourceLocation RBLoc) {
23729 ASTContext &Context = getASTContext();
23730 if (Base->hasPlaceholderType() &&
23731 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23733 if (Result.isInvalid())
23734 return ExprError();
23735 Base = Result.get();
23736 }
23737 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
23739 if (Result.isInvalid())
23740 return ExprError();
23742 if (Result.isInvalid())
23743 return ExprError();
23744 LowerBound = Result.get();
23745 }
23746 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
23748 if (Result.isInvalid())
23749 return ExprError();
23751 if (Result.isInvalid())
23752 return ExprError();
23753 Length = Result.get();
23754 }
23755 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
23757 if (Result.isInvalid())
23758 return ExprError();
23760 if (Result.isInvalid())
23761 return ExprError();
23762 Stride = Result.get();
23763 }
23764
23765 // Build an unanalyzed expression if either operand is type-dependent.
23766 if (Base->isTypeDependent() ||
23767 (LowerBound &&
23768 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
23769 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
23770 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
23771 return new (Context) ArraySectionExpr(
23772 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
23773 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23774 }
23775
23776 // Perform default conversions.
23778 QualType ResultTy;
23779 if (OriginalTy->isAnyPointerType()) {
23780 ResultTy = OriginalTy->getPointeeType();
23781 } else if (OriginalTy->isArrayType()) {
23782 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
23783 } else {
23784 return ExprError(
23785 Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
23786 << Base->getSourceRange());
23787 }
23788 // C99 6.5.2.1p1
23789 if (LowerBound) {
23790 auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
23791 LowerBound);
23792 if (Res.isInvalid())
23793 return ExprError(Diag(LowerBound->getExprLoc(),
23794 diag::err_omp_typecheck_section_not_integer)
23795 << 0 << LowerBound->getSourceRange());
23796 LowerBound = Res.get();
23797
23798 if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23799 LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23800 Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
23801 << 0 << LowerBound->getSourceRange();
23802 }
23803 if (Length) {
23804 auto Res =
23805 PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
23806 if (Res.isInvalid())
23807 return ExprError(Diag(Length->getExprLoc(),
23808 diag::err_omp_typecheck_section_not_integer)
23809 << 1 << Length->getSourceRange());
23810 Length = Res.get();
23811
23812 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23813 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23814 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
23815 << 1 << Length->getSourceRange();
23816 }
23817 if (Stride) {
23818 ExprResult Res =
23820 if (Res.isInvalid())
23821 return ExprError(Diag(Stride->getExprLoc(),
23822 diag::err_omp_typecheck_section_not_integer)
23823 << 1 << Stride->getSourceRange());
23824 Stride = Res.get();
23825
23826 if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23827 Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23828 Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
23829 << 1 << Stride->getSourceRange();
23830 }
23831
23832 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
23833 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
23834 // type. Note that functions are not objects, and that (in C99 parlance)
23835 // incomplete types are not object types.
23836 if (ResultTy->isFunctionType()) {
23837 Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
23838 << ResultTy << Base->getSourceRange();
23839 return ExprError();
23840 }
23841
23842 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
23843 diag::err_omp_section_incomplete_type, Base))
23844 return ExprError();
23845
23846 if (LowerBound && !OriginalTy->isAnyPointerType()) {
23848 if (LowerBound->EvaluateAsInt(Result, Context)) {
23849 // OpenMP 5.0, [2.1.5 Array Sections]
23850 // The array section must be a subset of the original array.
23851 llvm::APSInt LowerBoundValue = Result.Val.getInt();
23852 if (LowerBoundValue.isNegative()) {
23853 Diag(LowerBound->getExprLoc(),
23854 diag::err_omp_section_not_subset_of_array)
23855 << LowerBound->getSourceRange();
23856 return ExprError();
23857 }
23858 }
23859 }
23860
23861 if (Length) {
23863 if (Length->EvaluateAsInt(Result, Context)) {
23864 // OpenMP 5.0, [2.1.5 Array Sections]
23865 // The length must evaluate to non-negative integers.
23866 llvm::APSInt LengthValue = Result.Val.getInt();
23867 if (LengthValue.isNegative()) {
23868 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
23869 << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
23870 << Length->getSourceRange();
23871 return ExprError();
23872 }
23873 }
23874 } else if (ColonLocFirst.isValid() &&
23875 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
23876 !OriginalTy->isVariableArrayType()))) {
23877 // OpenMP 5.0, [2.1.5 Array Sections]
23878 // When the size of the array dimension is not known, the length must be
23879 // specified explicitly.
23880 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
23881 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
23882 return ExprError();
23883 }
23884
23885 if (Stride) {
23887 if (Stride->EvaluateAsInt(Result, Context)) {
23888 // OpenMP 5.0, [2.1.5 Array Sections]
23889 // The stride must evaluate to a positive integer.
23890 llvm::APSInt StrideValue = Result.Val.getInt();
23891 if (!StrideValue.isStrictlyPositive()) {
23892 Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
23893 << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
23894 << Stride->getSourceRange();
23895 return ExprError();
23896 }
23897 }
23898 }
23899
23900 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23902 if (Result.isInvalid())
23903 return ExprError();
23904 Base = Result.get();
23905 }
23906 return new (Context) ArraySectionExpr(
23907 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
23908 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23909}
23910
23912 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
23913 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
23914 ASTContext &Context = getASTContext();
23915 if (Base->hasPlaceholderType()) {
23917 if (Result.isInvalid())
23918 return ExprError();
23920 if (Result.isInvalid())
23921 return ExprError();
23922 Base = Result.get();
23923 }
23924 QualType BaseTy = Base->getType();
23925 // Delay analysis of the types/expressions if instantiation/specialization is
23926 // required.
23927 if (!BaseTy->isPointerType() && Base->isTypeDependent())
23928 return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
23929 LParenLoc, RParenLoc, Dims, Brackets);
23930 if (!BaseTy->isPointerType() ||
23931 (!Base->isTypeDependent() &&
23932 BaseTy->getPointeeType()->isIncompleteType()))
23933 return ExprError(Diag(Base->getExprLoc(),
23934 diag::err_omp_non_pointer_type_array_shaping_base)
23935 << Base->getSourceRange());
23936
23937 SmallVector<Expr *, 4> NewDims;
23938 bool ErrorFound = false;
23939 for (Expr *Dim : Dims) {
23940 if (Dim->hasPlaceholderType()) {
23942 if (Result.isInvalid()) {
23943 ErrorFound = true;
23944 continue;
23945 }
23947 if (Result.isInvalid()) {
23948 ErrorFound = true;
23949 continue;
23950 }
23951 Dim = Result.get();
23952 }
23953 if (!Dim->isTypeDependent()) {
23956 if (Result.isInvalid()) {
23957 ErrorFound = true;
23958 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
23959 << Dim->getSourceRange();
23960 continue;
23961 }
23962 Dim = Result.get();
23963 Expr::EvalResult EvResult;
23964 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
23965 // OpenMP 5.0, [2.1.4 Array Shaping]
23966 // Each si is an integral type expression that must evaluate to a
23967 // positive integer.
23968 llvm::APSInt Value = EvResult.Val.getInt();
23969 if (!Value.isStrictlyPositive()) {
23970 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
23971 << toString(Value, /*Radix=*/10, /*Signed=*/true)
23972 << Dim->getSourceRange();
23973 ErrorFound = true;
23974 continue;
23975 }
23976 }
23977 }
23978 NewDims.push_back(Dim);
23979 }
23980 if (ErrorFound)
23981 return ExprError();
23982 return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
23983 LParenLoc, RParenLoc, NewDims, Brackets);
23984}
23985
23987 SourceLocation IteratorKwLoc,
23988 SourceLocation LLoc,
23989 SourceLocation RLoc,
23991 ASTContext &Context = getASTContext();
23993 bool IsCorrect = true;
23994 for (const OMPIteratorData &D : Data) {
23995 TypeSourceInfo *TInfo = nullptr;
23996 SourceLocation StartLoc;
23997 QualType DeclTy;
23998 if (!D.Type.getAsOpaquePtr()) {
23999 // OpenMP 5.0, 2.1.6 Iterators
24000 // In an iterator-specifier, if the iterator-type is not specified then
24001 // the type of that iterator is of int type.
24002 DeclTy = Context.IntTy;
24003 StartLoc = D.DeclIdentLoc;
24004 } else {
24005 DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo);
24006 StartLoc = TInfo->getTypeLoc().getBeginLoc();
24007 }
24008
24009 bool IsDeclTyDependent = DeclTy->isDependentType() ||
24010 DeclTy->containsUnexpandedParameterPack() ||
24011 DeclTy->isInstantiationDependentType();
24012 if (!IsDeclTyDependent) {
24013 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
24014 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
24015 // The iterator-type must be an integral or pointer type.
24016 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
24017 << DeclTy;
24018 IsCorrect = false;
24019 continue;
24020 }
24021 if (DeclTy.isConstant(Context)) {
24022 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
24023 // The iterator-type must not be const qualified.
24024 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
24025 << DeclTy;
24026 IsCorrect = false;
24027 continue;
24028 }
24029 }
24030
24031 // Iterator declaration.
24032 assert(D.DeclIdent && "Identifier expected.");
24033 // Always try to create iterator declarator to avoid extra error messages
24034 // about unknown declarations use.
24035 auto *VD =
24036 VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc,
24037 D.DeclIdent, DeclTy, TInfo, SC_None);
24038 VD->setImplicit();
24039 if (S) {
24040 // Check for conflicting previous declaration.
24041 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
24043 RedeclarationKind::ForVisibleRedeclaration);
24044 Previous.suppressDiagnostics();
24046
24048 /*ConsiderLinkage=*/false,
24049 /*AllowInlineNamespace=*/false);
24050 if (!Previous.empty()) {
24051 NamedDecl *Old = Previous.getRepresentativeDecl();
24052 Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
24053 Diag(Old->getLocation(), diag::note_previous_definition);
24054 } else {
24056 }
24057 } else {
24059 }
24060
24061 /// Act on the iterator variable declaration.
24063
24064 Expr *Begin = D.Range.Begin;
24065 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
24068 Begin = BeginRes.get();
24069 }
24070 Expr *End = D.Range.End;
24071 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
24073 End, DeclTy, AssignmentAction::Converting);
24074 End = EndRes.get();
24075 }
24076 Expr *Step = D.Range.Step;
24077 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
24078 if (!Step->getType()->isIntegralType(Context)) {
24079 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
24080 << Step << Step->getSourceRange();
24081 IsCorrect = false;
24082 continue;
24083 }
24084 std::optional<llvm::APSInt> Result =
24085 Step->getIntegerConstantExpr(Context);
24086 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
24087 // If the step expression of a range-specification equals zero, the
24088 // behavior is unspecified.
24089 if (Result && Result->isZero()) {
24090 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
24091 << Step << Step->getSourceRange();
24092 IsCorrect = false;
24093 continue;
24094 }
24095 }
24096 if (!Begin || !End || !IsCorrect) {
24097 IsCorrect = false;
24098 continue;
24099 }
24100 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
24101 IDElem.IteratorDecl = VD;
24102 IDElem.AssignmentLoc = D.AssignLoc;
24103 IDElem.Range.Begin = Begin;
24104 IDElem.Range.End = End;
24105 IDElem.Range.Step = Step;
24106 IDElem.ColonLoc = D.ColonLoc;
24107 IDElem.SecondColonLoc = D.SecColonLoc;
24108 }
24109 if (!IsCorrect) {
24110 // Invalidate all created iterator declarations if error is found.
24111 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
24112 if (Decl *ID = D.IteratorDecl)
24113 ID->setInvalidDecl();
24114 }
24115 return ExprError();
24116 }
24119 // Build number of ityeration for each iteration range.
24120 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
24121 // ((Begini-Stepi-1-Endi) / -Stepi);
24123 // (Endi - Begini)
24124 ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub,
24125 D.Range.End, D.Range.Begin);
24126 if (!Res.isUsable()) {
24127 IsCorrect = false;
24128 continue;
24129 }
24130 ExprResult St, St1;
24131 if (D.Range.Step) {
24132 St = D.Range.Step;
24133 // (Endi - Begini) + Stepi
24134 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(),
24135 St.get());
24136 if (!Res.isUsable()) {
24137 IsCorrect = false;
24138 continue;
24139 }
24140 // (Endi - Begini) + Stepi - 1
24142 D.AssignmentLoc, BO_Sub, Res.get(),
24143 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
24144 if (!Res.isUsable()) {
24145 IsCorrect = false;
24146 continue;
24147 }
24148 // ((Endi - Begini) + Stepi - 1) / Stepi
24149 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(),
24150 St.get());
24151 if (!Res.isUsable()) {
24152 IsCorrect = false;
24153 continue;
24154 }
24155 St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
24156 D.Range.Step);
24157 // (Begini - Endi)
24159 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
24160 if (!Res1.isUsable()) {
24161 IsCorrect = false;
24162 continue;
24163 }
24164 // (Begini - Endi) - Stepi
24165 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(),
24166 St1.get());
24167 if (!Res1.isUsable()) {
24168 IsCorrect = false;
24169 continue;
24170 }
24171 // (Begini - Endi) - Stepi - 1
24173 D.AssignmentLoc, BO_Sub, Res1.get(),
24174 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
24175 if (!Res1.isUsable()) {
24176 IsCorrect = false;
24177 continue;
24178 }
24179 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
24180 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(),
24181 St1.get());
24182 if (!Res1.isUsable()) {
24183 IsCorrect = false;
24184 continue;
24185 }
24186 // Stepi > 0.
24188 D.AssignmentLoc, BO_GT, D.Range.Step,
24189 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
24190 if (!CmpRes.isUsable()) {
24191 IsCorrect = false;
24192 continue;
24193 }
24194 Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
24195 CmpRes.get(), Res.get(), Res1.get());
24196 if (!Res.isUsable()) {
24197 IsCorrect = false;
24198 continue;
24199 }
24200 }
24201 Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false);
24202 if (!Res.isUsable()) {
24203 IsCorrect = false;
24204 continue;
24205 }
24206
24207 // Build counter update.
24208 // Build counter.
24209 auto *CounterVD = VarDecl::Create(Context, SemaRef.CurContext,
24210 D.IteratorDecl->getBeginLoc(),
24211 D.IteratorDecl->getBeginLoc(), nullptr,
24212 Res.get()->getType(), nullptr, SC_None);
24213 CounterVD->setImplicit();
24214 ExprResult RefRes =
24215 SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue,
24216 D.IteratorDecl->getBeginLoc());
24217 // Build counter update.
24218 // I = Begini + counter * Stepi;
24219 ExprResult UpdateRes;
24220 if (D.Range.Step) {
24221 UpdateRes = SemaRef.CreateBuiltinBinOp(
24222 D.AssignmentLoc, BO_Mul,
24223 SemaRef.DefaultLvalueConversion(RefRes.get()).get(), St.get());
24224 } else {
24225 UpdateRes = SemaRef.DefaultLvalueConversion(RefRes.get());
24226 }
24227 if (!UpdateRes.isUsable()) {
24228 IsCorrect = false;
24229 continue;
24230 }
24231 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
24232 D.Range.Begin, UpdateRes.get());
24233 if (!UpdateRes.isUsable()) {
24234 IsCorrect = false;
24235 continue;
24236 }
24237 ExprResult VDRes =
24238 SemaRef.BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl),
24239 cast<VarDecl>(D.IteratorDecl)->getType(),
24240 VK_LValue, D.IteratorDecl->getBeginLoc());
24241 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
24242 VDRes.get(), UpdateRes.get());
24243 if (!UpdateRes.isUsable()) {
24244 IsCorrect = false;
24245 continue;
24246 }
24247 UpdateRes =
24248 SemaRef.ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true);
24249 if (!UpdateRes.isUsable()) {
24250 IsCorrect = false;
24251 continue;
24252 }
24253 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
24254 D.AssignmentLoc, UO_PreInc, RefRes.get());
24255 if (!CounterUpdateRes.isUsable()) {
24256 IsCorrect = false;
24257 continue;
24258 }
24259 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(CounterUpdateRes.get(),
24260 /*DiscardedValue=*/true);
24261 if (!CounterUpdateRes.isUsable()) {
24262 IsCorrect = false;
24263 continue;
24264 }
24265 OMPIteratorHelperData &HD = Helpers.emplace_back();
24266 HD.CounterVD = CounterVD;
24267 HD.Upper = Res.get();
24268 HD.Update = UpdateRes.get();
24269 HD.CounterUpdate = CounterUpdateRes.get();
24270 }
24271 } else {
24272 Helpers.assign(ID.size(), {});
24273 }
24274 if (!IsCorrect) {
24275 // Invalidate all created iterator declarations if error is found.
24276 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
24277 if (Decl *ID = D.IteratorDecl)
24278 ID->setInvalidDecl();
24279 }
24280 return ExprError();
24281 }
24282 return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc,
24283 LLoc, RLoc, ID, Helpers);
24284}
24285
24286/// Check if \p AssumptionStr is a known assumption and warn if not.
24288 StringRef AssumptionStr) {
24289 if (llvm::KnownAssumptionStrings.count(AssumptionStr))
24290 return;
24291
24292 unsigned BestEditDistance = 3;
24293 StringRef Suggestion;
24294 for (const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) {
24295 unsigned EditDistance =
24296 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
24297 if (EditDistance < BestEditDistance) {
24298 Suggestion = KnownAssumptionIt.getKey();
24299 BestEditDistance = EditDistance;
24300 }
24301 }
24302
24303 if (!Suggestion.empty())
24304 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
24305 << AssumptionStr << Suggestion;
24306 else
24307 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
24308 << AssumptionStr;
24309}
24310
24312 // Handle the case where the attribute has a text message.
24313 StringRef Str;
24314 SourceLocation AttrStrLoc;
24315 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
24316 return;
24317
24318 checkOMPAssumeAttr(SemaRef, AttrStrLoc, Str);
24319
24320 D->addAttr(::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
24321}
24322
24324 : SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3453
NodeId Parent
Definition: ASTDiff.cpp:191
DynTypedNode Node
StringRef P
const Decl * D
enum clang::sema::@1724::IndirectLocalPathEntry::EntryKind Kind
Expr * E
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
This file defines OpenMP nodes for declarative directives.
int Priority
Definition: Format.cpp:3055
llvm::DenseSet< const void * > Visited
Definition: HTMLLogger.cpp:145
unsigned Iter
Definition: HTMLLogger.cpp:153
static const Decl * getCanonicalDecl(const Decl *D)
#define X(type, name)
Definition: Value.h:144
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.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
uint32_t Id
Definition: SemaARM.cpp:1134
CastType
Definition: SemaCast.cpp:48
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.
SourceRange Range
Definition: SemaObjC.cpp:758
SourceLocation Loc
Definition: SemaObjC.cpp:759
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 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 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 std::pair< ValueDecl *, bool > getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, SourceRange &ERange, bool AllowArraySection=false, StringRef DiagType="")
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 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 VarDecl * buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type, StringRef Name, const AttrVec *Attrs=nullptr, DeclRefExpr *OrigRef=nullptr)
Build a variable declaration for OpenMP loop iteration variable.
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)
Definition: SourceCode.cpp:152
const char * Data
This file defines OpenMP AST classes for executable directives and clauses.
static QualType getPointeeType(const MemRegion *R)
SourceLocation Begin
StateNode * Previous
#define bool
Definition: amdgpuintrin.h:20
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.
APSInt & getInt()
Definition: APValue.h:465
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
const llvm::fltSemantics & getFloatTypeSemantics(QualType T) const
Return the APFloat 'semantics' for the specified scalar floating point type.
QualType getMemberPointerType(QualType T, const Type *Cls) const
Return the uniqued reference to the type for a member pointer to the specified type in the specified ...
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, bool Unqualified=false, bool AllowCXX=false, bool IsConditionalOperator=false)
DeclarationNameTable DeclarationNames
Definition: ASTContext.h:684
QualType getUnsignedPointerDiffType() const
Return the unique unsigned counterpart of "ptrdiff_t" integer type.
QualType getVariableArrayType(QualType EltTy, Expr *NumElts, ArraySizeModifier ASM, unsigned IndexTypeQuals, SourceRange Brackets) const
Return a non-unique reference to the type for a variable array of the specified element type.
ASTMutationListener * getASTMutationListener() const
Retrieve a pointer to the AST mutation listener associated with this AST context, if any.
Definition: ASTContext.h:1289
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2716
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:2732
bool DeclMustBeEmitted(const Decl *D)
Determines if the decl can be CodeGen'ed or deserialized from PCH lazily, only when used; this is onl...
CanQualType OMPArrayShapingTy
Definition: ASTContext.h:1201
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType VoidPtrTy
Definition: ASTContext.h:1187
void Deallocate(void *Ptr) const
Definition: ASTContext.h:760
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
CanQualType DependentTy
Definition: ASTContext.h:1188
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
Definition: ASTContext.h:1703
CanQualType OMPIteratorTy
Definition: ASTContext.h:1201
IdentifierTable & Idents
Definition: ASTContext.h:680
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
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 ArraySectionTy
Definition: ASTContext.h:1200
CanQualType BoolTy
Definition: ASTContext.h:1161
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,...
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
CanQualType BoundMemberTy
Definition: ASTContext.h:1188
CanQualType IntTy
Definition: ASTContext.h:1169
CharUnits getAlignOfGlobalVarInChars(QualType T, const VarDecl *VD) const
Return the alignment in characters that should be given to a global variable with type T.
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Definition: ASTContext.h:2763
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2482
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType VoidTy
Definition: ASTContext.h:1160
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
Definition: ASTContext.h:1681
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:799
bool typesAreCompatible(QualType T1, QualType T2, bool CompareUnqualified=false)
Compatibility predicates used to check assignment expressions.
An abstract interface that should be implemented by listeners that want to be notified when an AST en...
bool isUnset() const
Definition: Ownership.h:167
PtrTy get() const
Definition: Ownership.h:170
bool isInvalid() const
Definition: Ownership.h:166
bool isUsable() const
Definition: Ownership.h:168
This class represents BOTH the OpenMP Array Section and OpenACC 'subarray', with a boolean differenti...
Definition: Expr.h:6986
Expr * getBase()
Get base of the array section.
Definition: Expr.h:7052
Expr * getLength()
Get length of array section.
Definition: Expr.h:7062
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition: Expr.cpp:5184
Expr * getLowerBound()
Get lower bound of array section.
Definition: Expr.h:7056
SourceLocation getColonLocFirst() const
Definition: Expr.h:7083
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition: Expr.h:2718
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition: Type.h:3577
QualType getElementType() const
Definition: Type.h:3589
Attr - This represents one attribute.
Definition: Attr.h:43
Represents an attribute applied to a statement.
Definition: Stmt.h:2107
static AttributedStmt * Create(const ASTContext &C, SourceLocation Loc, ArrayRef< const Attr * > Attrs, Stmt *SubStmt)
Definition: Stmt.cpp:432
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3909
Expr * getLHS() const
Definition: Expr.h:3959
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition: Expr.cpp:2196
static Opcode getOpForCompoundAssignment(Opcode Opc)
Definition: Expr.h:4056
bool isRelationalOp() const
Definition: Expr.h:4004
SourceLocation getOperatorLoc() const
Definition: Expr.h:3951
SourceLocation getExprLoc() const
Definition: Expr.h:3950
static Opcode reverseComparisonOp(Opcode Opc)
Definition: Expr.h:4028
Expr * getRHS() const
Definition: Expr.h:3961
Opcode getOpcode() const
Definition: Expr.h:3954
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition: Expr.cpp:2158
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2553
Represents a C++ conversion function within a class.
Definition: DeclCXX.h:2885
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
Definition: StmtCXX.h:135
A call to an overloaded operator written using operator syntax.
Definition: ExprCXX.h:81
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:1245
bool hasDefinition() const
Definition: DeclCXX.h:572
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:74
bool isValid() const
A scope specifier is present, and it refers to a real scope.
Definition: DeclSpec.h:215
SourceLocation getBeginLoc() const
Definition: DeclSpec.h:84
bool isSet() const
Deprecated.
Definition: DeclSpec.h:228
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const
Retrieve a nested-name-specifier with location information, copied into the given AST context.
Definition: DeclSpec.cpp:149
bool isInvalid() const
An error occurred during parsing of the scope specifier.
Definition: DeclSpec.h:213
Represents the this expression in C++.
Definition: ExprCXX.h:1152
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2874
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:1499
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.cpp:1645
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition: Expr.h:3047
QualType withConst() const
Retrieves a version of this type with const applied.
A wrapper class around a pointer that always points to its canonical declaration.
Definition: Redeclarable.h:348
Represents the body of a CapturedStmt, and serves as its DeclContext.
Definition: Decl.h:4695
unsigned getNumParams() const
Definition: Decl.h:4737
void setNothrow(bool Nothrow=true)
Definition: Decl.cpp:5471
ImplicitParamDecl * getParam(unsigned i) const
Definition: Decl.h:4739
Describes the capture of either a variable, or 'this', or variable-length array type.
Definition: Stmt.h:3797
This captures a statement into a function.
Definition: Stmt.h:3784
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
Definition: Stmt.cpp:1414
SourceRange getSourceRange() const LLVM_READONLY
Definition: Stmt.h:3987
Stmt * getCapturedStmt()
Retrieve the statement being captured.
Definition: Stmt.h:3888
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
Definition: Stmt.cpp:1438
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.h:3979
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition: Expr.h:3547
Declaration of a class template.
Complex values, per C99 6.2.5p11.
Definition: Type.h:3145
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:1628
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
Definition: Stmt.cpp:390
ConditionalOperator - The ?: ternary operator.
Definition: Expr.h:4262
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
Definition: StmtVisitor.h:195
Base class for callback objects used by Sema::CorrectTypo to check the validity of a potential typo c...
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
The results of name lookup within a DeclContext.
Definition: DeclBase.h:1368
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1435
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:2100
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
Definition: DeclBase.h:2229
bool isFileContext() const
Definition: DeclBase.h:2171
ASTContext & getParentASTContext() const
Definition: DeclBase.h:2129
bool isExternCXXContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
Definition: DeclBase.cpp:1400
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
Definition: DeclBase.cpp:1334
DeclContext * getLexicalParent()
getLexicalParent - Returns the containing lexical DeclContext.
Definition: DeclBase.h:2116
bool isNamespace() const
Definition: DeclBase.h:2189
bool isTranslationUnit() const
Definition: DeclBase.h:2176
void addDecl(Decl *D)
Add the declaration D into this context.
Definition: DeclBase.cpp:1768
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition: DeclBase.h:2360
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
Definition: DeclBase.cpp:1385
bool Encloses(const DeclContext *DC) const
Determine whether this declaration context encloses the declaration context DC.
Definition: DeclBase.cpp:1404
void addHiddenDecl(Decl *D)
Add the declaration D to this context without modifying any lookup tables.
Definition: DeclBase.cpp:1742
static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls)
Definition: DeclGroup.h:68
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1265
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.cpp:550
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Definition: Expr.cpp:487
ValueDecl * getDecl()
Definition: Expr.h:1333
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Expr.cpp:555
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition: Stmt.h:1519
SourceLocation getEndLoc() const
Definition: Stmt.h:1542
const DeclGroupRef getDeclGroup() const
Definition: Stmt.h:1537
const Decl * getSingleDecl() const
Definition: Stmt.h:1534
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.h:1545
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
T * getAttr() const
Definition: DeclBase.h:576
bool hasAttrs() const
Definition: DeclBase.h:521
void addAttr(Attr *A)
Definition: DeclBase.cpp:1010
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition: DeclBase.h:596
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Definition: DeclBase.cpp:151
void markUsed(ASTContext &C)
Mark the declaration used, in the sense of odr-use.
Definition: DeclBase.cpp:564
bool isReferenced() const
Whether any declaration of this entity was referenced.
Definition: DeclBase.cpp:574
bool isCanonicalDecl() const
Whether this particular Decl is a canonical one.
Definition: DeclBase.h:973
bool isInvalidDecl() const
Definition: DeclBase.h:591
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition: DeclBase.h:562
void setAccess(AccessSpecifier AS)
Definition: DeclBase.h:505
SourceLocation getLocation() const
Definition: DeclBase.h:442
void setImplicit(bool I=true)
Definition: DeclBase.h:597
void setReferenced(bool R=true)
Definition: DeclBase.h:626
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
Definition: DeclBase.h:1038
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
Definition: DeclBase.cpp:549
DeclContext * getDeclContext()
Definition: DeclBase.h:451
AccessSpecifier getAccess() const
Definition: DeclBase.h:510
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclBase.h:434
AttrVec & getAttrs()
Definition: DeclBase.h:527
void setDeclContext(DeclContext *DC)
setDeclContext - Set both the semantic and lexical DeclContext to DC.
Definition: DeclBase.cpp:355
bool hasAttr() const
Definition: DeclBase.h:580
void setLexicalDeclContext(DeclContext *DC)
Definition: DeclBase.cpp:359
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclBase.h:967
Kind getKind() const
Definition: DeclBase.h:445
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition: DeclBase.h:430
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:1903
Recursive AST visitor that supports extension via dynamic dispatch.
RAII object that enters a new expression evaluation context.
The return type of classify().
Definition: Expr.h:330
This represents one expression.
Definition: Expr.h:110
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 isGLValue() const
Definition: Expr.h:280
@ SE_AllowSideEffects
Allow any unmodeled side effect.
Definition: Expr.h:671
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition: Expr.cpp:3102
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition: Expr.h:175
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition: Expr.h:437
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition: Expr.h:192
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
Definition: Expr.h:239
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Skip past any parentheses and lvalue casts which might surround this expression until reaching a fixe...
Definition: Expr.cpp:3114
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3097
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3085
bool containsErrors() const
Whether this expression contains subexpressions which had errors, e.g.
Definition: Expr.h:245
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3093
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition: Expr.h:277
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition: Expr.h:444
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition: Expr.h:221
bool isIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3077
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:276
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
QualType getType() const
Definition: Expr.h:142
Represents difference between two FPOptions values.
Definition: LangOptions.h:978
Represents a member of a struct/union/class.
Definition: Decl.h:3033
bool isBitField() const
Determines whether this field is a bitfield.
Definition: Decl.h:3136
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:4678
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
Definition: Decl.h:3275
static FloatingLiteral * Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L)
Definition: Expr.cpp:1081
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition: Stmt.h:2808
Stmt * getBody()
Definition: Stmt.h:2852
Represents a function declaration or definition.
Definition: Decl.h:1935
const ParmVarDecl * getParamDecl(unsigned i) const
Definition: Decl.h:2672
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:2649
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition: Decl.h:2398
bool isConsteval() const
Definition: Decl.h:2410
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition: Decl.cpp:3702
Represents a prototype with parameter type info, e.g.
Definition: Type.h:5107
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.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IfStmt - This represents an if/then/else.
Definition: Stmt.h:2165
ImaginaryLiteral - We support imaginary integer and floating point literals, like "1....
Definition: Expr.h:1717
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition: Expr.cpp:2089
ImplicitConversionSequence - Represents an implicit conversion sequence, which may be a standard conv...
Definition: Overload.h:567
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.